1 // 2 // wcstok_s.cpp 3 // 4 // Copyright (c) Microsoft Corporation. All rights reserved. 5 // 6 // Defines wcstok_s(), which tokenizes a string via repeated calls. See strtok() 7 // for more details. This more secure function uses a caller-provided context 8 // instead of the thread-local tokenization state. 9 // 10 #include <corecrt_internal_securecrt.h> 11 #include <string.h> 12 13 14 15 // This common implementation is used by both strtok() and strtok_s() 16 extern "C" wchar_t* __cdecl __acrt_wcstok_s_novalidation( 17 _Inout_opt_z_ wchar_t* string, 18 _In_z_ wchar_t const* control, 19 _Inout_ _Deref_prepost_opt_z_ wchar_t** context 20 ) 21 { 22 // If string is null, set the iterator to the saved pointer (i.e., continue 23 // breaking tokens out of the string from the last strtok call): 24 wchar_t* string_it = string != nullptr 25 ? string 26 : *context; 27 28 29 // Find beginning of token (skip over leading delimiters). Note that 30 // there is no token iff this loop sets string to point to the terminal 31 // null (*string == '\0') 32 while (*string_it) 33 { 34 wchar_t const* control_it = control; 35 for (; *control_it && *control_it != *string_it; ++control_it) 36 { 37 } 38 39 if (!*control_it) 40 break; 41 42 ++string_it; 43 } 44 45 wchar_t* const token_first = string_it; 46 47 // Find the end of the token. If it is not the end of the string, put a 48 // null character there: 49 for (; *string_it; ++string_it) 50 { 51 wchar_t const* control_it = control; 52 for (; *control_it && *control_it != *string_it; ++control_it) 53 { 54 } 55 56 if (*control_it) 57 { 58 *string_it++ = '\0'; 59 break; 60 } 61 } 62 63 // Update the saved pointer: 64 *context = string_it; 65 66 // Determine if a token has been found. 67 return string_it != token_first ? token_first : nullptr; 68 } 69 70 71 72 extern "C" wchar_t* __cdecl wcstok_s( 73 wchar_t* const string, 74 wchar_t const* const control, 75 wchar_t** const context 76 ) 77 { 78 _VALIDATE_POINTER_ERROR_RETURN(context, EINVAL, nullptr); 79 _VALIDATE_POINTER_ERROR_RETURN(control, EINVAL, nullptr); 80 _VALIDATE_CONDITION_ERROR_RETURN(string != nullptr || *context != nullptr, EINVAL, nullptr); 81 82 return __acrt_wcstok_s_novalidation(string, control, context); 83 } 84