#ifndef ABSL_STRINGS_STR_FORMAT_H_
#define ABSL_STRINGS_STR_FORMAT_H_
#include <cstdint>
#include <cstdio>
#include <string>
#include <type_traits>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/strings/internal/str_format/arg.h"
#include "absl/strings/internal/str_format/bind.h"
#include "absl/strings/internal/str_format/checker.h"
#include "absl/strings/internal/str_format/extension.h"
#include "absl/strings/internal/str_format/parser.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
class UntypedFormatSpec {
public:
UntypedFormatSpec() = delete;
UntypedFormatSpec(const UntypedFormatSpec&) = delete;
UntypedFormatSpec& operator=(const UntypedFormatSpec&) = delete;
explicit UntypedFormatSpec(string_view s) : spec_(s) {}
protected:
explicit UntypedFormatSpec(
absl::Nonnull<const str_format_internal::ParsedFormatBase*> pc)
: spec_(pc) {}
private:
friend str_format_internal::UntypedFormatSpecImpl;
str_format_internal::UntypedFormatSpecImpl spec_;
};
template <typename T>
str_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) {
return str_format_internal::StreamedWrapper<T>(v);
}
class FormatCountCapture {
public:
explicit FormatCountCapture(absl::Nonnull<int*> p) : p_(p) {}
private:
friend struct str_format_internal::FormatCountCaptureHelper;
absl::Nonnull<int*> Unused() { return p_; }
absl::Nonnull<int*> p_;
};
template <typename... Args>
using FormatSpec = str_format_internal::FormatSpecTemplate<
str_format_internal::ArgumentToConv<Args>()...>;
#if defined(__cpp_nontype_template_parameter_auto)
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
template <typename... Args>
ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format,
const Args&... args) {
return str_format_internal::FormatPack(
str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
template <typename... Args>
std::string& StrAppendFormat(absl::Nonnull<std::string*> dst,
const FormatSpec<Args...>& format,
const Args&... args) {
return str_format_internal::AppendPack(
dst, str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
template <typename... Args>
ABSL_MUST_USE_RESULT str_format_internal::Streamable StreamFormat(
const FormatSpec<Args...>& format, const Args&... args) {
return str_format_internal::Streamable(
str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
template <typename... Args>
int PrintF(const FormatSpec<Args...>& format, const Args&... args) {
return str_format_internal::FprintF(
stdout, str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
template <typename... Args>
int FPrintF(absl::Nonnull<std::FILE*> output, const FormatSpec<Args...>& format,
const Args&... args) {
return str_format_internal::FprintF(
output, str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
template <typename... Args>
int SNPrintF(absl::Nonnull<char*> output, std::size_t size,
const FormatSpec<Args...>& format, const Args&... args) {
return str_format_internal::SnprintF(
output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
class FormatRawSink {
public:
template <typename T,
typename = typename std::enable_if<std::is_constructible<
str_format_internal::FormatRawSinkImpl, T*>::value>::type>
FormatRawSink(absl::Nonnull<T*> raw) : sink_(raw) {}
private:
friend str_format_internal::FormatRawSinkImpl;
str_format_internal::FormatRawSinkImpl sink_;
};
template <typename... Args>
bool Format(FormatRawSink raw_sink, const FormatSpec<Args...>& format,
const Args&... args) {
return str_format_internal::FormatUntyped(
str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
using FormatArg = str_format_internal::FormatArgImpl;
ABSL_MUST_USE_RESULT inline bool FormatUntyped(
FormatRawSink raw_sink, const UntypedFormatSpec& format,
absl::Span<const FormatArg> args) {
return str_format_internal::FormatUntyped(
str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
}
enum class FormatConversionChar : uint8_t {
c, s, d, i, o, u, x, X, f, F, e, E, g, G, a, A, n, p, v };
class FormatConversionSpec {
public:
bool is_basic() const { return impl_.is_basic(); }
bool has_left_flag() const { return impl_.has_left_flag(); }
bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }
bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }
bool has_alt_flag() const { return impl_.has_alt_flag(); }
bool has_zero_flag() const { return impl_.has_zero_flag(); }
FormatConversionChar conversion_char() const {
return impl_.conversion_char();
}
int width() const { return impl_.width(); }
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_;
};
constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
FormatConversionCharSet b) {
return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |
static_cast<uint64_t>(b));
}
enum class FormatConversionCharSet : uint64_t {
c = str_format_internal::FormatConversionCharToConvInt('c'),
s = str_format_internal::FormatConversionCharToConvInt('s'),
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'),
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'),
n = str_format_internal::FormatConversionCharToConvInt('n'),
p = str_format_internal::FormatConversionCharToConvInt('p'),
v = str_format_internal::FormatConversionCharToConvInt('v'),
kStar = static_cast<uint64_t>(
absl::str_format_internal::FormatConversionCharSetInternal::kStar),
kIntegral = d | i | u | o | x | X,
kFloating = a | e | f | g | A | E | F | G,
kNumeric = kIntegral | kFloating,
kString = s,
kPointer = p,
};
class FormatSink {
public:
void Append(size_t count, char ch) { sink_->Append(count, ch); }
void Append(string_view v) { sink_->Append(v); }
bool PutPaddedString(string_view v, int width, int precision, bool left) {
return sink_->PutPaddedString(v, width, precision, left);
}
friend void AbslFormatFlush(absl::Nonnull<FormatSink*> sink,
absl::string_view v) {
sink->Append(v);
}
private:
friend str_format_internal::FormatSinkImpl;
explicit FormatSink(absl::Nonnull<str_format_internal::FormatSinkImpl*> s)
: sink_(s) {}
absl::Nonnull<str_format_internal::FormatSinkImpl*> sink_;
};
template <FormatConversionCharSet C>
struct FormatConvertResult {
bool value;
};
ABSL_NAMESPACE_END
}
#endif