1 //===-- String utils --------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LIBC_SRC_STRING_STRING_UTILS_H 10 #define LIBC_SRC_STRING_STRING_UTILS_H 11 12 #include "utils/CPP/Bitset.h" 13 #include <stddef.h> // size_t 14 15 namespace __llvm_libc { 16 namespace internal { 17 18 // Returns the maximum length span that contains only characters not found in 19 // 'segment'. If no characters are found, returns the length of 'src'. 20 static inline size_t complementary_span(const char *src, const char *segment) { 21 const char *initial = src; 22 cpp::Bitset<256> bitset; 23 24 for (; *segment; ++segment) 25 bitset.set(*segment); 26 for (; *src && !bitset.test(*src); ++src) 27 ; 28 return src - initial; 29 } 30 31 // Given the similarities between strtok and strtok_r, we can implement both 32 // using a utility function. On the first call, 'src' is scanned for the 33 // first character not found in 'delimiter_string'. Once found, it scans until 34 // the first character in the 'delimiter_string' or the null terminator is 35 // found. We define this span as a token. The end of the token is appended with 36 // a null terminator, and the token is returned. The point where the last token 37 // is found is then stored within 'context' for subsequent calls. Subsequent 38 // calls will use 'context' when a nullptr is passed in for 'src'. Once the null 39 // terminating character is reached, returns a nullptr. 40 static inline char *string_token(char *__restrict src, 41 const char *__restrict delimiter_string, 42 char **__restrict saveptr) { 43 cpp::Bitset<256> delimiter_set; 44 for (; *delimiter_string; ++delimiter_string) 45 delimiter_set.set(*delimiter_string); 46 47 src = src ? src : *saveptr; 48 for (; *src && delimiter_set.test(*src); ++src) 49 ; 50 if (!*src) { 51 *saveptr = src; 52 return nullptr; 53 } 54 char *token = src; 55 for (; *src && !delimiter_set.test(*src); ++src) 56 ; 57 if (*src) { 58 *src = '\0'; 59 ++src; 60 } 61 *saveptr = src; 62 return token; 63 } 64 65 } // namespace internal 66 } // namespace __llvm_libc 67 68 #endif // LIBC_SRC_STRING_STRING_UTILS_H 69