Format.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  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. #pragma once
  17. #define FOLLY_FORMAT_H_
  18. #include <cstdio>
  19. #include <stdexcept>
  20. #include <tuple>
  21. #include <type_traits>
  22. #include <folly/CPortability.h>
  23. #include <folly/Conv.h>
  24. #include <folly/FormatArg.h>
  25. #include <folly/Range.h>
  26. #include <folly/String.h>
  27. #include <folly/Traits.h>
  28. // Ignore shadowing warnings within this file, so includers can use -Wshadow.
  29. FOLLY_PUSH_WARNING
  30. FOLLY_GNU_DISABLE_WARNING("-Wshadow")
  31. namespace folly {
  32. // forward declarations
  33. template <bool containerMode, class... Args>
  34. class Formatter;
  35. template <class... Args>
  36. Formatter<false, Args...> format(StringPiece fmt, Args&&... args);
  37. template <class C>
  38. Formatter<true, C> vformat(StringPiece fmt, C&& container);
  39. template <class T, class Enable = void>
  40. class FormatValue;
  41. // meta-attribute to identify formatters in this sea of template weirdness
  42. namespace detail {
  43. class FormatterTag {};
  44. } // namespace detail
  45. /**
  46. * Formatter class.
  47. *
  48. * Note that this class is tricky, as it keeps *references* to its lvalue
  49. * arguments (while it takes ownership of the temporaries), and it doesn't
  50. * copy the passed-in format string. Thankfully, you can't use this
  51. * directly, you have to use format(...) below.
  52. */
  53. /* BaseFormatter class.
  54. * Overridable behaviours:
  55. * You may override the actual formatting of positional parameters in
  56. * `doFormatArg`. The Formatter class provides the default implementation.
  57. *
  58. * You may also override `doFormat` and `getSizeArg`. These override points were
  59. * added to permit static analysis of format strings, when it is inconvenient
  60. * or impossible to instantiate a BaseFormatter with the correct storage
  61. */
  62. template <class Derived, bool containerMode, class... Args>
  63. class BaseFormatter {
  64. public:
  65. /**
  66. * Append to output. out(StringPiece sp) may be called (more than once)
  67. */
  68. template <class Output>
  69. void operator()(Output& out) const;
  70. /**
  71. * Append to a string.
  72. */
  73. template <class Str>
  74. typename std::enable_if<IsSomeString<Str>::value>::type appendTo(
  75. Str& str) const {
  76. auto appender = [&str](StringPiece s) { str.append(s.data(), s.size()); };
  77. (*this)(appender);
  78. }
  79. /**
  80. * Conversion to string
  81. */
  82. std::string str() const {
  83. std::string s;
  84. appendTo(s);
  85. return s;
  86. }
  87. /**
  88. * Conversion to fbstring
  89. */
  90. fbstring fbstr() const {
  91. fbstring s;
  92. appendTo(s);
  93. return s;
  94. }
  95. /**
  96. * Metadata to identify generated children of BaseFormatter
  97. */
  98. typedef detail::FormatterTag IsFormatter;
  99. typedef BaseFormatter BaseType;
  100. private:
  101. typedef std::tuple<Args...> ValueTuple;
  102. static constexpr size_t valueCount = std::tuple_size<ValueTuple>::value;
  103. Derived const& asDerived() const {
  104. return *static_cast<const Derived*>(this);
  105. }
  106. template <size_t K, class Callback>
  107. typename std::enable_if<K == valueCount>::type
  108. doFormatFrom(size_t i, FormatArg& arg, Callback& /*cb*/) const {
  109. arg.error("argument index out of range, max=", i);
  110. }
  111. template <size_t K, class Callback>
  112. typename std::enable_if<(K < valueCount)>::type
  113. doFormatFrom(size_t i, FormatArg& arg, Callback& cb) const {
  114. if (i == K) {
  115. asDerived().template doFormatArg<K>(arg, cb);
  116. } else {
  117. doFormatFrom<K + 1>(i, arg, cb);
  118. }
  119. }
  120. template <class Callback>
  121. void doFormat(size_t i, FormatArg& arg, Callback& cb) const {
  122. return doFormatFrom<0>(i, arg, cb);
  123. }
  124. template <size_t K>
  125. typename std::enable_if<K == valueCount, int>::type getSizeArgFrom(
  126. size_t i,
  127. const FormatArg& arg) const {
  128. arg.error("argument index out of range, max=", i);
  129. }
  130. template <class T>
  131. typename std::enable_if<
  132. std::is_integral<T>::value && !std::is_same<T, bool>::value,
  133. int>::type
  134. getValue(const FormatValue<T>& format, const FormatArg&) const {
  135. return static_cast<int>(format.getValue());
  136. }
  137. template <class T>
  138. typename std::enable_if<
  139. !std::is_integral<T>::value || std::is_same<T, bool>::value,
  140. int>::type
  141. getValue(const FormatValue<T>&, const FormatArg& arg) const {
  142. arg.error("dynamic field width argument must be integral");
  143. }
  144. template <size_t K>
  145. typename std::enable_if <
  146. K<valueCount, int>::type getSizeArgFrom(size_t i, const FormatArg& arg)
  147. const {
  148. if (i == K) {
  149. return getValue(getFormatValue<K>(), arg);
  150. }
  151. return getSizeArgFrom<K + 1>(i, arg);
  152. }
  153. int getSizeArg(size_t i, const FormatArg& arg) const {
  154. return getSizeArgFrom<0>(i, arg);
  155. }
  156. StringPiece str_;
  157. protected:
  158. explicit BaseFormatter(StringPiece str, Args&&... args);
  159. // Not copyable
  160. BaseFormatter(const BaseFormatter&) = delete;
  161. BaseFormatter& operator=(const BaseFormatter&) = delete;
  162. // Movable, but the move constructor and assignment operator are private,
  163. // for the exclusive use of format() (below). This way, you can't create
  164. // a Formatter object, but can handle references to it (for streaming,
  165. // conversion to string, etc) -- which is good, as Formatter objects are
  166. // dangerous (they may hold references).
  167. BaseFormatter(BaseFormatter&&) = default;
  168. BaseFormatter& operator=(BaseFormatter&&) = default;
  169. template <size_t K>
  170. using ArgType = typename std::tuple_element<K, ValueTuple>::type;
  171. template <size_t K>
  172. FormatValue<typename std::decay<ArgType<K>>::type> getFormatValue() const {
  173. return FormatValue<typename std::decay<ArgType<K>>::type>(
  174. std::get<K>(values_));
  175. }
  176. ValueTuple values_;
  177. };
  178. template <bool containerMode, class... Args>
  179. class Formatter : public BaseFormatter<
  180. Formatter<containerMode, Args...>,
  181. containerMode,
  182. Args...> {
  183. private:
  184. explicit Formatter(StringPiece& str, Args&&... args)
  185. : BaseFormatter<
  186. Formatter<containerMode, Args...>,
  187. containerMode,
  188. Args...>(str, std::forward<Args>(args)...) {
  189. static_assert(
  190. !containerMode || sizeof...(Args) == 1,
  191. "Exactly one argument required in container mode");
  192. }
  193. template <size_t K, class Callback>
  194. void doFormatArg(FormatArg& arg, Callback& cb) const {
  195. this->template getFormatValue<K>().format(arg, cb);
  196. }
  197. friend class BaseFormatter<
  198. Formatter<containerMode, Args...>,
  199. containerMode,
  200. Args...>;
  201. template <class... A>
  202. friend Formatter<false, A...> format(StringPiece fmt, A&&... arg);
  203. template <class C>
  204. friend Formatter<true, C> vformat(StringPiece fmt, C&& container);
  205. };
  206. /**
  207. * Formatter objects can be written to streams.
  208. */
  209. template <bool containerMode, class... Args>
  210. std::ostream& operator<<(
  211. std::ostream& out,
  212. const Formatter<containerMode, Args...>& formatter) {
  213. auto writer = [&out](StringPiece sp) {
  214. out.write(sp.data(), std::streamsize(sp.size()));
  215. };
  216. formatter(writer);
  217. return out;
  218. }
  219. /**
  220. * Formatter objects can be written to stdio FILEs.
  221. */
  222. template <class Derived, bool containerMode, class... Args>
  223. void writeTo(
  224. FILE* fp,
  225. const BaseFormatter<Derived, containerMode, Args...>& formatter);
  226. /**
  227. * Create a formatter object.
  228. *
  229. * std::string formatted = format("{} {}", 23, 42).str();
  230. * LOG(INFO) << format("{} {}", 23, 42);
  231. * writeTo(stdout, format("{} {}", 23, 42));
  232. */
  233. template <class... Args>
  234. Formatter<false, Args...> format(StringPiece fmt, Args&&... args) {
  235. return Formatter<false, Args...>(fmt, std::forward<Args>(args)...);
  236. }
  237. /**
  238. * Like format(), but immediately returns the formatted string instead of an
  239. * intermediate format object.
  240. */
  241. template <class... Args>
  242. inline std::string sformat(StringPiece fmt, Args&&... args) {
  243. return format(fmt, std::forward<Args>(args)...).str();
  244. }
  245. /**
  246. * Create a formatter object that takes one argument (of container type)
  247. * and uses that container to get argument values from.
  248. *
  249. * std::map<string, string> map { {"hello", "world"}, {"answer", "42"} };
  250. *
  251. * The following are equivalent:
  252. * format("{0[hello]} {0[answer]}", map);
  253. *
  254. * vformat("{hello} {answer}", map);
  255. *
  256. * but the latter is cleaner.
  257. */
  258. template <class Container>
  259. Formatter<true, Container> vformat(StringPiece fmt, Container&& container) {
  260. return Formatter<true, Container>(fmt, std::forward<Container>(container));
  261. }
  262. /**
  263. * Like vformat(), but immediately returns the formatted string instead of an
  264. * intermediate format object.
  265. */
  266. template <class Container>
  267. inline std::string svformat(StringPiece fmt, Container&& container) {
  268. return vformat(fmt, std::forward<Container>(container)).str();
  269. }
  270. /**
  271. * Exception class thrown when a format key is not found in the given
  272. * associative container keyed by strings. We inherit std::out_of_range for
  273. * compatibility with callers that expect exception to be thrown directly
  274. * by std::map or std::unordered_map.
  275. *
  276. * Having the key be at the end of the message string, we can access it by
  277. * simply adding its offset to what(). Not storing separate std::string key
  278. * makes the exception type small and noexcept-copyable like std::out_of_range,
  279. * and therefore able to fit in-situ in exception_wrapper.
  280. */
  281. class FOLLY_EXPORT FormatKeyNotFoundException : public std::out_of_range {
  282. public:
  283. explicit FormatKeyNotFoundException(StringPiece key);
  284. char const* key() const noexcept {
  285. return what() + kMessagePrefix.size();
  286. }
  287. private:
  288. static constexpr StringPiece const kMessagePrefix = "format key not found: ";
  289. };
  290. /**
  291. * Wrap a sequence or associative container so that out-of-range lookups
  292. * return a default value rather than throwing an exception.
  293. *
  294. * Usage:
  295. * format("[no_such_key"], defaulted(map, 42)) -> 42
  296. */
  297. namespace detail {
  298. template <class Container, class Value>
  299. struct DefaultValueWrapper {
  300. DefaultValueWrapper(const Container& container, const Value& defaultValue)
  301. : container(container), defaultValue(defaultValue) {}
  302. const Container& container;
  303. const Value& defaultValue;
  304. };
  305. } // namespace detail
  306. template <class Container, class Value>
  307. detail::DefaultValueWrapper<Container, Value> defaulted(
  308. const Container& c,
  309. const Value& v) {
  310. return detail::DefaultValueWrapper<Container, Value>(c, v);
  311. }
  312. /**
  313. * Append formatted output to a string.
  314. *
  315. * std::string foo;
  316. * format(&foo, "{} {}", 42, 23);
  317. *
  318. * Shortcut for toAppend(format(...), &foo);
  319. */
  320. template <class Str, class... Args>
  321. typename std::enable_if<IsSomeString<Str>::value>::type
  322. format(Str* out, StringPiece fmt, Args&&... args) {
  323. format(fmt, std::forward<Args>(args)...).appendTo(*out);
  324. }
  325. /**
  326. * Append vformatted output to a string.
  327. */
  328. template <class Str, class Container>
  329. typename std::enable_if<IsSomeString<Str>::value>::type
  330. vformat(Str* out, StringPiece fmt, Container&& container) {
  331. vformat(fmt, std::forward<Container>(container)).appendTo(*out);
  332. }
  333. /**
  334. * Utilities for all format value specializations.
  335. */
  336. namespace format_value {
  337. /**
  338. * Format a string in "val", obeying appropriate alignment, padding, width,
  339. * and precision. Treats Align::DEFAULT as Align::LEFT, and
  340. * Align::PAD_AFTER_SIGN as Align::RIGHT; use formatNumber for
  341. * number-specific formatting.
  342. */
  343. template <class FormatCallback>
  344. void formatString(StringPiece val, FormatArg& arg, FormatCallback& cb);
  345. /**
  346. * Format a number in "val"; the first prefixLen characters form the prefix
  347. * (sign, "0x" base prefix, etc) which must be left-aligned if the alignment
  348. * is Align::PAD_AFTER_SIGN. Treats Align::DEFAULT as Align::LEFT. Ignores
  349. * arg.precision, as that has a different meaning for numbers (not "maximum
  350. * field width")
  351. */
  352. template <class FormatCallback>
  353. void formatNumber(
  354. StringPiece val,
  355. int prefixLen,
  356. FormatArg& arg,
  357. FormatCallback& cb);
  358. /**
  359. * Format a Formatter object recursively. Behaves just like
  360. * formatString(fmt.str(), arg, cb); but avoids creating a temporary
  361. * string if possible.
  362. */
  363. template <
  364. class FormatCallback,
  365. class Derived,
  366. bool containerMode,
  367. class... Args>
  368. void formatFormatter(
  369. const BaseFormatter<Derived, containerMode, Args...>& formatter,
  370. FormatArg& arg,
  371. FormatCallback& cb);
  372. } // namespace format_value
  373. /*
  374. * Specialize folly::FormatValue for your type.
  375. *
  376. * FormatValue<T> is constructed with a (reference-collapsed) T&&, which is
  377. * guaranteed to stay alive until the FormatValue object is destroyed, so you
  378. * may keep a reference (or pointer) to it instead of making a copy.
  379. *
  380. * You must define
  381. * template <class Callback>
  382. * void format(FormatArg& arg, Callback& cb) const;
  383. * with the following semantics: format the value using the given argument.
  384. *
  385. * arg is given by non-const reference for convenience -- it won't be reused,
  386. * so feel free to modify it in place if necessary. (For example, wrap an
  387. * existing conversion but change the default, or remove the "key" when
  388. * extracting an element from a container)
  389. *
  390. * Call the callback to append data to the output. You may call the callback
  391. * as many times as you'd like (or not at all, if you want to output an
  392. * empty string)
  393. */
  394. namespace detail {
  395. template <class T, class Enable = void>
  396. struct IsFormatter : public std::false_type {};
  397. template <class T>
  398. struct IsFormatter<
  399. T,
  400. typename std::enable_if<
  401. std::is_same<typename T::IsFormatter, detail::FormatterTag>::value>::
  402. type> : public std::true_type {};
  403. } // namespace detail
  404. // Deprecated API. formatChecked() et. al. now behave identically to their
  405. // non-Checked counterparts.
  406. template <class... Args>
  407. Formatter<false, Args...> formatChecked(StringPiece fmt, Args&&... args) {
  408. return format(fmt, std::forward<Args>(args)...);
  409. }
  410. template <class... Args>
  411. inline std::string sformatChecked(StringPiece fmt, Args&&... args) {
  412. return formatChecked(fmt, std::forward<Args>(args)...).str();
  413. }
  414. template <class Container>
  415. Formatter<true, Container> vformatChecked(
  416. StringPiece fmt,
  417. Container&& container) {
  418. return vformat(fmt, std::forward<Container>(container));
  419. }
  420. template <class Container>
  421. inline std::string svformatChecked(StringPiece fmt, Container&& container) {
  422. return vformatChecked(fmt, std::forward<Container>(container)).str();
  423. }
  424. template <class Str, class... Args>
  425. typename std::enable_if<IsSomeString<Str>::value>::type
  426. formatChecked(Str* out, StringPiece fmt, Args&&... args) {
  427. formatChecked(fmt, std::forward<Args>(args)...).appendTo(*out);
  428. }
  429. template <class Str, class Container>
  430. typename std::enable_if<IsSomeString<Str>::value>::type
  431. vformatChecked(Str* out, StringPiece fmt, Container&& container) {
  432. vformatChecked(fmt, std::forward<Container>(container)).appendTo(*out);
  433. }
  434. } // namespace folly
  435. #include <folly/Format-inl.h>
  436. FOLLY_POP_WARNING