101using RemoveCvref =
typename std::remove_cv_t<std::remove_reference_t<T>>;
103template <
typename T,
typename =
void>
114template <
typename T,
size_t N>
139struct TypeConstant<signed char> : std::integral_constant<Type, Type::kInt> {};
142struct TypeConstant<unsigned char> : std::integral_constant<Type, Type::kUint> {};
145struct TypeConstant<short> : std::integral_constant<Type, Type::kInt> {};
148struct TypeConstant<unsigned short> : std::integral_constant<Type, Type::kUint> {};
154struct TypeConstant<unsigned> : std::integral_constant<Type, Type::kUint> {};
157struct TypeConstant<long> : std::integral_constant<Type, Type::kLongLong> {};
160struct TypeConstant<unsigned long> : std::integral_constant<Type, Type::kUlongLong> {};
163struct TypeConstant<long long> : std::integral_constant<Type, Type::kLongLong> {};
166struct TypeConstant<unsigned long long> : std::integral_constant<Type, Type::kUlongLong> {};
169struct TypeConstant<bool> : std::integral_constant<Type, Type::kBool> {};
172struct TypeConstant<char> : std::integral_constant<Type, Type::kChar> {};
175struct TypeConstant<float> : std::integral_constant<Type, Type::kFloat> {};
178struct TypeConstant<double> : std::integral_constant<Type, Type::kDouble> {};
181struct TypeConstant<const char*> : std::integral_constant<Type, Type::kCstring> {};
184struct TypeConstant<char*> : std::integral_constant<Type, Type::kCstring> {};
187struct TypeConstant<
std::string_view> : std::integral_constant<Type, Type::kString> {};
193struct TypeConstant<char[N]> : std::integral_constant<Type, Type::kCstring> {};
196struct TypeConstant<const char[N]> : std::integral_constant<Type, Type::kCstring> {};
199struct TypeConstant<T*> : std::integral_constant<Type, Type::kPointer> {};
201template <
typename UIntT>
213template <
typename CharT,
typename UIntT>
215 CharT* end = buf + num_digits;
217 while (value >= 10) {
218 unsigned digit =
static_cast<unsigned>(value % 10);
219 *--end =
static_cast<CharT
>(
'0' + digit);
223 *--end =
static_cast<CharT
>(
'0' + value);
225 return buf + num_digits;
230 inline StringWriter(
char* buf,
size_t size) noexcept : begin_(buf), ptr_(buf), end_(buf + size) {}
232 inline char*
out() const noexcept {
return ptr_; }
234 inline size_t written() const noexcept {
return static_cast<size_t>(ptr_ - begin_); }
236 inline size_t total_size() const noexcept {
return total_size_; }
246 inline void write(
const char* s,
size_t count) {
247 total_size_ += count;
249 size_t avail =
static_cast<size_t>(end_ - ptr_);
250 size_t n = (count <= avail) ? count : avail;
253 std::memcpy(ptr_, s, n);
258 inline void write(std::string_view sv) {
write(sv.data(), sv.size()); }
261 char* begin_{
nullptr};
264 size_t total_size_{0};
267template <
typename OutputItT>
272 inline OutputItT
out() const noexcept {
return out_; }
274 inline size_t size() const noexcept {
return count_; }
281 inline void write(
const char* s,
size_t count) {
282 for (
size_t i = 0; i < count; ++i) {
289 inline void write(std::string_view sv) {
write(sv.data(), sv.size()); }
296template <
typename CharT>
357 template <
typename T>
361template <
typename CharT>
366 template <
typename T>
368 if constexpr (std::is_enum_v<T>) {
369 using U = std::underlying_type_t<T>;
376 static_assert(!
sizeof(T),
377 "[vlink::format] unsupported type for format_to/MLOG, "
378 "convert to string first");
390template <
typename CharT,
typename... ArgsT>
392 static constexpr size_t kNumArgs =
sizeof...(ArgsT);
395 template <
typename... T>
399template <
typename CharT>
404 template <
typename... ArgsT>
406 : args_(store.args), size_(sizeof...(ArgsT)) {}
410 constexpr size_t size()
const {
return size_; }
419template <
typename CharT,
typename WriterT>
426 const char* p = fmt.data();
427 const char* end = p + fmt.size();
433 if (p != end && *p ==
'}') {
460 if (arg_id < args.
size()) {
461 write_arg(args.
get(arg_id++));
469 size_t index = arg_id;
470 bool has_explicit_index =
false;
472 if (*p >=
'0' && *p <=
'9') {
474 has_explicit_index =
true;
476 while (p != end && *p >=
'0' && *p <=
'9') {
477 index = index * 10 +
static_cast<size_t>(*p++ -
'0');
481 while (p != end && *p !=
'}') {
486 if (index < args.
size()) {
487 write_arg(args.
get(index));
490 if (!has_explicit_index) {
499 inline auto out()
const {
return writer_.out(); }
501 template <
typename W = WriterT>
503 return writer_.total_size();
506 inline size_t size()
const {
return writer_.size(); }
509 void write_int(
int value) {
512 write_uint(
static_cast<unsigned>(-(value + 1)) + 1);
514 write_uint(
static_cast<unsigned>(value));
518 void write_uint(
unsigned value) {
522 writer_.write(buf,
static_cast<size_t>(num_digits));
525 void write_long_long(
long long value) {
528 write_ulong_long(
static_cast<unsigned long long>(-(value + 1)) + 1);
530 write_ulong_long(
static_cast<unsigned long long>(value));
534 void write_ulong_long(
unsigned long long value) {
538 writer_.write(buf,
static_cast<size_t>(num_digits));
541 void write_bool(
bool value) {
543 writer_.write(
"true", 4);
545 writer_.write(
"false", 5);
549 void write_char(
char value) { writer_.write(value); }
551 void write_string(
const char* str) {
553 writer_.write(str, std::strlen(str));
555 writer_.write(
"(null)", 6);
559 void write_string_view(std::string_view sv) { writer_.write(sv); }
561 void write_pointer(
const void* ptr) {
562 static constexpr const char kHexDigits[] =
"0123456789abcdef";
563 static_assert(
sizeof(uintptr_t) <= 8,
"pointer size > 64bit not supported");
567 auto value =
reinterpret_cast<uintptr_t
>(ptr);
569 writer_.write(
"0x", 2);
572 buf[--i] = kHexDigits[value & 0xF];
574 }
while (value != 0);
576 writer_.write(buf + i,
static_cast<size_t>(16 - i));
579 void write_float(
float value) {
581 int len = snprintf(buf,
sizeof(buf),
"%g",
static_cast<double>(value));
583 if (len > 0 && len <
static_cast<int>(
sizeof(buf))) {
584 writer_.write(buf,
static_cast<size_t>(len));
588 void write_double(
double value) {
590 int len = snprintf(buf,
sizeof(buf),
"%g", value);
592 if (len > 0 && len <
static_cast<int>(
sizeof(buf))) {
593 writer_.write(buf,
static_cast<size_t>(len));
597 void write_arg(
const FormatArg<CharT>& arg) {
598 switch (arg.type()) {
600 write_int(arg.value().int_value);
603 write_uint(arg.value().uint_value);
606 write_long_long(arg.value().long_long_value);
609 write_ulong_long(arg.value().ulong_long_value);
612 write_bool(arg.value().bool_value);
615 write_char(arg.value().char_value);
618 write_float(arg.value().float_value);
621 write_double(arg.value().double_value);
624 write_string(arg.value().string_value);
627 write_string_view(arg.value().string_view_value);
630 write_pointer(arg.value().pointer_value);
652template <
typename... T>
660 template <
typename StrT, std::enable_if_t<std::is_convertible_v<const StrT&, std::
string_view>,
int> = 0>
663 inline operator std::string_view()
const {
return str; }
664 std::string_view
get()
const {
return str; }
676template <
typename... T>
686template <
typename... ArgsT>
697template <
typename OutputItT>
719template <
typename... ArgsT>
726 writer.
format(fmt.get(), fargs);
729 return {writer.
out(), total, total > n};
756template <
size_t N,
typename... ArgsT>
759 return {result.out, result.size, result.truncated};
776template <
typename OutputItT,
typename... ArgsT,
777 std::enable_if_t<detail::kIsOutputIterator<detail::RemoveCvref<OutputItT>> &&
778 !std::is_array_v<std::remove_reference_t<OutputItT>>,
786 writer.
format(fmt.get(), fargs);
Platform-independent macro definitions for the VLink library.
#define VLIKELY(...)
Shorthand alias for VLINK_LIKELY. Hints that the expression is likely true.
定义 macros.h:297