1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_ 18 #define INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_ 19 20 #include <string> 21 22 namespace perfetto { 23 namespace base { 24 25 // C++ version of strtok(). Splits a string without making copies or any heap 26 // allocations. Destructs the original string passed in input. 27 // Supports the special case of using \0 as a delimiter. 28 // The token returned in output are valid as long as the input string is valid. 29 class StringSplitter { 30 public: 31 // Whether an empty string (two delimiters side-to-side) is a valid token. 32 enum class EmptyTokenMode { 33 DISALLOW_EMPTY_TOKENS, 34 ALLOW_EMPTY_TOKENS, 35 36 DEFAULT = DISALLOW_EMPTY_TOKENS, 37 }; 38 39 // Can take ownership of the string if passed via std::move(), e.g.: 40 // StringSplitter(std::move(str), '\n'); 41 StringSplitter(std::string, 42 char delimiter, 43 EmptyTokenMode empty_token_mode = EmptyTokenMode::DEFAULT); 44 45 // Splits a C-string. The input string will be forcefully null-terminated (so 46 // str[size - 1] should be == '\0' or the last char will be truncated). 47 StringSplitter(char* str, 48 size_t size, 49 char delimiter, 50 EmptyTokenMode empty_token_mode = EmptyTokenMode::DEFAULT); 51 52 // Splits the current token from an outer StringSplitter instance. This is to 53 // chain splitters as follows: 54 // for (base::StringSplitter lines(x, '\n'); ss.Next();) 55 // for (base::StringSplitter words(&lines, ' '); words.Next();) 56 StringSplitter(StringSplitter*, 57 char delimiter, 58 EmptyTokenMode empty_token_mode = EmptyTokenMode::DEFAULT); 59 60 // Returns true if a token is found (in which case it will be stored in 61 // cur_token()), false if no more tokens are found. 62 bool Next(); 63 64 // Returns the current token iff last call to Next() returned true. In this 65 // case it guarantees that the returned string is always null terminated. 66 // In all other cases (before the 1st call to Next() and after Next() returns 67 // false) returns nullptr. cur_token()68 char* cur_token() { return cur_; } 69 70 // Returns the length of the current token (excluding the null terminator). cur_token_size()71 size_t cur_token_size() const { return cur_size_; } 72 73 private: 74 StringSplitter(const StringSplitter&) = delete; 75 StringSplitter& operator=(const StringSplitter&) = delete; 76 void Initialize(char* str, size_t size); 77 78 std::string str_; 79 char* cur_; 80 size_t cur_size_; 81 char* next_; 82 char* end_; // STL-style, points one past the last char. 83 const char delimiter_; 84 const EmptyTokenMode empty_token_mode_; 85 }; 86 87 } // namespace base 88 } // namespace perfetto 89 90 #endif // INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_ 91