proxygen
FormatArg.h
Go to the documentation of this file.
1 /*
2  * Copyright 2012-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <stdexcept>
20 
21 #include <folly/CPortability.h>
22 #include <folly/Conv.h>
23 #include <folly/Likely.h>
24 #include <folly/Portability.h>
25 #include <folly/Range.h>
26 #include <folly/lang/Exception.h>
27 
28 namespace folly {
29 
30 class FOLLY_EXPORT BadFormatArg : public std::invalid_argument {
31  using invalid_argument::invalid_argument;
32 };
33 
37 struct FormatArg {
42  explicit FormatArg(StringPiece sp)
43  : fullArgString(sp),
44  fill(kDefaultFill),
45  align(Align::DEFAULT),
46  sign(Sign::DEFAULT),
47  basePrefix(false),
48  thousandsSeparator(false),
49  trailingDot(false),
50  width(kDefaultWidth),
51  widthIndex(kNoIndex),
52  precision(kDefaultPrecision),
53  presentation(kDefaultPresentation),
54  nextKeyMode_(NextKeyMode::NONE) {
55  if (!sp.empty()) {
56  initSlow();
57  }
58  }
59 
60  enum class Type {
61  INTEGER,
62  FLOAT,
63  OTHER,
64  };
68  void validate(Type type) const;
69 
75  template <typename... Args>
76  void enforce(bool v, Args&&... args) const {
77  if (UNLIKELY(!v)) {
78  error(std::forward<Args>(args)...);
79  }
80  }
81 
82  template <typename... Args>
83  std::string errorStr(Args&&... args) const;
84  template <typename... Args>
85  [[noreturn]] void error(Args&&... args) const;
86 
91 
95  static constexpr char kDefaultFill = '\0';
96  char fill;
97 
101  enum class Align : uint8_t {
102  DEFAULT,
103  LEFT,
104  RIGHT,
105  PAD_AFTER_SIGN,
106  CENTER,
107  INVALID,
108  };
110 
114  enum class Sign : uint8_t {
115  DEFAULT,
116  PLUS_OR_MINUS,
117  MINUS,
118  SPACE_OR_MINUS,
119  INVALID,
120  };
122 
127 
132 
137 
141  static constexpr int kDefaultWidth = -1;
142  static constexpr int kDynamicWidth = -2;
143  static constexpr int kNoIndex = -1;
144  int width;
146 
150  static constexpr int kDefaultPrecision = -1;
152 
156  static constexpr char kDefaultPresentation = '\0';
158 
163  template <bool emptyOk = false>
164  StringPiece splitKey();
165 
169  bool keyEmpty() const {
170  return nextKeyMode_ == NextKeyMode::NONE && key_.empty();
171  }
172 
177  int splitIntKey();
178 
179  void setNextIntKey(int val) {
180  assert(nextKeyMode_ == NextKeyMode::NONE);
181  nextKeyMode_ = NextKeyMode::INT;
182  nextIntKey_ = val;
183  }
184 
186  assert(nextKeyMode_ == NextKeyMode::NONE);
187  nextKeyMode_ = NextKeyMode::STRING;
188  nextKey_ = val;
189  }
190 
191  private:
192  void initSlow();
193  template <bool emptyOk>
194  StringPiece doSplitKey();
195 
199  enum class NextKeyMode {
200  NONE,
201  INT,
202  STRING,
203  };
205 };
206 
207 template <typename... Args>
208 inline std::string FormatArg::errorStr(Args&&... args) const {
209  return to<std::string>(
210  "invalid format argument {",
211  fullArgString,
212  "}: ",
213  std::forward<Args>(args)...);
214 }
215 
216 template <typename... Args>
217 [[noreturn]] inline void FormatArg::error(Args&&... args) const {
218  throw_exception<BadFormatArg>(errorStr(std::forward<Args>(args)...));
219 }
220 
221 template <bool emptyOk>
223  enforce(nextKeyMode_ != NextKeyMode::INT, "integer key expected");
224  return doSplitKey<emptyOk>();
225 }
226 
227 template <bool emptyOk>
229  if (nextKeyMode_ == NextKeyMode::STRING) {
230  nextKeyMode_ = NextKeyMode::NONE;
231  if (!emptyOk) { // static
232  enforce(!nextKey_.empty(), "non-empty key required");
233  }
234  return nextKey_;
235  }
236 
237  if (key_.empty()) {
238  if (!emptyOk) { // static
239  error("non-empty key required");
240  }
241  return StringPiece();
242  }
243 
244  const char* b = key_.begin();
245  const char* e = key_.end();
246  const char* p;
247  if (e[-1] == ']') {
248  --e;
249  p = static_cast<const char*>(memchr(b, '[', size_t(e - b)));
250  enforce(p != nullptr, "unmatched ']'");
251  } else {
252  p = static_cast<const char*>(memchr(b, '.', size_t(e - b)));
253  }
254  if (p) {
255  key_.assign(p + 1, e);
256  } else {
257  p = e;
258  key_.clear();
259  }
260  if (!emptyOk) { // static
261  enforce(b != p, "non-empty key required");
262  }
263  return StringPiece(b, p);
264 }
265 
267  if (nextKeyMode_ == NextKeyMode::INT) {
268  nextKeyMode_ = NextKeyMode::NONE;
269  return nextIntKey_;
270  }
271  try {
272  return to<int>(doSplitKey<true>());
273  } catch (const std::out_of_range&) {
274  error("integer key required");
275  return 0; // unreached
276  }
277 }
278 
279 } // namespace folly
char b
PskType type
StringPiece key_
Definition: FormatArg.h:196
double val
Definition: String.cpp:273
StringPiece splitKey()
Definition: FormatArg.h:222
void enforce(bool v, Args &&...args) const
Definition: FormatArg.h:76
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
bool thousandsSeparator
Definition: FormatArg.h:131
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
StringPiece nextKey_
Definition: FormatArg.h:198
#define FOLLY_EXPORT
Definition: CPortability.h:133
requires And< SemiMovable< VN >... > &&SemiMovable< E > auto error(E e)
Definition: error.h:48
#define STRING
constexpr bool empty() const
Definition: Range.h:443
std::string errorStr(Args &&...args) const
Definition: FormatArg.h:208
FormatArg(StringPiece sp)
Definition: FormatArg.h:42
void error(Args &&...args) const
Definition: FormatArg.h:217
const char * string
Definition: Conv.cpp:212
bool keyEmpty() const
Definition: FormatArg.h:169
void setNextKey(StringPiece val)
Definition: FormatArg.h:185
Range< const char * > StringPiece
#define UNLIKELY(x)
Definition: Likely.h:48
StringPiece fullArgString
Definition: FormatArg.h:90
NextKeyMode nextKeyMode_
Definition: FormatArg.h:204
StringPiece doSplitKey()
Definition: FormatArg.h:228
void setNextIntKey(int val)
Definition: FormatArg.h:179