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:
Vincent Ambo 2020-11-21 14:43:54 +01:00
parent cc27324d02
commit 082c006c04
854 changed files with 11260 additions and 5296 deletions

View file

@ -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