xref: /reactos/sdk/lib/ucrt/string/wcstok_s.cpp (revision fe11f7a2)
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