Fix SignalHandlerTest with ASAN
[folly.git] / folly / Format-inl.h
index 1b998dec9a05559183399c4b16270e35f20db52a..b97375c1f8e6e9b4660fa531af74075872c8d78c 100644 (file)
 
 #include <folly/Exception.h>
 #include <folly/FormatTraits.h>
+#include <folly/MapUtil.h>
 #include <folly/Traits.h>
 #include <folly/portability/Windows.h>
 
 // Ignore -Wformat-nonliteral warnings within this file
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+FOLLY_PUSH_WARNING
+FOLLY_GCC_DISABLE_WARNING("-Wformat-nonliteral")
 
 namespace folly {
 
@@ -157,13 +158,7 @@ template <class Derived, bool containerMode, class... Args>
 BaseFormatter<Derived, containerMode, Args...>::BaseFormatter(
     StringPiece str,
     Args&&... args)
-    : str_(str),
-      values_(FormatValue<typename std::decay<Args>::type>(
-          std::forward<Args>(args))...) {
-  static_assert(
-      !containerMode || sizeof...(Args) == 1,
-      "Exactly one argument required in container mode");
-}
+    : str_(str), values_(std::forward<Args>(args)...) {}
 
 template <class Derived, bool containerMode, class... Args>
 template <class Output>
@@ -186,7 +181,7 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(
       p = q;
 
       if (p == end || *p != '}') {
-        throw BadFormatArg("folly::format: single '}' in format string");
+        throwBadFormatArg("folly::format: single '}' in format string");
       }
       ++p;
     }
@@ -208,7 +203,7 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(
     p = q + 1;
 
     if (p == end) {
-      throw BadFormatArg("folly::format: '}' at end of format string");
+      throwBadFormatArg("folly::format: '}' at end of format string");
     }
 
     // "{{" -> "{"
@@ -221,7 +216,7 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(
     // Format string
     q = static_cast<const char*>(memchr(p, '}', size_t(end - p)));
     if (q == nullptr) {
-      throw BadFormatArg("folly::format: missing ending '}'");
+      throwBadFormatArg("folly::format: missing ending '}'");
     }
     FormatArg arg(StringPiece(p, q));
     p = q + 1;
@@ -246,7 +241,7 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(
               arg.widthIndex == FormatArg::kNoIndex,
               "cannot provide width arg index without value arg index");
           int sizeArg = nextArg++;
-          arg.width = getSizeArg(size_t(sizeArg), arg);
+          arg.width = asDerived().getSizeArg(size_t(sizeArg), arg);
         }
 
         argIndex = nextArg++;
@@ -256,7 +251,7 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(
           arg.enforce(
               arg.widthIndex != FormatArg::kNoIndex,
               "cannot provide value arg index without width arg index");
-          arg.width = getSizeArg(size_t(arg.widthIndex), arg);
+          arg.width = asDerived().getSizeArg(size_t(arg.widthIndex), arg);
         }
 
         try {
@@ -270,11 +265,11 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(
     }
 
     if (hasDefaultArgIndex && hasExplicitArgIndex) {
-      throw BadFormatArg(
+      throwBadFormatArg(
           "folly::format: may not have both default and explicit arg indexes");
     }
 
-    doFormat(size_t(argIndex), arg, out);
+    asDerived().doFormat(size_t(argIndex), arg, out);
   }
 }
 
@@ -296,19 +291,15 @@ namespace format_value {
 template <class FormatCallback>
 void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb) {
   if (arg.width != FormatArg::kDefaultWidth && arg.width < 0) {
-    throw BadFormatArg("folly::format: invalid width");
+    throwBadFormatArg("folly::format: invalid width");
   }
   if (arg.precision != FormatArg::kDefaultPrecision && arg.precision < 0) {
-    throw BadFormatArg("folly::format: invalid precision");
+    throwBadFormatArg("folly::format: invalid precision");
   }
 
-  // XXX: clang should be smart enough to not need the two static_cast<size_t>
-  // uses below given the above checks. If clang ever becomes that smart, we
-  // should remove the otherwise unnecessary warts.
-
   if (arg.precision != FormatArg::kDefaultPrecision &&
       val.size() > static_cast<size_t>(arg.precision)) {
-    val.reset(val.data(), size_t(arg.precision));
+    val.reset(val.data(), static_cast<size_t>(arg.precision));
   }
 
   constexpr int padBufSize = 128;
@@ -688,7 +679,7 @@ class FormatValue<float> {
   float val_;
 };
 
-// Sring-y types (implicitly convertible to StringPiece, except char*)
+// String-y types (implicitly convertible to StringPiece, except char*)
 template <class T>
 class FormatValue<
     T,
@@ -941,7 +932,7 @@ template <>
 struct KeyFromStringPiece<fbstring> : public FormatTraitsBase {
   typedef fbstring key_type;
   static fbstring convert(StringPiece s) {
-    return s.toFbstring();
+    return s.to<fbstring>();
   }
 };
 
@@ -960,7 +951,10 @@ struct KeyableTraitsAssoc : public FormatTraitsBase {
   typedef typename T::key_type key_type;
   typedef typename T::value_type::second_type value_type;
   static const value_type& at(const T& map, StringPiece key) {
-    return map.at(KeyFromStringPiece<key_type>::convert(key));
+    if (auto ptr = get_ptr(map, KeyFromStringPiece<key_type>::convert(key))) {
+      return *ptr;
+    }
+    detail::throwFormatKeyNotFoundException(key);
   }
   static const value_type&
   at(const T& map, StringPiece key, const value_type& dflt) {
@@ -1131,4 +1125,4 @@ typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
 
 } // namespace folly
 
-#pragma GCC diagnostic pop
+FOLLY_POP_WARNING