From 197cdd809226c02e074bb53d4e0c2db33dcfa3db Mon Sep 17 00:00:00 2001 From: "Alan M. Carroll" Date: Tue, 18 Dec 2018 14:36:22 -0600 Subject: [PATCH] BWF: Fix handling of null char * - avoid string_view constructor. --- include/tscore/BufferWriter.h | 27 ++++++++++++++++--- .../unit_tests/test_BufferWriterFormat.cc | 8 ++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/include/tscore/BufferWriter.h b/include/tscore/BufferWriter.h index 052a4de29cf..6da3e12c21b 100644 --- a/include/tscore/BufferWriter.h +++ b/include/tscore/BufferWriter.h @@ -704,12 +704,26 @@ BufferWriter::printv(BWFormat const &fmt, std::tuple const &args) return *this; } +// Must be first so that other inline formatters can use it. +BufferWriter &bwformat(BufferWriter &w, BWFSpec const &spec, std::string_view sv); + // Pointers that are not specialized. inline BufferWriter & bwformat(BufferWriter &w, BWFSpec const &spec, const void *ptr) { BWFSpec ptr_spec{spec}; ptr_spec._radix_lead_p = true; + + if (ptr == nullptr) { + if (spec._type == 's' || spec._type == 'S') { + ptr_spec._type = BWFSpec::DEFAULT_TYPE; + ptr_spec._ext = ""_sv; // clear any extension. + return bwformat(w, spec, spec._type == 's' ? "null"_sv : "NULL"_sv); + } else if (spec._type == BWFSpec::DEFAULT_TYPE) { + return w; // print nothing if there is no format character override. + } + } + if (ptr_spec._type == BWFSpec::DEFAULT_TYPE || ptr_spec._type == 'p') { ptr_spec._type = 'x'; // if default or 'p;, switch to lower hex. } else if (ptr_spec._type == 'P') { @@ -723,7 +737,12 @@ BufferWriter &bwformat(BufferWriter &w, BWFSpec const &spec, MemSpan const &span // -- Common formatters -- -BufferWriter &bwformat(BufferWriter &w, BWFSpec const &spec, std::string_view sv); +// Capture this explicitly so it doesn't go to any other pointer type. +inline BufferWriter & +bwformat(BufferWriter &w, BWFSpec const &spec, std::nullptr_t) +{ + return bwformat(w, spec, static_cast(nullptr)); +} template BufferWriter & @@ -735,10 +754,12 @@ bwformat(BufferWriter &w, BWFSpec const &spec, const char (&a)[N]) inline BufferWriter & bwformat(BufferWriter &w, BWFSpec const &spec, const char *v) { - if (spec._type == 'x' || spec._type == 'X') { + if (spec._type == 'x' || spec._type == 'X' || spec._type == 'p') { bwformat(w, spec, static_cast(v)); - } else { + } else if (v != nullptr) { bwformat(w, spec, std::string_view(v)); + } else { + bwformat(w, spec, nullptr); } return w; } diff --git a/src/tscore/unit_tests/test_BufferWriterFormat.cc b/src/tscore/unit_tests/test_BufferWriterFormat.cc index e8dee671a08..1e3a70b8cca 100644 --- a/src/tscore/unit_tests/test_BufferWriterFormat.cc +++ b/src/tscore/unit_tests/test_BufferWriterFormat.cc @@ -306,6 +306,14 @@ TEST_CASE("bwstring", "[bwprint][bwstring]") ts::bwprint(out, fmt, std::string_view(), "Leif", "confused"); REQUIRE(out == "Did you know? Leif is confused"); } + + char const *null_string{nullptr}; + ts::bwprint(s, "Null {0:x}.{0}", null_string); + REQUIRE(s == "Null 0x0."); + ts::bwprint(s, "Null {0:X}.{0}", nullptr); + REQUIRE(s == "Null 0X0."); + ts::bwprint(s, "Null {0:p}.{0:P}.{0:s}.{0:S}", null_string); + REQUIRE(s == "Null 0x0.0X0.null.NULL"); } TEST_CASE("BWFormat integral", "[bwprint][bwformat]")