24 #ifndef FOLLY_STRING_H_ 25 #error This file may only be included from String.h 38 template <
class String>
42 out.reserve(out.size() + str.
size());
48 while (p != str.
end()) {
50 unsigned char v =
static_cast<unsigned char>(
c);
54 }
else if (e ==
'O') {
55 out.append(&*last,
size_t(p - last));
56 esc[1] =
'0' + ((v >> 6) & 7);
57 esc[2] =
'0' + ((v >> 3) & 7);
58 esc[3] =
'0' + (v & 7);
63 out.append(&*last,
size_t(p - last));
70 out.append(&*last,
size_t(p - last));
82 extern const std::array<unsigned char, 256>
hexTable;
85 template <
class String>
87 out.reserve(out.size() + str.
size());
92 while (p != str.
end()) {
98 out.append(&*last, p - last);
100 if (p == str.
end()) {
102 throw std::invalid_argument(
"incomplete escape sequence");
110 unsigned char val = 0;
111 for (
int i = 0;
i < 3 && p != str.
end() && *p >=
'0' && *p <=
'7';
118 }
else if (e ==
'X') {
120 if (p == str.
end()) {
122 throw std::invalid_argument(
"incomplete hex escape sequence");
128 unsigned char val = 0;
130 for (; (p != str.
end() &&
138 }
else if (e ==
'I') {
140 throw std::invalid_argument(
"invalid escape sequence");
152 out.append(&*last, p - last);
165 template <
class String>
167 static const char hexValues[] =
"0123456789abcdef";
171 out.reserve(out.size() + str.
size() + 3 * (str.
size() / 4));
172 auto p = str.
begin();
176 unsigned char minEncode =
static_cast<unsigned char>(
mode);
177 while (p != str.
end()) {
179 unsigned char v =
static_cast<unsigned char>(
c);
181 if (
LIKELY(discriminator <= minEncode)) {
184 out.append(&*last,
size_t(p - last));
189 out.append(&*last,
size_t(p - last));
190 esc[1] = hexValues[v >> 4];
191 esc[2] = hexValues[v & 0x0f];
197 out.append(&*last,
size_t(p - last));
200 template <
class String>
202 out.reserve(out.size() + str.
size());
203 auto p = str.
begin();
207 while (p != str.
end()) {
212 throw std::invalid_argument(
"incomplete percent encode sequence");
216 if (
UNLIKELY(h1 == 16 || h2 == 16)) {
217 throw std::invalid_argument(
"invalid percent encode sequence");
219 out.append(&*last,
size_t(p - last));
220 out.push_back((h1 << 4) | h2);
227 out.append(&*last,
size_t(p - last));
240 out.append(&*last,
size_t(p - last));
259 return !std::memcmp(s, sp.
start(), sp.
size());
283 template <
class OutStringT,
class DelimT,
class OutputIterator>
291 const char*
s = sp.
start();
292 const size_t strSize = sp.
size();
295 if (dSize > strSize || dSize == 0) {
296 if (!ignoreEmpty || strSize > 0) {
297 *out++ = to<OutStringT>(sp);
303 return internalSplit<OutStringT>(
delimFront(delim), sp, out, ignoreEmpty);
306 size_t tokenStartPos = 0;
307 size_t tokenSize = 0;
308 for (
size_t i = 0;
i <= strSize - dSize; ++
i) {
310 if (!ignoreEmpty || tokenSize > 0) {
311 *out++ = to<OutStringT>(sp.
subpiece(tokenStartPos, tokenSize));
314 tokenStartPos = i + dSize;
321 tokenSize = strSize - tokenStartPos;
322 if (!ignoreEmpty || tokenSize > 0) {
323 *out++ = to<OutStringT>(sp.
subpiece(tokenStartPos, tokenSize));
327 template <
class String>
335 template <
class OutputType>
337 output = folly::to<OutputType>(input);
342 template <
bool exact,
class Delim,
class OutputType>
348 "split<false>() requires that the last argument be a string type " 350 if (exact &&
UNLIKELY(std::string::npos != input.
find(delimiter))) {
357 template <
bool exact,
class Delim,
class OutputType,
class... OutputTypes>
359 const Delim& delimiter,
362 OutputTypes&... outTail) {
363 size_t cut = input.
find(delimiter);
364 if (
UNLIKELY(cut == std::string::npos)) {
370 if (
LIKELY(splitFixed<exact>(delimiter, tail, outTail...))) {
381 template <
class Delim,
class String,
class OutputType>
383 const Delim& delimiter,
385 std::vector<OutputType>& out,
387 detail::internalSplit<OutputType>(
390 std::back_inserter(out),
394 template <
class Delim,
class String,
class OutputType>
396 const Delim& delimiter,
400 detail::internalSplit<OutputType>(
403 std::back_inserter(out),
408 class OutputValueType,
411 class OutputIterator>
413 const Delim& delimiter,
417 detail::internalSplit<OutputValueType>(
421 template <
bool exact,
class Delim,
class... OutputTypes>
422 typename std::enable_if<
424 sizeof...(OutputTypes) >= 1,
427 return detail::splitFixed<exact>(
446 template <
class Iterator>
448 :
IsSizableString<typename std::iterator_traits<Iterator>::value_type> {};
450 template <
class Delim,
class Iterator,
class String>
456 assert(begin != end);
462 while (++begin != end) {
463 toAppend(delimiter, *begin, &output);
467 template <
class Delim,
class Iterator,
class String>
474 const size_t dsize =
delimSize(delimiter);
476 size_t size = it->size();
477 while (++it != end) {
478 size += dsize + it->size();
480 output.reserve(size);
484 template <
class Delim,
class Iterator,
class String>
485 typename std::enable_if<
497 template <
class Delim,
class Iterator,
class String>
499 const Delim& delimiter,
506 template <
class OutputString>
511 static const char hexValues[] =
"0123456789abcdef";
513 output.reserve(3 * input.
size());
514 for (
unsigned char c : input) {
516 if (c < 0x20 || c > 0x7e ||
c ==
'\\') {
517 bool hex_append =
false;
518 output.push_back(
'\\');
524 }
else if (
c ==
'\n') {
526 }
else if (
c ==
'\t') {
528 }
else if (
c ==
'\a') {
530 }
else if (
c ==
'\b') {
532 }
else if (
c ==
'\0') {
534 }
else if (
c ==
'\\') {
541 output.push_back(
'x');
542 output.push_back(hexValues[(
c >> 4) & 0xf]);
543 output.push_back(hexValues[
c & 0xf]);
551 template <
class String1,
class String2>
553 size_t numUnprintable = 0;
554 size_t numPrintablePrefix = 0;
555 for (
unsigned char c : input) {
556 if (c < 0x20 || c > 0x7e ||
c ==
'\\') {
559 if (numUnprintable == 0) {
560 ++numPrintablePrefix;
577 if (numUnprintable == 0) {
579 }
else if (5 * numUnprintable >= 3 * input.size()) {
584 if (5 * numPrintablePrefix >= input.size()) {
595 template <
class InputString,
class OutputString>
597 const InputString& input,
599 bool append_output) {
600 if (!append_output) {
604 static char hexValues[] =
"0123456789abcdef";
605 auto j = output.size();
606 output.resize(2 * input.size() + output.size());
607 for (
size_t i = 0;
i < input.size(); ++
i) {
609 output[j++] = hexValues[(ch >> 4) & 0xf];
610 output[j++] = hexValues[ch & 0xf];
615 template <
class InputString,
class OutputString>
617 if (input.size() % 2 != 0) {
620 output.resize(input.size() / 2);
623 for (
size_t i = 0;
i < input.size();
i += 2) {
626 if ((highBits | lowBits) & 0x10) {
630 output[j++] = (highBits << 4) + lowBits;
644 template <
class OutIt>
648 while (offset < size) {
bool atDelim(const char *s, char c)
StringPiece prepareDelim(const String &s)
void splitTo(const Delim &delimiter, const String &input, OutputIterator out, bool ignoreEmpty)
bool unhexlify(const InputString &input, OutputString &output)
const std::array< unsigned char, 256 > uriEscapeTable
const std::array< char, 256 > cEscapeTable
void internalJoinAppend(Delim delimiter, Iterator begin, Iterator end, String &output)
void uriUnescape(StringPiece str, String &out, UriEscapeMode mode)
size_type find(const_range_type str) const
constexpr size_type size() const
auto begin(TestAdlIterable &instance)
void toOrIgnore(StringPiece input, OutputType &output)
void humanify(const String1 &input, String2 &output)
—— Concurrent Priority Queue Implementation ——
constexpr Iter start() const
void split(const Delim &delimiter, const String &input, std::vector< OutputType > &out, bool ignoreEmpty)
folly::Optional< PskKeyExchangeMode > mode
const std::array< unsigned char, 256 > hexTable
constexpr auto size(C const &c) -> decltype(c.size())
constexpr bool empty() const
auto end(TestAdlIterable &instance)
void uriEscape(StringPiece str, String &out, UriEscapeMode mode)
size_t hexDumpLine(const void *ptr, size_t offset, size_t size, std::string &line)
Range subpiece(size_type first, size_type length=npos) const
void cUnescape(StringPiece str, String &out, bool strict)
void hexDump(const void *ptr, size_t size, OutIt out)
const std::array< char, 256 > cUnescapeTable
static const char *const value
void toAppend(char value, Tgt *result)
constexpr Iter end() const
std::enable_if< IsSizableStringContainerIterator< Iterator >::value >::type internalJoin(Delim delimiter, Iterator begin, Iterator end, String &output)
constexpr Iter begin() const
void backslashify(folly::StringPiece input, OutputString &output, bool hex_style)
void internalSplit(DelimT delim, StringPiece sp, OutputIterator out, bool ignoreEmpty)
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
void join(const Delim &delimiter, Iterator begin, Iterator end, String &output)
bool splitFixed(const Delim &delimiter, StringPiece input, OutputType &output)
Range< const char * > StringPiece
bool hexlify(const InputString &input, OutputString &output, bool append_output)
#define FOLLY_FALLTHROUGH
void cEscape(StringPiece str, String &out)