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 17SECUREC_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 */ 30SECUREC_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 */ 47SECUREC_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 */ 66SECUREC_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 */ 95char *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 114EXPORT_SYMBOL(strtok_s); 115#endif 116 117