Reactos
at master 83 lines 2.6 kB view raw
1// 2// strtok_s.cpp 3// 4// Copyright (c) Microsoft Corporation. All rights reserved. 5// 6// Defines strtok_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 <string.h> 11#include <corecrt_internal_securecrt.h> 12 13 14 15// This common implementation is used by both strtok() and strtok_s() 16extern "C" char* __cdecl __acrt_strtok_s_novalidation( 17 _Inout_opt_z_ char* string, 18 _In_z_ char const* control, 19 _Inout_ _Deref_prepost_opt_z_ char** context 20 ) 21{ 22 // Clear control map. The control characters are stored in a bitmap, one 23 // bit per character. The null character is always a control character. 24 unsigned char map[32]; 25 for (int count = 0; count < 32; count++) 26 { 27 map[count] = 0; 28 } 29 30 // Set bits in delimiter table 31 unsigned char const* unsigned_control = reinterpret_cast<unsigned char const*>(control); 32 do 33 { 34 map[*unsigned_control >> 3] |= (1 << (*unsigned_control & 7)); 35 } 36 while (*unsigned_control++); 37 38 // If string is null, set the iterator to the saved pointer (i.e., continue 39 // breaking tokens out of the string from the last strtok call): 40 char* it = string != nullptr 41 ? string 42 : *context; 43 44 unsigned char*& unsigned_it = reinterpret_cast<unsigned char*&>(it); 45 46 // Find beginning of token (skip over leading delimiters). Note that 47 // there is no token iff this loop sets it to point to the terminal 48 // null (*it == '\0') 49 while ((map[*unsigned_it >> 3] & (1 << (*unsigned_it & 7))) && *it) 50 { 51 ++it; 52 } 53 54 char* const token_first = it; 55 56 // Find the end of the token. If it is not the end of the string, 57 // put a null there. 58 for (; *it; ++it) 59 { 60 if (map[*unsigned_it >> 3] & (1 << (*unsigned_it & 7))) 61 { 62 *it++ = '\0'; 63 break; 64 } 65 } 66 67 // Update the saved pointer: 68 *context = it; 69 70 // Determine if a token has been found. 71 return it != token_first ? token_first : nullptr; 72} 73 74 75 76extern "C" char* __cdecl strtok_s(char* string, char const* control, char** context) 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_strtok_s_novalidation(string, control, context); 83}