123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- #include "format.h"
- #include "string.h"
- namespace NYT::NDetail {
- ////////////////////////////////////////////////////////////////////////////////
- template <class TValue>
- void FormatValueViaSprintf(
- TStringBuilderBase* builder,
- TValue value,
- TStringBuf format,
- TStringBuf genericSpec)
- {
- constexpr int MaxFormatSize = 64;
- constexpr int SmallResultSize = 64;
- auto copyFormat = [] (char* destination, const char* source, int length) {
- int position = 0;
- for (int index = 0; index < length; ++index) {
- if (IsQuotationSpecSymbol(source[index])) {
- continue;
- }
- destination[position] = source[index];
- ++position;
- }
- return destination + position;
- };
- char formatBuf[MaxFormatSize];
- YT_VERIFY(format.length() >= 1 && format.length() <= MaxFormatSize - 2); // one for %, one for \0
- formatBuf[0] = '%';
- if (format.back() == GenericSpecSymbol) {
- char* formatEnd = copyFormat(formatBuf + 1, format.begin(), format.length() - 1);
- ::memcpy(formatEnd, genericSpec.begin(), genericSpec.length());
- formatEnd[genericSpec.length()] = '\0';
- } else {
- char* formatEnd = copyFormat(formatBuf + 1, format.begin(), format.length());
- *formatEnd = '\0';
- }
- char* result = builder->Preallocate(SmallResultSize);
- size_t resultSize = ::snprintf(result, SmallResultSize, formatBuf, value);
- if (resultSize >= SmallResultSize) {
- result = builder->Preallocate(resultSize + 1);
- YT_VERIFY(::snprintf(result, resultSize + 1, formatBuf, value) == static_cast<int>(resultSize));
- }
- builder->Advance(resultSize);
- }
- #define XX(type) \
- template \
- void FormatValueViaSprintf( \
- TStringBuilderBase* builder, \
- type value, \
- TStringBuf format, \
- TStringBuf genericSpec);
- XX(i32)
- XX(ui32)
- XX(i64)
- XX(ui64)
- XX(float)
- XX(double)
- XX(const void*)
- #undef XX
- template <class TValue>
- void FormatIntValue(
- TStringBuilderBase* builder,
- TValue value,
- TStringBuf format,
- TStringBuf genericSpec)
- {
- if (format == TStringBuf("v")) {
- constexpr int MaxResultSize = 64;
- char buffer[MaxResultSize];
- char* end = buffer + MaxResultSize;
- char* start = WriteDecIntToBufferBackwards(end, value);
- builder->AppendString(TStringBuf(start, end));
- } else if (format == TStringBuf("x") || format == TStringBuf("X")) {
- constexpr int MaxResultSize = 64;
- char buffer[MaxResultSize];
- char* end = buffer + MaxResultSize;
- char* start = WriteHexIntToBufferBackwards(end, value, format[0] == 'X');
- builder->AppendString(TStringBuf(start, end));
- } else {
- FormatValueViaSprintf(builder, value, format, genericSpec);
- }
- }
- #define XX(type) \
- template \
- void FormatIntValue( \
- TStringBuilderBase* builder, \
- type value, \
- TStringBuf format, \
- TStringBuf genericSpec);
- XX(i32)
- XX(ui32)
- XX(i64)
- XX(ui64)
- #undef XX
- void FormatPointerValue(
- TStringBuilderBase* builder,
- const void* value,
- TStringBuf format)
- {
- static_assert(sizeof(value) == sizeof(ui64));
- if (format == TStringBuf("p") || format == TStringBuf("v")) {
- builder->AppendString(TStringBuf("0x"));
- FormatValue(builder, reinterpret_cast<ui64>(value), TStringBuf("x"));
- } else if (format == TStringBuf("x") || format == TStringBuf("X")) {
- FormatValue(builder, reinterpret_cast<ui64>(value), format);
- } else {
- builder->AppendString("<invalid pointer format>");
- }
- }
- ////////////////////////////////////////////////////////////////////////////////
- } // namespace NYT::NDetail
|