| // |
| // Copyright (c) Microsoft. All rights reserved. |
| // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
| // |
| |
| /*++ |
| |
| |
| |
| Module Name: |
| |
| wchartls.c |
| |
| Abstract: |
| |
| Implementation of wide char string functions that depend on per-thread data |
| |
| |
| |
| --*/ |
| |
| #include "pal/palinternal.h" |
| #include "pal/thread.hpp" |
| #include "pal/dbgmsg.h" |
| #include "pal/unicode_data.h" |
| |
| using namespace CorUnix; |
| |
| |
| SET_DEFAULT_DEBUG_CHANNEL(CRT); |
| |
| /*++ |
| Function: |
| PAL_wcstok |
| |
| Finds the next token in a wide character string. |
| |
| Return value: |
| |
| A pointer to the next token found in strToken. Returns NULL when no more |
| tokens are found. Each call modifies strToken by substituting a NULL |
| character for each delimiter that is encountered. |
| |
| Parameters: |
| strToken String containing token(s) |
| strDelimit Set of delimiter characters |
| |
| --*/ |
| WCHAR * |
| __cdecl |
| PAL_wcstok(WCHAR *strToken, const WCHAR *strDelimit) |
| { |
| CPalThread *pThread = NULL; |
| WCHAR *retval = NULL; |
| WCHAR *delim_ptr; |
| WCHAR *next_context; /* string to save in TLS for future calls */ |
| |
| PERF_ENTRY(wcstok); |
| ENTRY("PAL_wcstok (strToken=%p (%S), strDelimit=%p (%S))\n", |
| strToken?strToken:W16_NULLSTRING, |
| strToken?strToken:W16_NULLSTRING, |
| strDelimit?strDelimit:W16_NULLSTRING, |
| strDelimit?strDelimit:W16_NULLSTRING); |
| |
| /* Get the per-thread buffer from the thread structure. */ |
| pThread = InternalGetCurrentThread(); |
| |
| if(NULL == strDelimit) |
| { |
| ERROR("delimiter string is NULL\n"); |
| goto done; |
| } |
| |
| /* get token string from TLS if none is provided */ |
| if(NULL == strToken) |
| { |
| TRACE("wcstok() called with NULL string, using previous string\n"); |
| strToken = pThread->crtInfo.wcstokContext; |
| if(NULL == strToken) |
| { |
| ERROR("wcstok called with NULL string without a previous call\n"); |
| goto done; |
| } |
| } |
| |
| /* first, skip all leading delimiters */ |
| while ((*strToken != '\0') && (PAL_wcschr(strDelimit,*strToken))) |
| { |
| strToken++; |
| } |
| |
| /* if there were only delimiters, there's no string */ |
| if('\0' == strToken[0]) |
| { |
| TRACE("end of string already reached, returning NULL\n"); |
| goto done; |
| } |
| |
| /* we're now at the beginning of the token; look for the first delimiter */ |
| delim_ptr = PAL_wcspbrk(strToken,strDelimit); |
| if(NULL == delim_ptr) |
| { |
| TRACE("no delimiters found, this is the last token\n"); |
| /* place the next context at the end of the string, so that subsequent |
| calls will return NULL */ |
| next_context = strToken+PAL_wcslen(strToken); |
| retval = strToken; |
| } |
| else |
| { |
| /* null-terminate current token */ |
| *delim_ptr=0; |
| |
| /* place the next context right after the delimiter */ |
| next_context = delim_ptr+1; |
| retval = strToken; |
| |
| TRACE("found delimiter; next token will be %p\n",next_context); |
| } |
| |
| pThread->crtInfo.wcstokContext = next_context; |
| |
| done: |
| LOGEXIT("PAL_wcstok() returns %p (%S)\n", retval?retval:W16_NULLSTRING, retval?retval:W16_NULLSTRING); |
| PERF_EXIT(wcstok); |
| return(retval); |
| } |
| |