Thread-safe version of loopKeepAlive()
[folly.git] / folly / Format-inl.h
index 6205a5682eb6e7a09c3fa124bc1913ba967e2a04..c27b7662ae1f71c52fe31512945ccd50f074d69c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #error This file may only be included from Format.h.
 #endif
 
+#include <array>
+#include <cinttypes>
+#include <deque>
+#include <map>
+#include <unordered_map>
+#include <vector>
+
 #include <folly/Exception.h>
+#include <folly/FormatTraits.h>
 #include <folly/Traits.h>
+#include <folly/portability/Windows.h>
 
 // Ignore -Wformat-nonliteral warnings within this file
 #pragma GCC diagnostic push
@@ -218,6 +227,8 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(Output& out)
     int argIndex = 0;
     auto piece = arg.splitKey<true>();  // empty key component is okay
     if (containerMode) {  // static
+      arg.enforce(arg.width != FormatArg::kDynamicWidth,
+                  "dynamic field width not supported in vformat()");
       if (piece.empty()) {
         arg.setNextIntKey(nextArg++);
         hasDefaultArgIndex = true;
@@ -227,9 +238,22 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(Output& out)
       }
     } else {
       if (piece.empty()) {
+        if (arg.width == FormatArg::kDynamicWidth) {
+          arg.enforce(arg.widthIndex == FormatArg::kNoIndex,
+                      "cannot provide width arg index without value arg index");
+          int sizeArg = nextArg++;
+          arg.width = getSizeArg(sizeArg, arg);
+        }
+
         argIndex = nextArg++;
         hasDefaultArgIndex = true;
       } else {
+        if (arg.width == FormatArg::kDynamicWidth) {
+          arg.enforce(arg.widthIndex != FormatArg::kNoIndex,
+                      "cannot provide value arg index without width arg index");
+          arg.width = getSizeArg(arg.widthIndex, arg);
+        }
+
         try {
           argIndex = to<int>(piece);
         } catch (const std::out_of_range& e) {
@@ -395,6 +419,11 @@ class FormatValue<
   {
  public:
   explicit FormatValue(T val) : val_(val) { }
+
+  T getValue() const {
+    return val_;
+  }
+
   template <class FormatCallback>
   void format(FormatArg& arg, FormatCallback& cb) const {
     arg.validate(FormatArg::Type::INTEGER);
@@ -415,7 +444,7 @@ class FormatValue<
     char sign;
     if (std::is_signed<T>::value) {
       if (folly::is_negative(val_)) {
-        uval = static_cast<UT>(-val_);
+        uval = -static_cast<UT>(val_);
         sign = '-';
       } else {
         uval = static_cast<UT>(val_);
@@ -463,8 +492,13 @@ class FormatValue<
                   "' specifier");
 
       valBufBegin = valBuf + 3;  // room for sign and base prefix
+#if defined(__ANDROID__)
       int len = snprintf(valBufBegin, (valBuf + valBufSize) - valBufBegin,
-                         "%'ju", static_cast<uintmax_t>(uval));
+                         "%" PRIuMAX, static_cast<uintmax_t>(uval));
+#else
+      int len = snprintf(valBufBegin, (valBuf + valBufSize) - valBufBegin,
+                         "%ju", static_cast<uintmax_t>(uval));
+#endif
       // valBufSize should always be big enough, so this should never
       // happen.
       assert(len < valBuf + valBufSize - valBufBegin);
@@ -727,7 +761,9 @@ template <class T, class = void>
 class TryFormatValue {
  public:
   template <class FormatCallback>
-  static void formatOrFail(T& value, FormatArg& arg, FormatCallback& cb) {
+  static void formatOrFail(T& /* value */,
+                           FormatArg& arg,
+                           FormatCallback& /* cb */) {
     arg.error("No formatter available for this type");
   }
 };
@@ -770,45 +806,6 @@ class FormatValue<
 
 namespace detail {
 
-// Shortcut, so we don't have to use enable_if everywhere
-struct FormatTraitsBase {
-  typedef void enabled;
-};
-
-// Traits that define enabled, value_type, and at() for anything
-// indexable with integral keys: pointers, arrays, vectors, and maps
-// with integral keys
-template <class T, class Enable=void> struct IndexableTraits;
-
-// Base class for sequences (vectors, deques)
-template <class C>
-struct IndexableTraitsSeq : public FormatTraitsBase {
-  typedef C container_type;
-  typedef typename C::value_type value_type;
-  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 && size_t(idx) < c.size()) ? c.at(idx) : dflt;
-  }
-};
-
-// Base class for associative types (maps)
-template <class C>
-struct IndexableTraitsAssoc : public FormatTraitsBase {
-  typedef typename C::value_type::second_type value_type;
-  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
 template <class T, size_t N>
 struct IndexableTraits<std::array<T, N>>
@@ -827,18 +824,6 @@ struct IndexableTraits<std::deque<T, A>>
   : public IndexableTraitsSeq<std::deque<T, A>> {
 };
 
-// fbvector
-template <class T, class A>
-struct IndexableTraits<fbvector<T, A>>
-  : public IndexableTraitsSeq<fbvector<T, A>> {
-};
-
-// small_vector
-template <class T, size_t M, class A, class B, class C>
-struct IndexableTraits<small_vector<T, M, A, B, C>>
-  : public IndexableTraitsSeq<small_vector<T, M, A, B, C>> {
-};
-
 // std::map with integral keys
 template <class K, class T, class C, class A>
 struct IndexableTraits<
@@ -1054,8 +1039,8 @@ class FormatValue<std::tuple<Args...>> {
   static constexpr size_t valueCount = std::tuple_size<Tuple>::value;
 
   template <size_t K, class Callback>
-  typename std::enable_if<K == valueCount>::type
-  doFormatFrom(size_t i, FormatArg& arg, Callback& cb) const {
+  typename std::enable_if<K == valueCount>::type doFormatFrom(
+      size_t i, FormatArg& arg, Callback& /* cb */) const {
     arg.enforce("tuple index out of range, max=", i);
   }