Fix another race in Notification Queue
[folly.git] / folly / Format-inl.h
index 5575151c27c0cef40435c569f2d0ca0e436b640f..625233f5f49c6a97e1045761a8bcae88f2a626b1 100644 (file)
@@ -18,8 +18,8 @@
 #error This file may only be included from Format.h.
 #endif
 
-#include "folly/Exception.h"
-#include "folly/Traits.h"
+#include <folly/Exception.h>
+#include <folly/Traits.h>
 
 // Ignore -Wformat-nonliteral warnings within this file
 #pragma GCC diagnostic push
@@ -912,6 +912,11 @@ struct IndexableTraitsSeq : public FormatTraitsBase {
   static const value_type& at(const C& c, int idx) {
     return c.at(idx);
   }
+
+  static const value_type& at(const C& c, int idx,
+                              const value_type& dflt) {
+    return (idx >= 0 && idx < c.size()) ? c.at(idx) : dflt;
+  }
 };
 
 // Base class for associative types (maps)
@@ -921,6 +926,11 @@ struct IndexableTraitsAssoc : public FormatTraitsBase {
   static const value_type& at(const C& c, int idx) {
     return c.at(static_cast<typename C::key_type>(idx));
   }
+  static const value_type& at(const C& c, int idx,
+                              const value_type& dflt) {
+    auto pos = c.find(static_cast<typename C::key_type>(idx));
+    return pos != c.end() ? pos->second : dflt;
+  }
 };
 
 // std::array
@@ -991,6 +1001,28 @@ class FormatValue<
   const T& val_;
 };
 
+template <class Container, class Value>
+class FormatValue<
+  detail::DefaultValueWrapper<Container, Value>,
+  typename detail::IndexableTraits<Container>::enabled> {
+ public:
+  explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val)
+    : val_(val) { }
+
+  template <class FormatCallback>
+  void format(FormatArg& arg, FormatCallback& cb) const {
+    FormatValue<typename std::decay<
+      typename detail::IndexableTraits<Container>::value_type>::type>(
+          detail::IndexableTraits<Container>::at(
+              val_.container,
+              arg.splitIntKey(),
+              val_.defaultValue)).format(arg, cb);
+  }
+
+ private:
+  const detail::DefaultValueWrapper<Container, Value>& val_;
+};
+
 namespace detail {
 
 // Define enabled, key_type, convert from StringPiece to the key types
@@ -1032,6 +1064,11 @@ template <class T> struct KeyableTraitsAssoc : public FormatTraitsBase {
   static const value_type& at(const T& map, StringPiece key) {
     return map.at(KeyFromStringPiece<key_type>::convert(key));
   }
+  static const value_type& at(const T& map, StringPiece key,
+                              const value_type& dflt) {
+    auto pos = map.find(KeyFromStringPiece<key_type>::convert(key));
+    return pos != map.end() ? pos->second : dflt;
+  }
 };
 
 // Define enabled, key_type, value_type, at() for supported string-keyed
@@ -1076,6 +1113,28 @@ class FormatValue<
   const T& val_;
 };
 
+template <class Container, class Value>
+class FormatValue<
+  detail::DefaultValueWrapper<Container, Value>,
+  typename detail::KeyableTraits<Container>::enabled> {
+ public:
+  explicit FormatValue(const detail::DefaultValueWrapper<Container, Value>& val)
+    : val_(val) { }
+
+  template <class FormatCallback>
+  void format(FormatArg& arg, FormatCallback& cb) const {
+    FormatValue<typename std::decay<
+      typename detail::KeyableTraits<Container>::value_type>::type>(
+          detail::KeyableTraits<Container>::at(
+              val_.container,
+              arg.splitKey(),
+              val_.defaultValue)).format(arg, cb);
+  }
+
+ private:
+  const detail::DefaultValueWrapper<Container, Value>& val_;
+};
+
 // Partial specialization of FormatValue for pairs
 template <class A, class B>
 class FormatValue<std::pair<A, B>> {