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
9Module Name:
10
11 wchartls.c
12
13Abstract:
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
26using namespace CorUnix;
27
28
29SET_DEFAULT_DEBUG_CHANNEL(CRT);
30
31/*++
32Function:
33 PAL_wcstok
34
35Finds the next token in a wide character string.
36
37Return value:
38
39A pointer to the next token found in strToken. Returns NULL when no more
40tokens are found. Each call modifies strToken by substituting a NULL
41character for each delimiter that is encountered.
42
43Parameters:
44strToken String containing token(s)
45strDelimit Set of delimiter characters
46
47--*/
48WCHAR *
49__cdecl
50PAL_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
122done:
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