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