1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2014-2021. All rights reserved.
3 * Licensed under Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 * Description: strtok_s function
12 * Create: 2014-02-25
13 */
14
15 #include "securecutil.h"
16
SecIsInDelimit(char ch,const char * strDelimit)17 SECUREC_INLINE int SecIsInDelimit(char ch, const char *strDelimit)
18 {
19 const char *ctl = strDelimit;
20 while (*ctl != '\0' && *ctl != ch) {
21 ++ctl;
22 }
23 return (int)(*ctl != '\0');
24 }
25
26 /*
27 * Find beginning of token (skip over leading delimiters).
28 * Note that there is no token if this loop sets string to point to the terminal null.
29 */
SecFindBegin(char * strToken,const char * strDelimit)30 SECUREC_INLINE char *SecFindBegin(char *strToken, const char *strDelimit)
31 {
32 char *token = strToken;
33 while (*token != '\0') {
34 if (SecIsInDelimit(*token, strDelimit) != 0) {
35 ++token;
36 continue;
37 }
38 /* Don't find any delimiter in string header, break the loop */
39 break;
40 }
41 return token;
42 }
43
44 /*
45 * Find rest of token
46 */
SecFindRest(char * strToken,const char * strDelimit)47 SECUREC_INLINE char *SecFindRest(char *strToken, const char *strDelimit)
48 {
49 /* Find the rest of the token. If it is not the end of the string, put a null there */
50 char *token = strToken;
51 while (*token != '\0') {
52 if (SecIsInDelimit(*token, strDelimit) != 0) {
53 /* Find a delimiter, set string terminator */
54 *token = '\0';
55 ++token;
56 break;
57 }
58 ++token;
59 }
60 return token;
61 }
62
63 /*
64 * Find the final position pointer
65 */
SecUpdateToken(char * strToken,const char * strDelimit,char ** context)66 SECUREC_INLINE char *SecUpdateToken(char *strToken, const char *strDelimit, char **context)
67 {
68 /* Point to updated position. Record string position for next search in the context */
69 *context = SecFindRest(strToken, strDelimit);
70 /* Determine if a token has been found. */
71 if (*context == strToken) {
72 return NULL;
73 }
74 return strToken;
75 }
76
77 /*
78 * <FUNCTION DESCRIPTION>
79 * The strtok_s function parses a string into a sequence of strToken,
80 * replace all characters in strToken string that match to strDelimit set with 0.
81 * On the first call to strtok_s the string to be parsed should be specified in strToken.
82 * In each subsequent call that should parse the same string, strToken should be NULL
83 * <INPUT PARAMETERS>
84 * strToken String containing token or tokens.
85 * strDelimit Set of delimiter characters.
86 * context Used to store position information between calls
87 * to strtok_s
88 * <OUTPUT PARAMETERS>
89 * context is updated
90 * <RETURN VALUE>
91 * On the first call returns the address of the first non \0 character, otherwise NULL is returned.
92 * In subsequent calls, the strtoken is set to NULL, and the context set is the same as the previous call,
93 * return NULL if the *context string length is equal 0, otherwise return *context.
94 */
strtok_s(char * strToken,const char * strDelimit,char ** context)95 char *strtok_s(char *strToken, const char *strDelimit, char **context)
96 {
97 char *orgToken = strToken;
98 /* Validate delimiter and string context */
99 if (context == NULL || strDelimit == NULL) {
100 return NULL;
101 }
102 /* Valid input string and string pointer from where to search */
103 if (orgToken == NULL && *context == NULL) {
104 return NULL;
105 }
106 /* If string is null, continue searching from previous string position stored in context */
107 if (orgToken == NULL) {
108 orgToken = *context;
109 }
110 orgToken = SecFindBegin(orgToken, strDelimit);
111 return SecUpdateToken(orgToken, strDelimit, context);
112 }
113 #if SECUREC_EXPORT_KERNEL_SYMBOL
114 EXPORT_SYMBOL(strtok_s);
115 #endif
116
117