From 5b95a68ffef94e867f061ad01ecbf96010dd19d7 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 4 Sep 2018 05:18:59 +0700 Subject: [PATCH] strings::format string view support --- headers/enduro2d/base/_all.hpp | 1 + headers/enduro2d/base/stdex.hpp | 4 +++ headers/enduro2d/utils/_all.hpp | 1 + headers/enduro2d/utils/strfmts.hpp | 28 +++++++++++++++ headers/enduro2d/utils/strings.hpp | 4 +-- headers/enduro2d/utils/strings.inl | 25 +++++++------- .../utils/image_impl/image_reader_stb.cpp | 2 +- untests/sources/untests_utils/strings.cpp | 34 +++++++++++++------ 8 files changed, 74 insertions(+), 25 deletions(-) diff --git a/headers/enduro2d/base/_all.hpp b/headers/enduro2d/base/_all.hpp index d0a9c1cd..e079b43e 100644 --- a/headers/enduro2d/base/_all.hpp +++ b/headers/enduro2d/base/_all.hpp @@ -7,6 +7,7 @@ #pragma once #include "_base.hpp" + #include "configs.hpp" #include "macros.hpp" #include "stdex.hpp" diff --git a/headers/enduro2d/base/stdex.hpp b/headers/enduro2d/base/stdex.hpp index dc3a4a01..a984f712 100644 --- a/headers/enduro2d/base/stdex.hpp +++ b/headers/enduro2d/base/stdex.hpp @@ -398,6 +398,10 @@ namespace e2d { namespace stdex size_type size_ = 0; }; + template < typename Char, typename Traits > + const typename basic_string_view::size_type + basic_string_view::npos; + template < typename Char, typename Traits > bool operator<( basic_string_view l, diff --git a/headers/enduro2d/utils/_all.hpp b/headers/enduro2d/utils/_all.hpp index f4b65d53..7d92d665 100644 --- a/headers/enduro2d/utils/_all.hpp +++ b/headers/enduro2d/utils/_all.hpp @@ -17,4 +17,5 @@ #include "streams.hpp" #include "strfmts.hpp" #include "strings.hpp" +#include "strings.inl" #include "time.hpp" diff --git a/headers/enduro2d/utils/strfmts.hpp b/headers/enduro2d/utils/strfmts.hpp index 371390b7..bad15136 100644 --- a/headers/enduro2d/utils/strfmts.hpp +++ b/headers/enduro2d/utils/strfmts.hpp @@ -353,6 +353,13 @@ namespace e2d { namespace strings } }; + template <> + class format_arg : public format_arg { + public: + explicit format_arg(str_view sv) + : format_arg(sv) {} + }; + // // wstr // @@ -372,6 +379,13 @@ namespace e2d { namespace strings } }; + template <> + class format_arg : public format_arg { + public: + explicit format_arg(wstr_view sv) + : format_arg(sv) {} + }; + // // str16 // @@ -391,6 +405,13 @@ namespace e2d { namespace strings } }; + template <> + class format_arg : public format_arg { + public: + explicit format_arg(str16_view sv) + : format_arg(sv) {} + }; + // // str32 // @@ -410,6 +431,13 @@ namespace e2d { namespace strings } }; + template <> + class format_arg : public format_arg { + public: + explicit format_arg(str32_view sv) + : format_arg(sv) {} + }; + // // color // diff --git a/headers/enduro2d/utils/strings.hpp b/headers/enduro2d/utils/strings.hpp index f94fa31d..6949f913 100644 --- a/headers/enduro2d/utils/strings.hpp +++ b/headers/enduro2d/utils/strings.hpp @@ -46,10 +46,10 @@ namespace e2d template < typename... Args > std::size_t format( char* dst, std::size_t size, - const char* fmt, Args&&... args); + str_view fmt, Args&&... args); template < typename... Args > - str rformat(const char* fmt, Args&&... args); + str rformat(str_view fmt, Args&&... args); bool wildcard_match(str_view string, str_view pattern); } diff --git a/headers/enduro2d/utils/strings.inl b/headers/enduro2d/utils/strings.inl index 35715f65..35880f13 100644 --- a/headers/enduro2d/utils/strings.inl +++ b/headers/enduro2d/utils/strings.inl @@ -238,8 +238,10 @@ namespace e2d { namespace strings template < typename Tuple > std::enable_if_t::value <= 10, std::size_t> - format_impl(char* dst, std::size_t size, const char* format, const Tuple& targs) { - if ( !format ) { + format_impl(char* dst, std::size_t size, str_view fmt, const Tuple& targs) { + const char* format_i = fmt.cbegin(); + const char* const format_e = fmt.cend(); + if ( !format_i ) { throw bad_format(); } if ( !dst != !size ) { @@ -248,20 +250,19 @@ namespace e2d { namespace strings std::size_t result = 0; const char* const b_dst = dst; const char* const e_dst = b_dst ? b_dst + size : nullptr; - while ( *format ) { + while ( format_i != format_e ) { if ( dst && dst == e_dst - 1 ) { *dst = '\0'; throw bad_format_buffer(); } - if ( *format != '%' ) { + if ( *format_i != '%' ) { if ( dst ) { - *dst++ = *format; + *dst++ = *format_i; } ++result; - ++format; + ++format_i; } else { - const char n_param = *(++format); - if ( !n_param ) { + if ( ++format_i == format_e ) { // "hello%" if ( dst ) { *dst = '\0'; @@ -273,7 +274,7 @@ namespace e2d { namespace strings ? math::numeric_cast(e_dst - dst) : 0; E2D_ASSERT(!dst || dst_tail_size); - switch ( n_param ) { + switch ( *format_i ) { case '0' : write_arg_r = write_arg_n<0>(dst, dst_tail_size, targs); break; @@ -337,7 +338,7 @@ namespace e2d { namespace strings dst += write_bytes; } result += write_bytes; - ++format; + ++format_i; } } if ( dst ) { @@ -353,7 +354,7 @@ namespace e2d { namespace strings template < typename... Args > std::size_t format( char* dst, std::size_t size, - const char* fmt, Args&&... args) + str_view fmt, Args&&... args) { return impl::format_impl( dst, size, fmt, @@ -361,7 +362,7 @@ namespace e2d { namespace strings } template < typename... Args > - str rformat(const char* fmt, Args&&... args) { + str rformat(str_view fmt, Args&&... args) { auto targs = std::make_tuple( impl::wrap_arg(std::forward(args))...); const std::size_t expected_format_size = impl::format_impl( diff --git a/sources/enduro2d/utils/image_impl/image_reader_stb.cpp b/sources/enduro2d/utils/image_impl/image_reader_stb.cpp index da973a0d..94447fdf 100644 --- a/sources/enduro2d/utils/image_impl/image_reader_stb.cpp +++ b/sources/enduro2d/utils/image_impl/image_reader_stb.cpp @@ -68,7 +68,7 @@ namespace dst.assign(img_size, img_format, std::move(img_buffer)); return true; } - } catch (std::exception&) { + } catch (...) { // nothing } return false; diff --git a/untests/sources/untests_utils/strings.cpp b/untests/sources/untests_utils/strings.cpp index 9177cfc8..3c9d0872 100644 --- a/untests/sources/untests_utils/strings.cpp +++ b/untests/sources/untests_utils/strings.cpp @@ -7,6 +7,16 @@ #include "_utils.hpp" using namespace e2d; +namespace +{ + const char* null_utf8 = nullptr; + const wchar_t* null_wide = nullptr; + const char16_t* null_utf16 = nullptr; + const char32_t* null_utf32 = nullptr; + + str_view null_view = {null_utf8, 0}; +} + TEST_CASE("strings") { { REQUIRE(make_utf8("hello") == "hello"); @@ -30,11 +40,6 @@ TEST_CASE("strings") { REQUIRE(make_utf32(U"hello") == U"hello"); } { - const char* null_utf8 = nullptr; - const wchar_t* null_wide = nullptr; - const char16_t* null_utf16 = nullptr; - const char32_t* null_utf32 = nullptr; - REQUIRE(make_utf8(str_view(null_utf8, 0)) == make_utf8(u"")); REQUIRE(make_utf8(wstr_view(null_wide, 0)) == make_utf8(L"")); REQUIRE(make_utf8(str16_view(null_utf16, 0)) == make_utf8(u"")); @@ -95,8 +100,6 @@ TEST_CASE("strings") { REQUIRE(wildcard_match("", "*") == true); REQUIRE(wildcard_match("", "?") == false); - const char* null_utf8 = nullptr; - str_view null_view = {null_utf8, 0}; REQUIRE(wildcard_match(null_view, null_view) == true); REQUIRE(wildcard_match("a", null_view) == false); REQUIRE(wildcard_match(null_view, "*") == true); @@ -214,7 +217,6 @@ TEST_CASE("strings") { } { char buf[6]; - REQUIRE_THROWS_AS(strings::format(buf, sizeof(buf), nullptr), strings::bad_format); REQUIRE_THROWS_AS(strings::format(buf, 0, "hello"), strings::bad_format_buffer); REQUIRE_THROWS_AS(strings::format(nullptr, sizeof(buf), "hello"), strings::bad_format_buffer); REQUIRE_THROWS_AS(strings::format(buf, sizeof(buf), "helloE"), strings::bad_format_buffer); @@ -235,8 +237,6 @@ TEST_CASE("strings") { REQUIRE_THROWS_AS(strings::format(buf, sizeof(buf), "%z%hell"), strings::bad_format); } { - REQUIRE_THROWS_AS(strings::rformat(nullptr), strings::bad_format); - REQUIRE_THROWS_AS(strings::rformat("%"), strings::bad_format); REQUIRE_THROWS_AS(strings::rformat("%hell"), strings::bad_format); REQUIRE_THROWS_AS(strings::rformat("he%ll"), strings::bad_format); @@ -250,6 +250,20 @@ TEST_CASE("strings") { REQUIRE_THROWS_AS(strings::rformat("hell%y%"), strings::bad_format); REQUIRE_THROWS_AS(strings::rformat("%z%hell"), strings::bad_format); } + { + REQUIRE(strings::rformat(str_view("%0"), 42) == "42"); + REQUIRE(strings::rformat(str_view("%0%1",2), 42) == "42"); + + auto s1 = make_utf8("hello"); + auto s2 = make_wide("hello"); + auto s3 = make_utf16("hello"); + auto s4 = make_utf32("hello"); + + REQUIRE(strings::rformat(str_view("%0"), str_view(s1)) == "hello"); + REQUIRE(strings::rformat(str_view("%0"), wstr_view(s2)) == "hello"); + REQUIRE(strings::rformat(str_view("%0"), str16_view(s3)) == "hello"); + REQUIRE(strings::rformat(str_view("%0"), str32_view(s4)) == "hello"); + } { char buf[1];