/*
- * 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
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;
}
} 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) {
{
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);
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_);
"' 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);
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");
}
};
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>>
: 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<
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);
}