• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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