Initialize LifoSem's padding to allow for its constexpr constructor.
[folly.git] / folly / String-inl.h
index e61ef33217c5655b87fcdff8ae894c23495af197..1a4edb7d949aeb93c20ba29849a7371bd1aedc97 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -203,7 +203,6 @@ void uriUnescape(StringPiece str, String& out, UriEscapeMode mode) {
   // this is faster than calling push_back repeatedly.
   while (p != str.end()) {
     char c = *p;
-    unsigned char v = static_cast<unsigned char>(v);
     switch (c) {
     case '%':
       {
@@ -320,9 +319,9 @@ void internalSplit(DelimT delim, StringPiece sp, OutputIterator out,
       ignoreEmpty);
   }
 
-  int tokenStartPos = 0;
-  int tokenSize = 0;
-  for (int i = 0; i <= strSize - dSize; ++i) {
+  size_t tokenStartPos = 0;
+  size_t tokenSize = 0;
+  for (size_t i = 0; i <= strSize - dSize; ++i) {
     if (atDelim(&s[i], delim)) {
       if (!ignoreEmpty || tokenSize > 0) {
         *out++ = conv(StringPiece(&s[tokenStartPos], tokenSize));
@@ -335,9 +334,8 @@ void internalSplit(DelimT delim, StringPiece sp, OutputIterator out,
       ++tokenSize;
     }
   }
-
+  tokenSize = strSize - tokenStartPos;
   if (!ignoreEmpty || tokenSize > 0) {
-    tokenSize = strSize - tokenStartPos;
     *out++ = conv(StringPiece(&s[tokenStartPos], tokenSize));
   }
 }
@@ -347,25 +345,36 @@ template<class String> StringPiece prepareDelim(const String& s) {
 }
 inline char prepareDelim(char c) { return c; }
 
+template <class Dst>
+struct convertTo {
+  template <class Src>
+  static Dst from(const Src& src) { return folly::to<Dst>(src); }
+  static Dst from(const Dst& src) { return src; }
+};
+
 template<bool exact,
-         class Delim>
-bool splitFixed(const Delim& delimiter,
-                StringPiece input,
-                StringPiece& out) {
+         class Delim,
+         class OutputType>
+typename std::enable_if<IsSplitTargetType<OutputType>::value, bool>::type
+splitFixed(const Delim& delimiter,
+           StringPiece input,
+           OutputType& out) {
   if (exact && UNLIKELY(std::string::npos != input.find(delimiter))) {
     return false;
   }
-  out = input;
+  out = convertTo<OutputType>::from(input);
   return true;
 }
 
 template<bool exact,
          class Delim,
-         class... StringPieces>
-bool splitFixed(const Delim& delimiter,
-                StringPiece input,
-                StringPiece& outHead,
-                StringPieces&... outTail) {
+         class OutputType,
+         class... OutputTypes>
+typename std::enable_if<IsSplitTargetType<OutputType>::value, bool>::type
+splitFixed(const Delim& delimiter,
+           StringPiece input,
+           OutputType& outHead,
+           OutputTypes&... outTail) {
   size_t cut = input.find(delimiter);
   if (UNLIKELY(cut == std::string::npos)) {
     return false;
@@ -374,7 +383,7 @@ bool splitFixed(const Delim& delimiter,
   StringPiece tail(input.begin() + cut + detail::delimSize(delimiter),
                    input.end());
   if (LIKELY(splitFixed<exact>(delimiter, tail, outTail...))) {
-    outHead = head;
+    outHead = convertTo<OutputType>::from(head);
     return true;
   }
   return false;
@@ -423,11 +432,13 @@ void splitTo(const Delim& delimiter,
 
 template<bool exact,
          class Delim,
-         class... StringPieces>
-bool split(const Delim& delimiter,
-           StringPiece input,
-           StringPiece& outHead,
-           StringPieces&... outTail) {
+         class OutputType,
+         class... OutputTypes>
+typename std::enable_if<IsSplitTargetType<OutputType>::value, bool>::type
+split(const Delim& delimiter,
+      StringPiece input,
+      OutputType& outHead,
+      OutputTypes&... outTail) {
   return detail::splitFixed<exact>(
     detail::prepareDelim(delimiter),
     input,
@@ -437,9 +448,20 @@ bool split(const Delim& delimiter,
 
 namespace detail {
 
+/*
+ * If a type can have its string size determined cheaply, we can more
+ * efficiently append it in a loop (see internalJoinAppend). Note that the
+ * struct need not conform to the std::string api completely (ex. does not need
+ * to implement append()).
+ */
+template <class T> struct IsSizableString {
+  enum { value = IsSomeString<T>::value
+         || std::is_same<T, StringPiece>::value };
+};
+
 template <class Iterator>
-struct IsStringContainerIterator :
-  IsSomeString<typename std::iterator_traits<Iterator>::value_type> {
+struct IsSizableStringContainerIterator :
+  IsSizableString<typename std::iterator_traits<Iterator>::value_type> {
 };
 
 template <class Delim, class Iterator, class String>
@@ -460,7 +482,7 @@ void internalJoinAppend(Delim delimiter,
 }
 
 template <class Delim, class Iterator, class String>
-typename std::enable_if<IsStringContainerIterator<Iterator>::value>::type
+typename std::enable_if<IsSizableStringContainerIterator<Iterator>::value>::type
 internalJoin(Delim delimiter,
              Iterator begin,
              Iterator end,
@@ -480,7 +502,8 @@ internalJoin(Delim delimiter,
 }
 
 template <class Delim, class Iterator, class String>
-typename std::enable_if<!IsStringContainerIterator<Iterator>::value>::type
+typename
+std::enable_if<!IsSizableStringContainerIterator<Iterator>::value>::type
 internalJoin(Delim delimiter,
              Iterator begin,
              Iterator end,
@@ -543,8 +566,8 @@ void backslashify(const String1& input, String2& output, bool hex_style) {
 
 template <class String1, class String2>
 void humanify(const String1& input, String2& output) {
-  int numUnprintable = 0;
-  int numPrintablePrefix = 0;
+  size_t numUnprintable = 0;
+  size_t numPrintablePrefix = 0;
   for (unsigned char c : input) {
     if (c < 0x20 || c > 0x7e || c == '\\') {
       ++numUnprintable;
@@ -591,9 +614,9 @@ bool hexlify(const InputString& input, OutputString& output,
   if (!append_output) output.clear();
 
   static char hexValues[] = "0123456789abcdef";
-  int j = output.size();
+  auto j = output.size();
   output.resize(2 * input.size() + output.size());
-  for (int i = 0; i < input.size(); ++i) {
+  for (size_t i = 0; i < input.size(); ++i) {
     int ch = input[i];
     output[j++] = hexValues[(ch >> 4) & 0xf];
     output[j++] = hexValues[ch & 0xf];
@@ -615,7 +638,7 @@ bool unhexlify(const InputString& input, OutputString& output) {
            -1;
   };
 
-  for (int i = 0; i < input.size(); i += 2) {
+  for (size_t i = 0; i < input.size(); i += 2) {
     int highBits = unhex(input[i]);
     int lowBits = unhex(input[i + 1]);
     if (highBits < 0 || lowBits < 0) {
@@ -648,4 +671,3 @@ void hexDump(const void* ptr, size_t size, OutIt out) {
 }  // namespace folly
 
 #endif /* FOLLY_STRING_INL_H_ */
-