X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FString.h;h=da93cd265d106a296e60a651aad59cd1cfb16bfd;hb=cb5272724fbe18e937bbe8bb8a0a279027255032;hp=c843eed8b1b5d4768570fc9dd0aa528092e2858e;hpb=5c77fedbef46995a71ffa268c9fcaf49efddd01b;p=folly.git diff --git a/folly/String.h b/folly/String.h index c843eed8..da93cd26 100644 --- a/folly/String.h +++ b/folly/String.h @@ -112,6 +112,56 @@ String cUnescape(StringPiece str, bool strict = true) { return out; } +/** + * URI-escape a string. Appends the result to the output string. + * + * Alphanumeric characters and other characters marked as "unreserved" in RFC + * 3986 ( -_.~ ) are left unchanged. In PATH mode, the forward slash (/) is + * also left unchanged. In QUERY mode, spaces are replaced by '+'. All other + * characters are percent-encoded. + */ +enum class UriEscapeMode : unsigned char { + // The values are meaningful, see generate_escape_tables.py + ALL = 0, + QUERY = 1, + PATH = 2 +}; +template +void uriEscape(StringPiece str, + String& out, + UriEscapeMode mode = UriEscapeMode::ALL); + +/** + * Similar to uriEscape above, but returns the escaped string. + */ +template +String uriEscape(StringPiece str, UriEscapeMode mode = UriEscapeMode::ALL) { + String out; + uriEscape(str, out, mode); + return out; +} + +/** + * URI-unescape a string. Appends the result to the output string. + * + * In QUERY mode, '+' are replaced by space. %XX sequences are decoded if + * XX is a valid hex sequence, otherwise we throw invalid_argument. + */ +template +void uriUnescape(StringPiece str, + String& out, + UriEscapeMode mode = UriEscapeMode::ALL); + +/** + * Similar to uriUnescape above, but returns the unescaped string. + */ +template +String uriUnescape(StringPiece str, UriEscapeMode mode = UriEscapeMode::ALL) { + String out; + uriUnescape(str, out, mode); + return out; +} + /** * stringPrintf is much like printf but deposits its result into a * string. Two signatures are supported: the first simply returns the @@ -272,13 +322,36 @@ fbstring errnoStr(int err); * * Use for debugging -- do not rely on demangle() returning anything useful. * - * This function may allocate memory (and therefore throw). + * This function may allocate memory (and therefore throw std::bad_alloc). */ fbstring demangle(const char* name); inline fbstring demangle(const std::type_info& type) { return demangle(type.name()); } +/** + * Return the demangled (prettyfied) version of a C++ type in a user-provided + * buffer. + * + * The semantics are the same as for snprintf or strlcpy: bufSize is the size + * of the buffer, the string is always null-terminated, and the return value is + * the number of characters (not including the null terminator) that would have + * been written if the buffer was big enough. (So a return value >= bufSize + * indicates that the output was truncated) + * + * This function does not allocate memory and is async-signal-safe. + * + * Note that the underlying function for the fbstring-returning demangle is + * somewhat standard (abi::__cxa_demangle, which uses malloc), the underlying + * function for this version is less so (cplus_demangle_v3_callback from + * libiberty), so it is possible for the fbstring version to work, while this + * version returns the original, mangled name. + */ +size_t demangle(const char* name, char* buf, size_t bufSize); +inline size_t demangle(const std::type_info& type, char* buf, size_t bufSize) { + return demangle(type.name(), buf, bufSize); +} + /** * Debug string for an exception: include type and what(). */ @@ -344,6 +417,35 @@ void splitTo(const Delim& delimiter, OutputIterator out, bool ignoreEmpty = false); +/* + * Split a string into a fixed number of pieces by delimiter. Returns 'true' if + * the fields were all successfully populated. + * + * Example: + * + * folly::StringPiece name, key, value; + * if (folly::split('\t', line, name, key, value)) + * ... + * + * The 'exact' template paremeter specifies how the function behaves when too + * many fields are present in the input string. When 'exact' is set to its + * default value of 'true', a call to split will fail if the number of fields in + * the input string does not exactly match the number of output parameters + * passed. If 'exact' is overridden to 'false', all remaining fields will be + * stored, unsplit, in the last field, as shown below: + * + * folly::StringPiece x, y. + * if (folly::split(':', "a:b:c", x, y)) + * assert(x == "a" && y == "b:c"); + */ +template +bool split(const Delim& delimiter, + StringPiece input, + StringPiece& outHead, + StringPieces&... outTail); + /* * Join list of tokens. * @@ -364,6 +466,13 @@ void join(const Delim& delimiter, join(delimiter, container.begin(), container.end(), output); } +template +void join(const Delim& delimiter, + const std::initializer_list& values, + String& output) { + join(delimiter, values.begin(), values.end(), output); +} + template std::string join(const Delim& delimiter, const Container& container) { @@ -372,6 +481,14 @@ std::string join(const Delim& delimiter, return output; } +template +std::string join(const Delim& delimiter, + const std::initializer_list& values) { + std::string output; + join(delimiter, values.begin(), values.end(), output); + return output; +} + } // namespace folly // Hash functions for string and fbstring usable with e.g. hash_map