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