1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*++ |
6 | |
7 | |
8 | |
9 | Module Name: |
10 | |
11 | wchartls.c |
12 | |
13 | Abstract: |
14 | |
15 | Implementation of wide char string functions that depend on per-thread data |
16 | |
17 | |
18 | |
19 | --*/ |
20 | |
21 | #include "pal/palinternal.h" |
22 | #include "pal/thread.hpp" |
23 | #include "pal/dbgmsg.h" |
24 | #include "pal/unicode_data.h" |
25 | |
26 | using namespace CorUnix; |
27 | |
28 | |
29 | SET_DEFAULT_DEBUG_CHANNEL(CRT); |
30 | |
31 | /*++ |
32 | Function: |
33 | PAL_wcstok |
34 | |
35 | Finds the next token in a wide character string. |
36 | |
37 | Return value: |
38 | |
39 | A pointer to the next token found in strToken. Returns NULL when no more |
40 | tokens are found. Each call modifies strToken by substituting a NULL |
41 | character for each delimiter that is encountered. |
42 | |
43 | Parameters: |
44 | strToken String containing token(s) |
45 | strDelimit Set of delimiter characters |
46 | |
47 | --*/ |
48 | WCHAR * |
49 | __cdecl |
50 | PAL_wcstok(WCHAR *strToken, const WCHAR *strDelimit) |
51 | { |
52 | CPalThread *pThread = NULL; |
53 | WCHAR *retval = NULL; |
54 | WCHAR *delim_ptr; |
55 | WCHAR *next_context; /* string to save in TLS for future calls */ |
56 | |
57 | PERF_ENTRY(wcstok); |
58 | ENTRY("PAL_wcstok (strToken=%p (%S), strDelimit=%p (%S))\n" , |
59 | strToken?strToken:W16_NULLSTRING, |
60 | strToken?strToken:W16_NULLSTRING, |
61 | strDelimit?strDelimit:W16_NULLSTRING, |
62 | strDelimit?strDelimit:W16_NULLSTRING); |
63 | |
64 | /* Get the per-thread buffer from the thread structure. */ |
65 | pThread = InternalGetCurrentThread(); |
66 | |
67 | if(NULL == strDelimit) |
68 | { |
69 | ERROR("delimiter string is NULL\n" ); |
70 | goto done; |
71 | } |
72 | |
73 | /* get token string from TLS if none is provided */ |
74 | if(NULL == strToken) |
75 | { |
76 | TRACE("wcstok() called with NULL string, using previous string\n" ); |
77 | strToken = pThread->crtInfo.wcstokContext; |
78 | if(NULL == strToken) |
79 | { |
80 | ERROR("wcstok called with NULL string without a previous call\n" ); |
81 | goto done; |
82 | } |
83 | } |
84 | |
85 | /* first, skip all leading delimiters */ |
86 | while ((*strToken != '\0') && (PAL_wcschr(strDelimit,*strToken))) |
87 | { |
88 | strToken++; |
89 | } |
90 | |
91 | /* if there were only delimiters, there's no string */ |
92 | if('\0' == strToken[0]) |
93 | { |
94 | TRACE("end of string already reached, returning NULL\n" ); |
95 | goto done; |
96 | } |
97 | |
98 | /* we're now at the beginning of the token; look for the first delimiter */ |
99 | delim_ptr = PAL_wcspbrk(strToken,strDelimit); |
100 | if(NULL == delim_ptr) |
101 | { |
102 | TRACE("no delimiters found, this is the last token\n" ); |
103 | /* place the next context at the end of the string, so that subsequent |
104 | calls will return NULL */ |
105 | next_context = strToken+PAL_wcslen(strToken); |
106 | retval = strToken; |
107 | } |
108 | else |
109 | { |
110 | /* null-terminate current token */ |
111 | *delim_ptr=0; |
112 | |
113 | /* place the next context right after the delimiter */ |
114 | next_context = delim_ptr+1; |
115 | retval = strToken; |
116 | |
117 | TRACE("found delimiter; next token will be %p\n" ,next_context); |
118 | } |
119 | |
120 | pThread->crtInfo.wcstokContext = next_context; |
121 | |
122 | done: |
123 | LOGEXIT("PAL_wcstok() returns %p (%S)\n" , retval?retval:W16_NULLSTRING, retval?retval:W16_NULLSTRING); |
124 | PERF_EXIT(wcstok); |
125 | return(retval); |
126 | } |
127 | |
128 | |