86 const char *str =
nullptr;
91 cstring(std::nullptr_t) {}
98 cstring(
const char *
string, std::size_t length) {
99 if (
string !=
nullptr) {
100 construct_from_shared(
string, length);
107 explicit cstring(
const char *
string) {
108 if (
string !=
nullptr) {
109 construct_from_shared(
string, std::strlen(
string));
115 cstring(
const std::string &
string) {
116 construct_from_shared(
string.data(),
string.length());
121 explicit cstring(std::string_view
string) {
122 construct_from_shared(
string.data(),
string.length());
130 cstring(
const std::stringstream &stream)
131 : cstring(stream.str()) {}
137 static cstring own(
const char *
string, std::size_t length) {
138 if (
string ==
nullptr) {
143 result.construct_from_unique(
string, length);
148 template <
typename T, std::size_t N,
149 typename =
typename std::enable_if<std::is_same<T, const char>::value>::type>
150 static cstring literal(T (&
string)[N]) {
152 result.construct_from_literal(
string, N - 1 );
157 static bool is_cached(std::string_view s);
159 static cstring
get_cached(std::string_view s);
163 void construct_from_shared(
const char *
string, std::size_t length);
166 void construct_from_unique(
const char *
string, std::size_t length);
169 void construct_from_literal(
const char *
string, std::size_t length);
171 friend cstring P4::literals::operator
""_cs(
const char *str, std::size_t len);
179 template <
typename Iter>
180 cstring(Iter begin, Iter end) {
181 *
this = cstring(std::string(begin, end));
184 char get(
unsigned index)
const {
return (index < size()) ? str[index] : 0; }
185 const char *c_str()
const {
return str; }
186 explicit operator const char *()
const {
return str; }
188 std::string string()
const {
return str ? std::string(str) : std::string(
""); }
189 explicit operator std::string()
const {
return string(); }
191 std::string_view string_view()
const {
192 return str ? std::string_view(str) : std::string_view(
"");
194 operator std::string_view()
const {
return string_view(); }
197 size_t size()
const {
201 return str ? strlen(str) : 0;
203 bool isNull()
const {
return str ==
nullptr; }
204 bool isNullOrEmpty()
const {
return str ==
nullptr ? true : str[0] == 0; }
205 explicit operator bool()
const {
return str; }
208 const char *begin()
const {
return str; }
209 const char *end()
const {
return str ? str + strlen(str) : str; }
212 const char *find(
int c)
const {
return str ? strchr(str, c) :
nullptr; }
213 const char *findlast(
int c)
const {
return str ? strrchr(str, c) : str; }
216 const char *find(
const char *s)
const {
return str ? strstr(str, s) :
nullptr; }
219 bool operator==(cstring a)
const {
return str == a.str; }
220 bool operator!=(cstring a)
const {
return str != a.str; }
222 bool operator==(std::nullptr_t)
const {
return str ==
nullptr; }
223 bool operator!=(std::nullptr_t)
const {
return str !=
nullptr; }
226 bool operator==(
const char *a)
const {
return str ? a && !strcmp(str, a) : !a; }
227 bool operator!=(
const char *a)
const {
return str ? !a || !!strcmp(str, a) : !!a; }
228 bool operator<(cstring a)
const {
return *
this < a.str; }
229 bool operator<(
const char *a)
const {
return str ? a && strcmp(str, a) < 0 : !!a; }
230 bool operator<=(cstring a)
const {
return *
this <= a.str; }
231 bool operator<=(
const char *a)
const {
return str ? a && strcmp(str, a) <= 0 :
true; }
232 bool operator>(cstring a)
const {
return *
this > a.str; }
233 bool operator>(
const char *a)
const {
return str ? !a || strcmp(str, a) > 0 :
false; }
234 bool operator>=(cstring a)
const {
return *
this >= a.str; }
235 bool operator>=(
const char *a)
const {
return str ? !a || strcmp(str, a) >= 0 : !a; }
236 bool operator==(std::string_view a)
const {
return str ? a.compare(str) == 0 : a.empty(); }
237 bool operator!=(std::string_view a)
const {
return str ? a.compare(str) != 0 : !a.empty(); }
239 bool operator==(
const std::string &a)
const {
return *
this == a.c_str(); }
240 bool operator!=(
const std::string &a)
const {
return *
this != a.c_str(); }
241 bool operator<(
const std::string &a)
const {
return *
this < a.c_str(); }
242 bool operator<=(
const std::string &a)
const {
return *
this <= a.c_str(); }
243 bool operator>(
const std::string &a)
const {
return *
this > a.c_str(); }
244 bool operator>=(
const std::string &a)
const {
return *
this >= a.c_str(); }
246 bool startsWith(std::string_view prefix)
const;
247 bool endsWith(std::string_view suffix)
const;
257 cstring operator+=(cstring a);
258 cstring operator+=(
const char *a);
259 cstring operator+=(std::string a);
260 cstring operator+=(
char a);
262 cstring before(
const char *at)
const;
263 cstring substr(
size_t start)
const {
264 return (start >= size()) ? cstring::literal(
"") : substr(start, size() - start);
266 cstring substr(
size_t start,
size_t length)
const;
267 cstring replace(
char find,
char replace)
const;
268 cstring replace(std::string_view find, std::string_view replace)
const;
269 cstring exceptLast(
size_t count) {
return substr(0, size() - count); }
272 cstring trim(
const char *ws =
" \t\r\n")
const;
275 static cstring newline;
276 static cstring empty;
279 template <
typename T>
280 static cstring to_cstring(
const T &t) {
281 std::stringstream ss;
283 return cstring(ss.str());
285 template <
typename Iterator>
286 static cstring join(Iterator begin, Iterator end,
const char *delim =
", ") {
287 std::stringstream ss;
288 for (
auto current = begin; current != end; ++current) {
289 if (begin != current) ss << delim;
292 return cstring(ss.str());
295 static cstring make_unique(
const T &inuse, cstring base,
char sep =
'.');
297 static cstring make_unique(
const T &inuse, cstring base,
int &counter,
char sep =
'.');
310 cstring
indent(
size_t amount)
const;
314 template <
typename Sink>
316 sink.Append(s.string_view());