merge(3p/absl): subtree merge of Abseil up to e19260f
... notably, this includes Abseil's own StatusOr type, which conflicted with our implementation (that was taken from TensorFlow). Change-Id: Ie7d6764b64055caaeb8dc7b6b9d066291e6b538f
This commit is contained in:
parent
cc27324d02
commit
082c006c04
854 changed files with 11260 additions and 5296 deletions
270
third_party/abseil_cpp/absl/strings/str_format.h
vendored
270
third_party/abseil_cpp/absl/strings/str_format.h
vendored
|
|
@ -63,6 +63,9 @@
|
|||
// loosely typed. `FormatUntyped()` is not a template and does not perform
|
||||
// any compile-time checking of the format string; instead, it returns a
|
||||
// boolean from a runtime check.
|
||||
//
|
||||
// In addition, the `str_format` library provides extension points for
|
||||
// augmenting formatting to new types. See "StrFormat Extensions" below.
|
||||
|
||||
#ifndef ABSL_STRINGS_STR_FORMAT_H_
|
||||
#define ABSL_STRINGS_STR_FORMAT_H_
|
||||
|
|
@ -278,9 +281,36 @@ using FormatSpec = str_format_internal::FormatSpecTemplate<
|
|||
// } else {
|
||||
// ... error case ...
|
||||
// }
|
||||
|
||||
#if defined(__cpp_nontype_template_parameter_auto)
|
||||
// If C++17 is available, an 'extended' format is also allowed that can specify
|
||||
// multiple conversion characters per format argument, using a combination of
|
||||
// `absl::FormatConversionCharSet` enum values (logically a set union)
|
||||
// via the `|` operator. (Single character-based arguments are still accepted,
|
||||
// but cannot be combined). Some common conversions also have predefined enum
|
||||
// values, such as `absl::FormatConversionCharSet::kIntegral`.
|
||||
//
|
||||
// Example:
|
||||
// // Extended format supports multiple conversion characters per argument,
|
||||
// // specified via a combination of `FormatConversionCharSet` enums.
|
||||
// using MyFormat = absl::ParsedFormat<absl::FormatConversionCharSet::d |
|
||||
// absl::FormatConversionCharSet::x>;
|
||||
// MyFormat GetFormat(bool use_hex) {
|
||||
// if (use_hex) return MyFormat("foo %x bar");
|
||||
// return MyFormat("foo %d bar");
|
||||
// }
|
||||
// // `format` can be used with any value that supports 'd' and 'x',
|
||||
// // like `int`.
|
||||
// auto format = GetFormat(use_hex);
|
||||
// value = StringF(format, i);
|
||||
template <auto... Conv>
|
||||
using ParsedFormat = absl::str_format_internal::ExtendedParsedFormat<
|
||||
absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
|
||||
#else
|
||||
template <char... Conv>
|
||||
using ParsedFormat = str_format_internal::ExtendedParsedFormat<
|
||||
absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
|
||||
#endif // defined(__cpp_nontype_template_parameter_auto)
|
||||
|
||||
// StrFormat()
|
||||
//
|
||||
|
|
@ -537,6 +567,246 @@ ABSL_MUST_USE_RESULT inline bool FormatUntyped(
|
|||
str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// StrFormat Extensions
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// AbslFormatConvert()
|
||||
//
|
||||
// The StrFormat library provides a customization API for formatting
|
||||
// user-defined types using absl::StrFormat(). The API relies on detecting an
|
||||
// overload in the user-defined type's namespace of a free (non-member)
|
||||
// `AbslFormatConvert()` function, usually as a friend definition with the
|
||||
// following signature:
|
||||
//
|
||||
// absl::FormatConvertResult<...> AbslFormatConvert(
|
||||
// const X& value,
|
||||
// const absl::FormatConversionSpec& spec,
|
||||
// absl::FormatSink *sink);
|
||||
//
|
||||
// An `AbslFormatConvert()` overload for a type should only be declared in the
|
||||
// same file and namespace as said type.
|
||||
//
|
||||
// The abstractions within this definition include:
|
||||
//
|
||||
// * An `absl::FormatConversionSpec` to specify the fields to pull from a
|
||||
// user-defined type's format string
|
||||
// * An `absl::FormatSink` to hold the converted string data during the
|
||||
// conversion process.
|
||||
// * An `absl::FormatConvertResult` to hold the status of the returned
|
||||
// formatting operation
|
||||
//
|
||||
// The return type encodes all the conversion characters that your
|
||||
// AbslFormatConvert() routine accepts. The return value should be {true}.
|
||||
// A return value of {false} will result in `StrFormat()` returning
|
||||
// an empty string. This result will be propagated to the result of
|
||||
// `FormatUntyped`.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// struct Point {
|
||||
// // To add formatting support to `Point`, we simply need to add a free
|
||||
// // (non-member) function `AbslFormatConvert()`. This method interprets
|
||||
// // `spec` to print in the request format. The allowed conversion characters
|
||||
// // can be restricted via the type of the result, in this example
|
||||
// // string and integral formatting are allowed (but not, for instance
|
||||
// // floating point characters like "%f"). You can add such a free function
|
||||
// // using a friend declaration within the body of the class:
|
||||
// friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
|
||||
// absl::FormatConversionCharSet::kIntegral>
|
||||
// AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
|
||||
// absl::FormatSink* s) {
|
||||
// if (spec.conversion_char() == absl::FormatConversionChar::s) {
|
||||
// s->Append(absl::StrCat("x=", p.x, " y=", p.y));
|
||||
// } else {
|
||||
// s->Append(absl::StrCat(p.x, ",", p.y));
|
||||
// }
|
||||
// return {true};
|
||||
// }
|
||||
//
|
||||
// int x;
|
||||
// int y;
|
||||
// };
|
||||
|
||||
// clang-format off
|
||||
|
||||
// FormatConversionChar
|
||||
//
|
||||
// Specifies the formatting character provided in the format string
|
||||
// passed to `StrFormat()`.
|
||||
enum class FormatConversionChar : uint8_t {
|
||||
c, s, // text
|
||||
d, i, o, u, x, X, // int
|
||||
f, F, e, E, g, G, a, A, // float
|
||||
n, p // misc
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// FormatConversionSpec
|
||||
//
|
||||
// Specifies modifications to the conversion of the format string, through use
|
||||
// of one or more format flags in the source format string.
|
||||
class FormatConversionSpec {
|
||||
public:
|
||||
// FormatConversionSpec::is_basic()
|
||||
//
|
||||
// Indicates that width and precision are not specified, and no additional
|
||||
// flags are set for this conversion character in the format string.
|
||||
bool is_basic() const { return impl_.is_basic(); }
|
||||
|
||||
// FormatConversionSpec::has_left_flag()
|
||||
//
|
||||
// Indicates whether the result should be left justified for this conversion
|
||||
// character in the format string. This flag is set through use of a '-'
|
||||
// character in the format string. E.g. "%-s"
|
||||
bool has_left_flag() const { return impl_.has_left_flag(); }
|
||||
|
||||
// FormatConversionSpec::has_show_pos_flag()
|
||||
//
|
||||
// Indicates whether a sign column is prepended to the result for this
|
||||
// conversion character in the format string, even if the result is positive.
|
||||
// This flag is set through use of a '+' character in the format string.
|
||||
// E.g. "%+d"
|
||||
bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }
|
||||
|
||||
// FormatConversionSpec::has_sign_col_flag()
|
||||
//
|
||||
// Indicates whether a mandatory sign column is added to the result for this
|
||||
// conversion character. This flag is set through use of a space character
|
||||
// (' ') in the format string. E.g. "% i"
|
||||
bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }
|
||||
|
||||
// FormatConversionSpec::has_alt_flag()
|
||||
//
|
||||
// Indicates whether an "alternate" format is applied to the result for this
|
||||
// conversion character. Alternative forms depend on the type of conversion
|
||||
// character, and unallowed alternatives are undefined. This flag is set
|
||||
// through use of a '#' character in the format string. E.g. "%#h"
|
||||
bool has_alt_flag() const { return impl_.has_alt_flag(); }
|
||||
|
||||
// FormatConversionSpec::has_zero_flag()
|
||||
//
|
||||
// Indicates whether zeroes should be prepended to the result for this
|
||||
// conversion character instead of spaces. This flag is set through use of the
|
||||
// '0' character in the format string. E.g. "%0f"
|
||||
bool has_zero_flag() const { return impl_.has_zero_flag(); }
|
||||
|
||||
// FormatConversionSpec::conversion_char()
|
||||
//
|
||||
// Returns the underlying conversion character.
|
||||
FormatConversionChar conversion_char() const {
|
||||
return impl_.conversion_char();
|
||||
}
|
||||
|
||||
// FormatConversionSpec::width()
|
||||
//
|
||||
// Returns the specified width (indicated through use of a non-zero integer
|
||||
// value or '*' character) of the conversion character. If width is
|
||||
// unspecified, it returns a negative value.
|
||||
int width() const { return impl_.width(); }
|
||||
|
||||
// FormatConversionSpec::precision()
|
||||
//
|
||||
// Returns the specified precision (through use of the '.' character followed
|
||||
// by a non-zero integer value or '*' character) of the conversion character.
|
||||
// If precision is unspecified, it returns a negative value.
|
||||
int precision() const { return impl_.precision(); }
|
||||
|
||||
private:
|
||||
explicit FormatConversionSpec(
|
||||
str_format_internal::FormatConversionSpecImpl impl)
|
||||
: impl_(impl) {}
|
||||
|
||||
friend str_format_internal::FormatConversionSpecImpl;
|
||||
|
||||
absl::str_format_internal::FormatConversionSpecImpl impl_;
|
||||
};
|
||||
|
||||
// Type safe OR operator for FormatConversionCharSet to allow accepting multiple
|
||||
// conversion chars in custom format converters.
|
||||
constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
|
||||
FormatConversionCharSet b) {
|
||||
return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |
|
||||
static_cast<uint64_t>(b));
|
||||
}
|
||||
|
||||
// FormatConversionCharSet
|
||||
//
|
||||
// Specifies the _accepted_ conversion types as a template parameter to
|
||||
// FormatConvertResult for custom implementations of `AbslFormatConvert`.
|
||||
// Note the helper predefined alias definitions (kIntegral, etc.) below.
|
||||
enum class FormatConversionCharSet : uint64_t {
|
||||
// text
|
||||
c = str_format_internal::FormatConversionCharToConvInt('c'),
|
||||
s = str_format_internal::FormatConversionCharToConvInt('s'),
|
||||
// integer
|
||||
d = str_format_internal::FormatConversionCharToConvInt('d'),
|
||||
i = str_format_internal::FormatConversionCharToConvInt('i'),
|
||||
o = str_format_internal::FormatConversionCharToConvInt('o'),
|
||||
u = str_format_internal::FormatConversionCharToConvInt('u'),
|
||||
x = str_format_internal::FormatConversionCharToConvInt('x'),
|
||||
X = str_format_internal::FormatConversionCharToConvInt('X'),
|
||||
// Float
|
||||
f = str_format_internal::FormatConversionCharToConvInt('f'),
|
||||
F = str_format_internal::FormatConversionCharToConvInt('F'),
|
||||
e = str_format_internal::FormatConversionCharToConvInt('e'),
|
||||
E = str_format_internal::FormatConversionCharToConvInt('E'),
|
||||
g = str_format_internal::FormatConversionCharToConvInt('g'),
|
||||
G = str_format_internal::FormatConversionCharToConvInt('G'),
|
||||
a = str_format_internal::FormatConversionCharToConvInt('a'),
|
||||
A = str_format_internal::FormatConversionCharToConvInt('A'),
|
||||
// misc
|
||||
n = str_format_internal::FormatConversionCharToConvInt('n'),
|
||||
p = str_format_internal::FormatConversionCharToConvInt('p'),
|
||||
|
||||
// Used for width/precision '*' specification.
|
||||
kStar = static_cast<uint64_t>(
|
||||
absl::str_format_internal::FormatConversionCharSetInternal::kStar),
|
||||
// Some predefined values:
|
||||
kIntegral = d | i | u | o | x | X,
|
||||
kFloating = a | e | f | g | A | E | F | G,
|
||||
kNumeric = kIntegral | kFloating,
|
||||
kString = s,
|
||||
kPointer = p,
|
||||
};
|
||||
|
||||
// FormatSink
|
||||
//
|
||||
// An abstraction to which conversions write their string data.
|
||||
//
|
||||
class FormatSink {
|
||||
public:
|
||||
// Appends `count` copies of `ch`.
|
||||
void Append(size_t count, char ch) { sink_->Append(count, ch); }
|
||||
|
||||
void Append(string_view v) { sink_->Append(v); }
|
||||
|
||||
// Appends the first `precision` bytes of `v`. If this is less than
|
||||
// `width`, spaces will be appended first (if `left` is false), or
|
||||
// after (if `left` is true) to ensure the total amount appended is
|
||||
// at least `width`.
|
||||
bool PutPaddedString(string_view v, int width, int precision, bool left) {
|
||||
return sink_->PutPaddedString(v, width, precision, left);
|
||||
}
|
||||
|
||||
private:
|
||||
friend str_format_internal::FormatSinkImpl;
|
||||
explicit FormatSink(str_format_internal::FormatSinkImpl* s) : sink_(s) {}
|
||||
str_format_internal::FormatSinkImpl* sink_;
|
||||
};
|
||||
|
||||
// FormatConvertResult
|
||||
//
|
||||
// Indicates whether a call to AbslFormatConvert() was successful.
|
||||
// This return type informs the StrFormat extension framework (through
|
||||
// ADL but using the return type) of what conversion characters are supported.
|
||||
// It is strongly discouraged to return {false}, as this will result in an
|
||||
// empty string in StrFormat.
|
||||
template <FormatConversionCharSet C>
|
||||
struct FormatConvertResult {
|
||||
bool value;
|
||||
};
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue