77 const char *str =
nullptr;
82 cstring(std::nullptr_t) {}
89 cstring(
const char *
string, std::size_t length) {
90 if (
string !=
nullptr) {
91 construct_from_shared(
string, length);
98 explicit cstring(
const char *
string) {
99 if (
string !=
nullptr) {
100 construct_from_shared(
string, std::strlen(
string));
106 cstring(
const std::string &
string) {
107 construct_from_shared(
string.data(),
string.length());
112 explicit cstring(std::string_view
string) {
113 construct_from_shared(
string.data(),
string.length());
121 cstring(
const std::stringstream &stream)
122 : cstring(stream.str()) {}
128 static cstring own(
const char *
string, std::size_t length) {
129 if (
string ==
nullptr) {
134 result.construct_from_unique(
string, length);
139 template <
typename T, std::size_t N,
140 typename =
typename std::enable_if<std::is_same<T, const char>::value>::type>
141 static cstring literal(T (&
string)[N]) {
143 result.construct_from_literal(
string, N - 1 );
148 static bool is_cached(std::string_view s);
150 static cstring
get_cached(std::string_view s);
154 void construct_from_shared(
const char *
string, std::size_t length);
157 void construct_from_unique(
const char *
string, std::size_t length);
160 void construct_from_literal(
const char *
string, std::size_t length);
162 friend cstring P4::literals::operator
""_cs(
const char *str, std::size_t len);
170 template <
typename Iter>
171 cstring(Iter begin, Iter end) {
172 *
this = cstring(std::string(begin, end));
175 char get(
unsigned index)
const {
return (index < size()) ? str[index] : 0; }
176 const char *c_str()
const {
return str; }
177 explicit operator const char *()
const {
return str; }
179 std::string string()
const {
return str ? std::string(str) : std::string(
""); }
180 explicit operator std::string()
const {
return string(); }
182 std::string_view string_view()
const {
183 return str ? std::string_view(str) : std::string_view(
"");
185 operator std::string_view()
const {
return string_view(); }
188 size_t size()
const {
192 return str ? strlen(str) : 0;
194 bool isNull()
const {
return str ==
nullptr; }
195 bool isNullOrEmpty()
const {
return str ==
nullptr ? true : str[0] == 0; }
196 explicit operator bool()
const {
return str; }
199 const char *begin()
const {
return str; }
200 const char *end()
const {
return str ? str + strlen(str) : str; }
203 const char *find(
int c)
const {
return str ? strchr(str, c) :
nullptr; }
204 const char *findlast(
int c)
const {
return str ? strrchr(str, c) : str; }
207 const char *find(
const char *s)
const {
return str ? strstr(str, s) :
nullptr; }
210 bool operator==(cstring a)
const {
return str == a.str; }
211 bool operator!=(cstring a)
const {
return str != a.str; }
213 bool operator==(std::nullptr_t)
const {
return str ==
nullptr; }
214 bool operator!=(std::nullptr_t)
const {
return str !=
nullptr; }
217 bool operator==(
const char *a)
const {
return str ? a && !strcmp(str, a) : !a; }
218 bool operator!=(
const char *a)
const {
return str ? !a || !!strcmp(str, a) : !!a; }
219 bool operator<(cstring a)
const {
return *
this < a.str; }
220 bool operator<(
const char *a)
const {
return str ? a && strcmp(str, a) < 0 : !!a; }
221 bool operator<=(cstring a)
const {
return *
this <= a.str; }
222 bool operator<=(
const char *a)
const {
return str ? a && strcmp(str, a) <= 0 :
true; }
223 bool operator>(cstring a)
const {
return *
this > a.str; }
224 bool operator>(
const char *a)
const {
return str ? !a || strcmp(str, a) > 0 :
false; }
225 bool operator>=(cstring a)
const {
return *
this >= a.str; }
226 bool operator>=(
const char *a)
const {
return str ? !a || strcmp(str, a) >= 0 : !a; }
227 bool operator==(std::string_view a)
const {
return str ? a.compare(str) == 0 : a.empty(); }
228 bool operator!=(std::string_view a)
const {
return str ? a.compare(str) != 0 : !a.empty(); }
230 bool operator==(
const std::string &a)
const {
return *
this == a.c_str(); }
231 bool operator!=(
const std::string &a)
const {
return *
this != a.c_str(); }
232 bool operator<(
const std::string &a)
const {
return *
this < a.c_str(); }
233 bool operator<=(
const std::string &a)
const {
return *
this <= a.c_str(); }
234 bool operator>(
const std::string &a)
const {
return *
this > a.c_str(); }
235 bool operator>=(
const std::string &a)
const {
return *
this >= a.c_str(); }
237 bool startsWith(std::string_view
prefix)
const;
238 bool endsWith(std::string_view suffix)
const;
248 cstring operator+=(cstring a);
249 cstring operator+=(
const char *a);
250 cstring operator+=(std::string a);
251 cstring operator+=(
char a);
253 cstring before(
const char *at)
const;
254 cstring substr(
size_t start)
const {
255 return (start >= size()) ? cstring::literal(
"") : substr(start, size() - start);
257 cstring substr(
size_t start,
size_t length)
const;
258 cstring replace(
char find,
char replace)
const;
259 cstring replace(std::string_view find, std::string_view replace)
const;
260 cstring exceptLast(
size_t count) {
return substr(0, size() - count); }
263 cstring trim(
const char *ws =
" \t\r\n")
const;
266 static cstring newline;
267 static cstring empty;
270 template <
typename T>
271 static cstring to_cstring(
const T &t) {
272 std::stringstream ss;
274 return cstring(ss.str());
276 template <
typename Iterator>
277 static cstring join(Iterator begin, Iterator end,
const char *delim =
", ") {
278 std::stringstream ss;
279 for (
auto current = begin; current != end; ++current) {
280 if (begin != current) ss << delim;
283 return cstring(ss.str());
286 static cstring make_unique(
const T &inuse, cstring base,
char sep =
'.');
288 static cstring make_unique(
const T &inuse, cstring base,
int &counter,
char sep =
'.');
301 cstring
indent(
size_t amount)
const;
305 template <
typename Sink>
307 sink.Append(s.string_view());