X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2FString.h;h=ef153bd20b69f30f15afa89b91ac6d0f37f161c3;hp=563f5313ecc04a63c4fb739763a819a93026c1c6;hb=20808864dfde991fd740e6caefe632d4bf244d69;hpb=db66e2f4b93dee8c8834dede216e068a3a3e40af diff --git a/folly/String.h b/folly/String.h index 563f5313..ef153bd2 100644 --- a/folly/String.h +++ b/folly/String.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2011-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,30 +14,27 @@ * limitations under the License. */ -#ifndef FOLLY_BASE_STRING_H_ -#define FOLLY_BASE_STRING_H_ +#pragma once +#define FOLLY_STRING_H_ +#include #include #include -#include - -#ifdef FOLLY_HAVE_DEPRECATED_ASSOC -#ifdef _GLIBCXX_SYMVER -#include -#include -#endif -#endif - -#include #include +#include +#include + +#include +#include #include -#include +#include #include #include #include #include #include +#include // Compatibility function, to make sure toStdString(s) can be called // to convert a std::string or fbstring variable s into type std::string @@ -186,6 +183,16 @@ std::string& stringAppendf(std::string* output, FOLLY_PRINTF_FORMAT const char* format, ...) FOLLY_PRINTF_FORMAT_ATTR(2, 3); +/** + * Similar to stringPrintf, but accepts a va_list argument. + * + * As with vsnprintf() itself, the value of ap is undefined after the call. + * These functions do not call va_end() on ap. + */ +std::string stringVPrintf(const char* format, va_list ap); +void stringVPrintf(std::string* out, const char* format, va_list ap); +std::string& stringVAppendf(std::string* out, const char* format, va_list ap); + /** * Backslashify a string, that is, replace non-printable characters * with C-style (but NOT C compliant) "\xHH" encoding. If hex_style @@ -205,12 +212,15 @@ std::string& stringAppendf(std::string* output, * C++, use cEscape instead. This function is for display purposes * only. */ -template -void backslashify(const String1& input, String2& output, bool hex_style=false); - -template -String backslashify(const String& input, bool hex_style=false) { - String output; +template +void backslashify( + folly::StringPiece input, + OutputString& output, + bool hex_style = false); + +template +OutputString backslashify(StringPiece input, bool hex_style = false) { + OutputString output; backslashify(input, output, hex_style); return output; } @@ -243,17 +253,43 @@ String humanify(const String& input) { * If append_output is true, append data to the output rather than * replace it. */ -template +template bool hexlify(const InputString& input, OutputString& output, bool append=false); +template +OutputString hexlify(ByteRange input) { + OutputString output; + if (!hexlify(input, output)) { + // hexlify() currently always returns true, so this can't really happen + throw std::runtime_error("hexlify failed"); + } + return output; +} + +template +OutputString hexlify(StringPiece input) { + return hexlify(ByteRange{input}); +} + /** * Same functionality as Python's binascii.unhexlify. Returns true * on successful conversion. */ -template +template bool unhexlify(const InputString& input, OutputString& output); +template +OutputString unhexlify(StringPiece input) { + OutputString output; + if (!unhexlify(input, output)) { + // unhexlify() fails if the input has non-hexidecimal characters, + // or if it doesn't consist of a whole number of bytes + throw std::domain_error("unhexlify() called with non-hex input"); + } + return output; +} + /* * A pretty-printer for numbers that appends suffixes of units of the * given type. It prints 4 sig-figs of value with the most @@ -348,23 +384,6 @@ std::string hexDump(const void* ptr, size_t size); */ fbstring errnoStr(int err); -/** - * Debug string for an exception: include type and what(). - */ -inline fbstring exceptionStr(const std::exception& e) { - return folly::to(demangle(typeid(e)), ": ", e.what()); -} - -inline fbstring exceptionStr(std::exception_ptr ep) { - try { - std::rethrow_exception(ep); - } catch (const std::exception& e) { - return exceptionStr(e); - } catch (...) { - return ""; - } -} - /* * Split a string into a list of tokens by delimiter. * @@ -394,30 +413,35 @@ inline fbstring exceptionStr(std::exception_ptr ep) { * or not (generating empty tokens). */ -template +template void split(const Delim& delimiter, const String& input, std::vector& out, - bool ignoreEmpty = false); + const bool ignoreEmpty = false); -template +template void split(const Delim& delimiter, const String& input, folly::fbvector& out, - bool ignoreEmpty = false); + const bool ignoreEmpty = false); -template +template < + class OutputValueType, + class Delim, + class String, + class OutputIterator> void splitTo(const Delim& delimiter, const String& input, OutputIterator out, - bool ignoreEmpty = false); + const bool ignoreEmpty = false); /* * Split a string into a fixed number of string pieces and/or numeric types - * by delimiter. Any numeric type that folly::to<> can convert to from a - * string piece is supported as a target. Returns 'true' if the fields were - * all successfully populated. + * by delimiter. Conversions are supported for any type which folly:to<> can + * target, including all overloads of parseTo(). Returns 'true' if the fields + * were all successfully populated. Returns 'false' if there were too few + * fields in the input, or too many fields if exact=true. Casting exceptions + * will not be caught. * * Examples: * @@ -445,20 +469,24 @@ void splitTo(const Delim& delimiter, * Note that this will likely not work if the last field's target is of numeric * type, in which case folly::to<> will throw an exception. */ -template -using IsSplitTargetType = std::integral_constant::value || - std::is_same::value>; - -template -typename std::enable_if::value, bool>::type -split(const Delim& delimiter, - StringPiece input, - OutputType& outHead, - OutputTypes&... outTail); +namespace detail { +template +struct IsConvertible : std::false_type {}; + +template +struct IsConvertible< + void_t()))>, + OutputType> : std::true_type {}; +} // namespace detail +template +struct IsConvertible : detail::IsConvertible {}; + +template +typename std::enable_if< + StrictConjunction...>::value && + sizeof...(OutputTypes) >= 1, + bool>::type +split(const Delim& delimiter, StringPiece input, OutputTypes&... outputs); /* * Join list of tokens. @@ -503,18 +531,64 @@ std::string join(const Delim& delimiter, return output; } +template < + class Delim, + class Iterator, + typename std::enable_if::iterator_category, + std::random_access_iterator_tag>::value>::type* = nullptr> +std::string join(const Delim& delimiter, Iterator begin, Iterator end) { + std::string output; + join(delimiter, begin, end, output); + return output; +} + /** * Returns a subpiece with all whitespace removed from the front of @sp. * Whitespace means any of [' ', '\n', '\r', '\t']. */ -StringPiece skipWhitespace(StringPiece sp); +StringPiece ltrimWhitespace(StringPiece sp); + +/** + * Returns a subpiece with all whitespace removed from the back of @sp. + * Whitespace means any of [' ', '\n', '\r', '\t']. + */ +StringPiece rtrimWhitespace(StringPiece sp); + +/** + * Returns a subpiece with all whitespace removed from the back and front of @sp. + * Whitespace means any of [' ', '\n', '\r', '\t']. + */ +inline StringPiece trimWhitespace(StringPiece sp) { + return ltrimWhitespace(rtrimWhitespace(sp)); +} + +/** + * Returns a subpiece with all whitespace removed from the front of @sp. + * Whitespace means any of [' ', '\n', '\r', '\t']. + * DEPRECATED: @see ltrimWhitespace @see rtrimWhitespace + */ +inline StringPiece skipWhitespace(StringPiece sp) { + return ltrimWhitespace(sp); +} + +/** + * Strips the leading and the trailing whitespace-only lines. Then looks for + * the least indented non-whitespace-only line and removes its amount of + * leading whitespace from every line. Assumes leading whitespace is either all + * spaces or all tabs. + * + * Purpose: including a multiline string literal in source code, indented to + * the level expected from context. + */ +std::string stripLeftMargin(std::string s); /** * Fast, in-place lowercasing of ASCII alphabetic characters in strings. * Leaves all other characters unchanged, including those with the 0x80 * bit set. * @param str String to convert - * @param len Length of str, in bytes + * @param length Length of str, in bytes */ void toLowerAscii(char* str, size_t length); @@ -522,46 +596,27 @@ inline void toLowerAscii(MutableStringPiece str) { toLowerAscii(str.begin(), str.size()); } -} // namespace folly - -// Hash functions to make std::string usable with e.g. hash_map -// -// Handle interaction with different C++ standard libraries, which -// expect these types to be in different namespaces. -namespace std { - -template -struct hash > : private hash { - size_t operator()(const std::basic_string & s) const { - return hash::operator()(s.c_str()); - } -}; - +inline void toLowerAscii(std::string& str) { + // str[0] is legal also if the string is empty. + toLowerAscii(&str[0], str.size()); } -#if FOLLY_HAVE_DEPRECATED_ASSOC -#if defined(_GLIBCXX_SYMVER) && !defined(__BIONIC__) -namespace __gnu_cxx { - -template -struct hash > : private hash { - size_t operator()(const std::basic_string & s) const { - return hash::operator()(s.c_str()); - } +template < + class Iterator = const char*, + class Base = folly::Range>> +class UTF8Range : public Base { + public: + /* implicit */ UTF8Range(const folly::Range baseRange) + : Base(boost::u8_to_u32_iterator( + baseRange.begin(), baseRange.begin(), baseRange.end()), + boost::u8_to_u32_iterator( + baseRange.end(), baseRange.begin(), baseRange.end())) {} + /* implicit */ UTF8Range(const std::string& baseString) + : Base(folly::Range(baseString)) {} }; -} -#endif -#endif - -// Hook into boost's type traits -namespace boost { -template -struct has_nothrow_constructor > : true_type { - enum { value = true }; -}; -} // namespace boost +using UTF8StringPiece = UTF8Range; -#include +} // namespace folly -#endif +#include