diff options
author | Marco Bubke <marco.bubke@qt.io> | 2024-03-15 09:01:32 +0100 |
---|---|---|
committer | Marco Bubke <marco.bubke@qt.io> | 2024-03-20 11:13:33 +0000 |
commit | c9527e03419de8e5edd3527e4bc1be4497e0e3bd (patch) | |
tree | 4613ca770d5bbe3a4f42ee34ba81d49a5b435a42 /src/libs | |
parent | bfaef2cbb7231abdc8c94e266a157899da884230 (diff) |
Sqlite: Improve tracing
Change-Id: Id5d6ee448a7f2cf06cda2e2776f3dbbe7c8f66c4
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Diffstat (limited to 'src/libs')
-rw-r--r-- | src/libs/nanotrace/nanotracehr.h | 6 | ||||
-rw-r--r-- | src/libs/sqlite/sqlitebasestatement.cpp | 207 | ||||
-rw-r--r-- | src/libs/sqlite/sqlitebasestatement.h | 63 | ||||
-rw-r--r-- | src/libs/utils/smallstring.h | 15 |
4 files changed, 226 insertions, 65 deletions
diff --git a/src/libs/nanotrace/nanotracehr.h b/src/libs/nanotrace/nanotracehr.h index ac29bce928..ded7137539 100644 --- a/src/libs/nanotrace/nanotracehr.h +++ b/src/libs/nanotrace/nanotracehr.h @@ -147,6 +147,12 @@ void convertToString(String &string, long long number) } template<typename String> +void convertToString(String &string, std::size_t number) +{ + string.append(Utils::SmallString::number(number)); +} + +template<typename String> void convertToString(String &string, double number) { string.append(Utils::SmallString::number(number)); diff --git a/src/libs/sqlite/sqlitebasestatement.cpp b/src/libs/sqlite/sqlitebasestatement.cpp index c340c52a0e..9fa1638d38 100644 --- a/src/libs/sqlite/sqlitebasestatement.cpp +++ b/src/libs/sqlite/sqlitebasestatement.cpp @@ -26,30 +26,35 @@ extern "C" int sqlite3_carray_bind( namespace Sqlite { -namespace { -using TraceFile = NanotraceHR::TraceFile<sqliteTracingStatus()>; - -TraceFile traceFile{"sqlite.json"}; +TraceFile &traceFile() +{ + static TraceFile traceFile{"tracing.json"}; -thread_local NanotraceHR::EventQueue<NanotraceHR::StringViewTraceEvent, sqliteTracingStatus()> eventQueue( - traceFile); + return traceFile; +} -NanotraceHR::StringViewCategory<sqliteTracingStatus()> &sqliteLowLevelCategory(); +namespace { -thread_local NanotraceHR::StringViewCategory<sqliteTracingStatus()> sqliteLowLevelCategory_{ - "sqlite low level"_t, eventQueue, sqliteLowLevelCategory}; +thread_local NanotraceHR::EventQueue<NanotraceHR::StringViewWithStringArgumentsTraceEvent, + sqliteTracingStatus()> + eventQueue(traceFile()); -NanotraceHR::StringViewCategory<sqliteTracingStatus()> &sqliteLowLevelCategory() +NanotraceHR::StringViewWithStringArgumentsCategory<sqliteTracingStatus()> &sqliteLowLevelCategory() { + thread_local NanotraceHR::StringViewWithStringArgumentsCategory<sqliteTracingStatus()> + sqliteLowLevelCategory_{"sqlite low level"_t, eventQueue, sqliteLowLevelCategory}; return sqliteLowLevelCategory_; } -thread_local NanotraceHR::StringViewCategory<sqliteTracingStatus()> sqliteHighLevelCategory_{ - "sqlite high level"_t, eventQueue, sqliteHighLevelCategory}; +using NanotraceHR::keyValue; + } // namespace -NanotraceHR::StringViewCategory<sqliteTracingStatus()> &sqliteHighLevelCategory() +NanotraceHR::StringViewWithStringArgumentsCategory<sqliteTracingStatus()> &sqliteHighLevelCategory() { + thread_local NanotraceHR::StringViewWithStringArgumentsCategory<sqliteTracingStatus()> + sqliteHighLevelCategory_{"sqlite high level"_t, eventQueue, sqliteHighLevelCategory}; + return sqliteHighLevelCategory_; } @@ -107,14 +112,18 @@ void BaseStatement::waitForUnlockNotify() const void BaseStatement::reset() const noexcept { - NanotraceHR::Tracer tracer{"reset"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"reset"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle())}; sqlite3_reset(m_compiledStatement.get()); } bool BaseStatement::next() const { - NanotraceHR::Tracer tracer{"next"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"next"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle())}; int resultCode; do { @@ -141,7 +150,10 @@ void BaseStatement::step() const void BaseStatement::bindNull(int index) { - NanotraceHR::Tracer tracer{"bind null"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"bind null"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("index", index)}; int resultCode = sqlite3_bind_null(m_compiledStatement.get(), index); if (resultCode != SQLITE_OK) @@ -155,7 +167,11 @@ void BaseStatement::bind(int index, NullValue) void BaseStatement::bind(int index, int value) { - NanotraceHR::Tracer tracer{"bind int"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"bind int"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("index", index), + keyValue("value", value)}; int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value); if (resultCode != SQLITE_OK) @@ -164,7 +180,11 @@ void BaseStatement::bind(int index, int value) void BaseStatement::bind(int index, long long value) { - NanotraceHR::Tracer tracer{"bind long long"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"bind long long"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("index", index), + keyValue("value", value)}; int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value); if (resultCode != SQLITE_OK) @@ -173,7 +193,11 @@ void BaseStatement::bind(int index, long long value) void BaseStatement::bind(int index, double value) { - NanotraceHR::Tracer tracer{"bind double"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"bind double"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("index", index), + keyValue("value", value)}; int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value); if (resultCode != SQLITE_OK) @@ -182,7 +206,11 @@ void BaseStatement::bind(int index, double value) void BaseStatement::bind(int index, void *pointer) { - NanotraceHR::Tracer tracer{"bind pointer"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"bind pointer"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("index", index), + keyValue("pointer", reinterpret_cast<std::uintptr_t>(pointer))}; int resultCode = sqlite3_bind_pointer(m_compiledStatement.get(), index, pointer, "carray", nullptr); if (resultCode != SQLITE_OK) @@ -191,7 +219,12 @@ void BaseStatement::bind(int index, void *pointer) void BaseStatement::bind(int index, Utils::span<const int> values) { - NanotraceHR::Tracer tracer{"bind int span"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"bind int span"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("index", index), + keyValue("pointer", reinterpret_cast<std::uintptr_t>(values.data())), + keyValue("size", values.size())}; int resultCode = sqlite3_carray_bind(m_compiledStatement.get(), index, @@ -205,7 +238,12 @@ void BaseStatement::bind(int index, Utils::span<const int> values) void BaseStatement::bind(int index, Utils::span<const long long> values) { - NanotraceHR::Tracer tracer{"bind long long span"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"bind long long span"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("index", index), + keyValue("pointer", reinterpret_cast<std::uintptr_t>(values.data())), + keyValue("size", values.size())}; int resultCode = sqlite3_carray_bind(m_compiledStatement.get(), index, @@ -219,7 +257,12 @@ void BaseStatement::bind(int index, Utils::span<const long long> values) void BaseStatement::bind(int index, Utils::span<const double> values) { - NanotraceHR::Tracer tracer{"bind double span"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"bind double span"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("index", index), + keyValue("pointer", reinterpret_cast<std::uintptr_t>(values.data())), + keyValue("size", values.size())}; int resultCode = sqlite3_carray_bind(m_compiledStatement.get(), index, @@ -233,7 +276,12 @@ void BaseStatement::bind(int index, Utils::span<const double> values) void BaseStatement::bind(int index, Utils::span<const char *> values) { - NanotraceHR::Tracer tracer{"bind const char* span"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"bind const char* span"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("index", index), + keyValue("pointer", reinterpret_cast<std::uintptr_t>(values.data())), + keyValue("size", values.size())}; int resultCode = sqlite3_carray_bind(m_compiledStatement.get(), index, @@ -247,7 +295,11 @@ void BaseStatement::bind(int index, Utils::span<const char *> values) void BaseStatement::bind(int index, Utils::SmallStringView text) { - NanotraceHR::Tracer tracer{"bind string"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"bind string"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("index", index), + keyValue("text", text)}; int resultCode = sqlite3_bind_text(m_compiledStatement.get(), index, @@ -260,7 +312,12 @@ void BaseStatement::bind(int index, Utils::SmallStringView text) void BaseStatement::bind(int index, BlobView blobView) { - NanotraceHR::Tracer tracer{"bind blob"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"bind blob"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("index", index), + keyValue("pointer", reinterpret_cast<std::uintptr_t>(blobView.data())), + keyValue("size", blobView.size())}; int resultCode = SQLITE_OK; @@ -280,7 +337,11 @@ void BaseStatement::bind(int index, BlobView blobView) void BaseStatement::bind(int index, const Value &value) { - NanotraceHR::Tracer tracer{"bind value"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{ + "bind value"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + }; switch (value.type()) { case ValueType::Integer: @@ -303,7 +364,11 @@ void BaseStatement::bind(int index, const Value &value) void BaseStatement::bind(int index, ValueView value) { - NanotraceHR::Tracer tracer{"bind value"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{ + "bind value"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + }; switch (value.type()) { case ValueType::Integer: @@ -326,7 +391,9 @@ void BaseStatement::bind(int index, ValueView value) void BaseStatement::prepare(Utils::SmallStringView sqlStatement) { - NanotraceHR::Tracer tracer{"prepare"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"prepare"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle())}; if (!m_database.isLocked()) throw DatabaseIsNotLocked{}; @@ -342,14 +409,18 @@ void BaseStatement::prepare(Utils::SmallStringView sqlStatement) nullptr); m_compiledStatement.reset(sqliteStatement); - if (resultCode == SQLITE_LOCKED) + if (resultCode == SQLITE_LOCKED) { + tracer.tick("wait for unlock"_t); waitForUnlockNotify(); + } } while (resultCode == SQLITE_LOCKED); if (resultCode != SQLITE_OK) Sqlite::throwError(resultCode, sqliteDatabaseHandle()); + + tracer.end(keyValue("sql statement", handle())); } sqlite3 *BaseStatement::sqliteDatabaseHandle() const @@ -427,7 +498,10 @@ StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column) Type BaseStatement::fetchType(int column) const { - NanotraceHR::Tracer tracer{"fetch type"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"fetch type"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("column", column)}; auto dataType = sqlite3_column_type(m_compiledStatement.get(), column); @@ -449,9 +523,16 @@ Type BaseStatement::fetchType(int column) const int BaseStatement::fetchIntValue(int column) const { - NanotraceHR::Tracer tracer{"fetch int"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"fetch int"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("column", column)}; + + auto value = sqlite3_column_int(m_compiledStatement.get(), column); + + tracer.end(keyValue("value", value)); - return sqlite3_column_int(m_compiledStatement.get(), column); + return value; } template<> @@ -473,9 +554,16 @@ long BaseStatement::fetchValue<long>(int column) const long long BaseStatement::fetchLongLongValue(int column) const { - NanotraceHR::Tracer tracer{"fetch long long"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"fetch long long"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("column", column)}; - return sqlite3_column_int64(m_compiledStatement.get(), column); + auto value = sqlite3_column_int64(m_compiledStatement.get(), column); + + tracer.end(keyValue("value", value)); + + return value; } template<> @@ -486,14 +574,24 @@ long long BaseStatement::fetchValue<long long>(int column) const double BaseStatement::fetchDoubleValue(int column) const { - NanotraceHR::Tracer tracer{"fetch double"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"fetch double"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("column", column)}; + + auto value = sqlite3_column_double(m_compiledStatement.get(), column); - return sqlite3_column_double(m_compiledStatement.get(), column); + tracer.end(keyValue("value", value)); + + return value; } BlobView BaseStatement::fetchBlobValue(int column) const { - NanotraceHR::Tracer tracer{"fetch blob"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{"fetch blob"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("column", column)}; return convertToBlobForColumn(m_compiledStatement.get(), column); } @@ -507,7 +605,16 @@ double BaseStatement::fetchValue<double>(int column) const template<typename StringType> StringType BaseStatement::fetchValue(int column) const { - return convertToTextForColumn<StringType>(m_compiledStatement.get(), column); + NanotraceHR::Tracer tracer{"fetch string value"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("column", column)}; + + auto text = convertToTextForColumn<StringType>(m_compiledStatement.get(), column); + + tracer.end(keyValue("text", text)); + + return text; } template SQLITE_EXPORT Utils::SmallStringView BaseStatement::fetchValue<Utils::SmallStringView>( @@ -519,11 +626,25 @@ template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue<Utils::PathSt Utils::SmallStringView BaseStatement::fetchSmallStringViewValue(int column) const { - return fetchValue<Utils::SmallStringView>(column); + NanotraceHR::Tracer tracer{"fetch string view"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("column", column)}; + + auto text = fetchValue<Utils::SmallStringView>(column); + + tracer.end(keyValue("text", text)); + + return text; } ValueView BaseStatement::fetchValueView(int column) const { + NanotraceHR::Tracer tracer{"fetch value view"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", handle()), + keyValue("column", column)}; + int dataType = sqlite3_column_type(m_compiledStatement.get(), column); switch (dataType) { case SQLITE_NULL: @@ -543,7 +664,11 @@ ValueView BaseStatement::fetchValueView(int column) const void BaseStatement::Deleter::operator()(sqlite3_stmt *statement) { - NanotraceHR::Tracer tracer{"finalize"_t, sqliteLowLevelCategory()}; + NanotraceHR::Tracer tracer{ + "finalize"_t, + sqliteLowLevelCategory(), + keyValue("sqlite statement", reinterpret_cast<std::uintptr_t>(statement)), + }; sqlite3_finalize(statement); } diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h index d2306c67a5..9f81bfb9e2 100644 --- a/src/libs/sqlite/sqlitebasestatement.h +++ b/src/libs/sqlite/sqlitebasestatement.h @@ -47,13 +47,18 @@ constexpr static std::underlying_type_t<Enumeration> to_underlying(Enumeration e constexpr NanotraceHR::Tracing sqliteTracingStatus() { #ifdef ENABLE_SQLITE_TRACING - return NanotraceHR::tracingStatus(); + return NanotraceHR::Tracing::IsEnabled; #else return NanotraceHR::Tracing::IsDisabled; #endif } -SQLITE_EXPORT NanotraceHR::StringViewCategory<sqliteTracingStatus()> &sqliteHighLevelCategory(); +using TraceFile = NanotraceHR::TraceFile<sqliteTracingStatus()>; + +SQLITE_EXPORT TraceFile &traceFile(); + +SQLITE_EXPORT NanotraceHR::StringViewWithStringArgumentsCategory<sqliteTracingStatus()> & +sqliteHighLevelCategory(); class SQLITE_EXPORT BaseStatement { @@ -136,6 +141,11 @@ public: protected: ~BaseStatement() = default; + std::uintptr_t handle() const + { + return reinterpret_cast<std::uintptr_t>(m_compiledStatement.get()); + } + private: struct Deleter { @@ -166,7 +176,12 @@ public: void execute() { - NanotraceHR::Tracer tracer{"execute"_t, sqliteHighLevelCategory()}; + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{ + "execute"_t, + sqliteHighLevelCategory(), + keyValue("sqlite statement", BaseStatement::handle()), + }; Resetter resetter{this}; BaseStatement::next(); @@ -175,7 +190,10 @@ public: template<typename... ValueType> void bindValues(const ValueType &...values) { - NanotraceHR::Tracer tracer{"bind"_t, sqliteHighLevelCategory()}; + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"bind"_t, + sqliteHighLevelCategory(), + keyValue("sqlite statement", BaseStatement::handle())}; static_assert(BindParameterCount == sizeof...(values), "Wrong binding parameter count!"); @@ -186,7 +204,10 @@ public: template<typename... ValueType> void write(const ValueType&... values) { - NanotraceHR::Tracer tracer{"write"_t, sqliteHighLevelCategory()}; + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"write"_t, + sqliteHighLevelCategory(), + keyValue("sqlite statement", BaseStatement::handle())}; Resetter resetter{this}; bindValues(values...); @@ -212,7 +233,10 @@ public: typename... QueryTypes> auto values(const QueryTypes &...queryValues) { - NanotraceHR::Tracer tracer{"values"_t, sqliteHighLevelCategory()}; + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"values"_t, + sqliteHighLevelCategory(), + keyValue("sqlite statement", BaseStatement::handle())}; Resetter resetter{this}; Container resultValues; @@ -241,7 +265,10 @@ public: template<typename ResultType, typename... QueryTypes> auto value(const QueryTypes &...queryValues) { - NanotraceHR::Tracer tracer{"value"_t, sqliteHighLevelCategory()}; + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"value"_t, + sqliteHighLevelCategory(), + keyValue("sqlite statement", BaseStatement::handle())}; Resetter resetter{this}; ResultType resultValue{}; @@ -257,7 +284,10 @@ public: template<typename ResultType, typename... QueryTypes> auto optionalValue(const QueryTypes &...queryValues) { - NanotraceHR::Tracer tracer{"optionalValue"_t, sqliteHighLevelCategory()}; + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"optionalValue"_t, + sqliteHighLevelCategory(), + keyValue("sqlite statement", BaseStatement::handle())}; Resetter resetter{this}; std::optional<ResultType> resultValue; @@ -273,6 +303,7 @@ public: template<typename Type> static auto toValue(Utils::SmallStringView sqlStatement, Database &database) { + using NanotraceHR::keyValue; NanotraceHR::Tracer tracer{"toValue"_t, sqliteHighLevelCategory()}; StatementImplementation statement(sqlStatement, database); @@ -287,7 +318,10 @@ public: template<typename Callable, typename... QueryTypes> void readCallback(Callable &&callable, const QueryTypes &...queryValues) { - NanotraceHR::Tracer tracer{"readCallback"_t, sqliteHighLevelCategory()}; + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"readCallback"_t, + sqliteHighLevelCategory(), + keyValue("sqlite statement", BaseStatement::handle())}; Resetter resetter{this}; @@ -304,7 +338,10 @@ public: template<typename Container, typename... QueryTypes> void readTo(Container &container, const QueryTypes &...queryValues) { - NanotraceHR::Tracer tracer{"readTo"_t, sqliteHighLevelCategory()}; + using NanotraceHR::keyValue; + NanotraceHR::Tracer tracer{"readTo"_t, + sqliteHighLevelCategory(), + keyValue("sqlite statement", BaseStatement::handle())}; Resetter resetter{this}; @@ -402,9 +439,11 @@ public: private: using TracerCategory = std::decay_t<decltype(sqliteHighLevelCategory())>; - NanotraceHR::Tracer<TracerCategory, typename TracerCategory::IsActive> tracer{ - "range"_t, sqliteHighLevelCategory()}; StatementImplementation &m_statement; + NanotraceHR::Tracer<TracerCategory, typename TracerCategory::IsActive> tracer{ + "range"_t, + sqliteHighLevelCategory(), + NanotraceHR::keyValue("sqlite statement", m_statement.handle())}; }; template<typename ResultType> diff --git a/src/libs/utils/smallstring.h b/src/libs/utils/smallstring.h index a32b09986c..1d5eeb2438 100644 --- a/src/libs/utils/smallstring.h +++ b/src/libs/utils/smallstring.h @@ -582,20 +582,11 @@ public: return joinedString; } - static - BasicSmallString number(int number) + template<typename Integer, typename = std::enable_if_t<std::is_integral_v<Integer>>> + static BasicSmallString number(Integer number) { // 2 bytes for the sign and because digits10 returns the floor - char buffer[std::numeric_limits<int>::digits10 + 2]; - auto result = std::to_chars(buffer, buffer + sizeof(buffer), number); - auto endOfConversionString = result.ptr; - return BasicSmallString(buffer, endOfConversionString); - } - - static BasicSmallString number(long long int number) noexcept - { - // 2 bytes for the sign and because digits10 returns the floor - char buffer[std::numeric_limits<long long int>::digits10 + 2]; + char buffer[std::numeric_limits<Integer>::digits10 + 2]; auto result = std::to_chars(buffer, buffer + sizeof(buffer), number); auto endOfConversionString = result.ptr; return BasicSmallString(buffer, endOfConversionString); |