1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2014-2020. 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 * Author: lishunda
13 * Create: 2014-02-25
14 */
15
16 #include "securecutil.h"
17
SecIsInDelimit(char ch,const char * strDelimit)18 SECUREC_INLINE int SecIsInDelimit(char ch, const char *strDelimit)
19 {
20 const char *ctl = strDelimit;
21 while (*ctl != '\0' && *ctl != ch) {
22 ++ctl;
23 }
24 return (int)(*ctl != '\0');
25 }
26
27 /*
28 * Find beginning of token (skip over leading delimiters).
29 * Note that there is no token if this loop sets string to point to the terminal null.
30 */
SecFindBegin(char * strToken,const char * strDelimit)31 SECUREC_INLINE char *SecFindBegin(char *strToken, const char *strDelimit)
32 {
33 char *token = strToken;
34 while (*token != '\0') {
35 if (SecIsInDelimit(*token, strDelimit) != 0) {
36 ++token;
37 continue;
38 }
39 /* Don't find any delimiter in string header, break the loop */
40 break;
41 }
42 return token;
43 }
44
45 /*
46 * Find rest of token
47 */
SecFindRest(char * strToken,const char * strDelimit)48 SECUREC_INLINE char *SecFindRest(char *strToken, const char *strDelimit)
49 {
50 /* Find the rest of the token. If it is not the end of the string, put a null there */
51 char *token = strToken;
52 while (*token != '\0') {
53 if (SecIsInDelimit(*token, strDelimit) != 0) {
54 /* Find a delimiter, set string termintor */
55 *token = '\0';
56 ++token;
57 break;
58 }
59 ++token;
60 }
61 return token;
62 }
63
64 /*
65 * Find the final position pointer
66 */
SecUpdateToken(char * strToken,const char * strDelimit,char ** context)67 SECUREC_INLINE char *SecUpdateToken(char *strToken, const char *strDelimit, char **context)
68 {
69 /* Point to updated position. Record string position for next search in the context */
70 *context = SecFindRest(strToken, strDelimit);
71 /* Determine if a token has been found. */
72 if (*context == strToken) {
73 return NULL;
74 }
75 return strToken;
76 }
77
78 /*
79 * <FUNCTION DESCRIPTION>
80 * The strtok_s function parses a string into a sequence of strToken,
81 * replace all characters in strToken string that match to strDelimit set with 0.
82 * On the first call to strtok_s the string to be parsed should be specified in strToken.
83 * In each subsequent call that should parse the same string, strToken should be NULL
84 * <INPUT PARAMETERS>
85 * strToken String containing token or tokens.
86 * strDelimit Set of delimiter characters.
87 * context Used to store position information between calls
88 * to strtok_s
89 * <OUTPUT PARAMETERS>
90 * context is updated
91 * <RETURN VALUE>
92 * On the first call returns the address of the first non \0 character, otherwise NULL is returned.
93 * In subsequent calls, the strtoken is set to NULL, and the context set is the same as the previous call,
94 * return NULL if the *context string length is equal 0, otherwise return *context.
95 */
strtok_s(char * strToken,const char * strDelimit,char ** context)96 char *strtok_s(char *strToken, const char *strDelimit, char **context)
97 {
98 char *orgToken = strToken;
99 /* Validate delimiter and string context */
100 if (context == NULL || strDelimit == NULL) {
101 return NULL;
102 }
103 /* Valid input string and string pointer from where to search */
104 if (orgToken == NULL && *context == NULL) {
105 return NULL;
106 }
107 /* If string is null, continue searching from previous string position stored in context */
108 if (orgToken == NULL) {
109 orgToken = *context;
110 }
111 orgToken = SecFindBegin(orgToken, strDelimit);
112 return SecUpdateToken(orgToken, strDelimit, context);
113 }
114 #if SECUREC_IN_KERNEL
115 EXPORT_SYMBOL(strtok_s);
116 #endif
117
118