SST 15.0
Structural Simulation Toolkit
stringize.h
1// Copyright 2009-2025 NTESS. Under the terms
2// of Contract DE-NA0003525 with NTESS, the U.S.
3// Government retains certain rights in this software.
4//
5// Copyright (c) 2009-2025, NTESS
6// All rights reserved.
7//
8// This file is part of the SST software package. For license
9// information, see the LICENSE file in the top level directory of the
10// distribution.
11
12#ifndef SST_CORE_STRINGIZE_H
13#define SST_CORE_STRINGIZE_H
14
15#include <cctype>
16#include <cinttypes>
17#include <cstdarg>
18#include <cstdio>
19#include <string>
20#include <strings.h>
21#include <vector>
22
23namespace SST {
24
25inline bool
26strcasecmp(const std::string& s1, const std::string& s2)
27{
28 return !::strcasecmp(s1.c_str(), s2.c_str());
29}
30
31inline void
32to_lower(std::string& s)
33{
34 for ( size_t i = 0; i < s.size(); i++ ) {
35 s[i] = std::tolower(s[i]);
36 }
37}
38
39inline void
40trim(std::string& s)
41{
42 auto start = s.find_first_not_of(" \t\n\r\v\f");
43 if ( start != 0 ) {
44 s.replace(s.begin(), s.begin() + (start), "");
45 }
46 auto end = s.find_last_not_of(" \t\n\r\v\f");
47 if ( end != s.size() - 1 ) {
48 s.replace(s.begin() + end + 1, s.end(), "");
49 }
50}
51
52inline void
53tokenize(std::vector<std::string>& output, const std::string& input, const std::string& delim, bool trim_ws = false)
54{
55 size_t start = 0;
56 size_t end = input.find(delim);
57
58 std::string token;
59 while ( end != std::string::npos ) {
60 token = input.substr(start, end - start);
61 if ( trim_ws ) trim(token);
62 output.push_back(token);
63 start = end + delim.length();
64 end = input.find(delim, start);
65 }
66
67 token = input.substr(start, end);
68 if ( trim_ws ) trim(token);
69 output.push_back(token);
70}
71
72struct char_delimiter
73{
74 using iter = std::string::const_iterator;
75 const std::string delim;
76 explicit char_delimiter(const std::string& delim = " \t\v\f\n\r") :
77 delim(delim)
78 {}
79
80 /**
81 * @return pair<iter, iter> = <tok_end, next_tok>
82 */
83 void operator()(iter& first, iter last, std::string& token)
84 {
85 token.clear();
86
87 /* Skip any leading separators */
88 while ( first != last && delim.find(*first) != std::string::npos )
89 ++first;
90
91 while ( first != last && delim.find(*first) == std::string::npos )
92 token += *first++;
93 }
94};
95
96struct escaped_list_separator
97{
98 using iter = std::string::const_iterator;
99 std::string e, q, s;
100
101 escaped_list_separator(
102 const std::string& esc = "\\", const std::string& sep = ",", const std::string& quote = "\"") :
103 e(esc),
104 q(quote),
105 s(sep)
106 {}
107
108 /**
109 * Sets pair<iter, iter> = <tok_end, next_tok>
110 */
111 void operator()(iter& first, iter last, std::string& token)
112 {
113 token.clear();
114
115 bool inside_quotes = false;
116 bool in_escape = false;
117 while ( first != last ) {
118 char c = *first++;
119
120 if ( in_escape ) {
121 token += c;
122 in_escape = false;
123 }
124 else if ( s.find(c) != std::string::npos && !inside_quotes ) {
125 /* Separator found */
126 break;
127 }
128 else if ( q.find(c) != std::string::npos ) {
129 inside_quotes = !inside_quotes;
130 }
131 else if ( e.find(c) != std::string::npos ) {
132 in_escape = true;
133 }
134 else {
135 token += c;
136 }
137 }
138 }
139};
140
141template <typename TokenizerFunc = char_delimiter>
142class Tokenizer
143{
144
145 template <typename Func>
146 struct token_iter
147 {
148 Func& f;
149 std::string::const_iterator first;
150 std::string::const_iterator last;
151 std::string token;
152
153 public:
154 explicit token_iter(Func& f_, std::string::const_iterator& first_, std::string::const_iterator& last_) :
155 f(f_),
156 first(first_),
157 last(last_)
158 {
159 f(first, last, token);
160 }
161 token_iter& operator++()
162 {
163 f(first, last, token);
164 return *this;
165 }
166 token_iter operator++(int)
167 {
168 token_iter retval = *this;
169 ++(*this);
170 return retval;
171 }
172 bool operator==(token_iter other) const
173 {
174 return (first == other.first) && (last == other.last) && (token == other.token);
175 }
176 bool operator!=(token_iter other) const { return !(*this == other); }
177 const std::string& operator*() const { return token; }
178 const std::string& operator->() const { return token; }
179
180 using difference_type = std::ptrdiff_t;
181 using value_type = std::string;
182 using pointer = const std::string*;
183 using reference = const std::string&;
184 using iterator_category = std::input_iterator_tag;
185 };
186
187 using iter = token_iter<TokenizerFunc>;
188
189public:
190 using iterator = iter;
191 using const_iterator = iter;
192 using value_type = std::string;
193
194 iter begin() { return iter(f, first, last); }
195 iter end() { return iter(f, last, last); }
196
197 Tokenizer(const std::string& s, const TokenizerFunc& f = TokenizerFunc()) :
198 first(s.begin()),
199 last(s.end()),
200 f(f)
201 {}
202
203private:
204 std::string::const_iterator first, last;
205 TokenizerFunc f;
206};
207
208
209/**
210 Creates a string using a vprintf like function call. This function
211 uses a dynamically allocated char array of size max_length to
212 create the buffer to intialize the string.
213
214 @param max_length Maximum length of string. Anything past
215 max_length will be truncated (null terminator is included in the
216 length)
217
218 @param format printf-like format string
219
220 @param args va_list containing variable length argument list
221
222 @return formatted string, potentially truncated at length max_length - 1
223 */
224std::string vformat_string(size_t max_length, const char* format, va_list args) __attribute__((format(printf, 2, 0)));
225
226/**
227 Creates a string using a printf like function call. This function
228 uses a compile time allocated char array of length 256 to create
229 the buffer to intialize the string. If this is not long enough, it
230 will dynamically allocate an array that is just big enough to
231 create the buffer to initialize the string. No truncation will
232 occur.
233
234 @param format printf-like format string
235
236 @param args va_list containing variable length argument list
237
238 @return formatted string
239 */
240std::string vformat_string(const char* format, va_list args) __attribute__((format(printf, 1, 0)));
241
242/**
243 Creates a string using a printf like function call. This function
244 uses a dynamically allocated char array of size max_length to
245 create the buffer to intialize the string.
246
247 @param max_length Maximum length of string. Anything past
248 max_length will be truncated (null terminator is included in the
249 length)
250
251 @param format printf-like format string
252
253 @param ... arguments for format string
254
255 @return formatted string, potentially truncated at length max_length - 1
256 */
257std::string format_string(size_t max_length, const char* format, ...) __attribute__((format(printf, 2, 3)));
258
259/**
260 Creates a string using a printf like function call. This function
261 uses a compile time allocated char array of length 256 to create
262 the buffer to intialize the string. If this is not long enough, it
263 will dynamically allocate an array that is just big enough to
264 create the buffer to initialize the string. No truncation will
265 occur.
266
267 @param format printf-like format string
268
269 @param ... arguments for format string
270
271 @return formatted string
272 */
273std::string format_string(const char* format, ...) __attribute__((format(printf, 1, 2)));
274
275} // namespace SST
276
277#endif // SST_CORE_STRINGIZE_H
void operator()(iter &first, iter last, std::string &token)
Definition stringize.h:83
void operator()(iter &first, iter last, std::string &token)
Sets pair<iter, iter> = <tok_end, next_tok>
Definition stringize.h:111