mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-16 22:16:53 +07:00
strings::format string view support
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "_base.hpp"
|
#include "_base.hpp"
|
||||||
|
|
||||||
#include "configs.hpp"
|
#include "configs.hpp"
|
||||||
#include "macros.hpp"
|
#include "macros.hpp"
|
||||||
#include "stdex.hpp"
|
#include "stdex.hpp"
|
||||||
|
|||||||
@@ -398,6 +398,10 @@ namespace e2d { namespace stdex
|
|||||||
size_type size_ = 0;
|
size_type size_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template < typename Char, typename Traits >
|
||||||
|
const typename basic_string_view<Char, Traits>::size_type
|
||||||
|
basic_string_view<Char, Traits>::npos;
|
||||||
|
|
||||||
template < typename Char, typename Traits >
|
template < typename Char, typename Traits >
|
||||||
bool operator<(
|
bool operator<(
|
||||||
basic_string_view<Char, Traits> l,
|
basic_string_view<Char, Traits> l,
|
||||||
|
|||||||
@@ -17,4 +17,5 @@
|
|||||||
#include "streams.hpp"
|
#include "streams.hpp"
|
||||||
#include "strfmts.hpp"
|
#include "strfmts.hpp"
|
||||||
#include "strings.hpp"
|
#include "strings.hpp"
|
||||||
|
#include "strings.inl"
|
||||||
#include "time.hpp"
|
#include "time.hpp"
|
||||||
|
|||||||
@@ -353,6 +353,13 @@ namespace e2d { namespace strings
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class format_arg<str_view> : public format_arg<str> {
|
||||||
|
public:
|
||||||
|
explicit format_arg(str_view sv)
|
||||||
|
: format_arg<str>(sv) {}
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// wstr
|
// wstr
|
||||||
//
|
//
|
||||||
@@ -372,6 +379,13 @@ namespace e2d { namespace strings
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class format_arg<wstr_view> : public format_arg<wstr> {
|
||||||
|
public:
|
||||||
|
explicit format_arg(wstr_view sv)
|
||||||
|
: format_arg<wstr>(sv) {}
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// str16
|
// str16
|
||||||
//
|
//
|
||||||
@@ -391,6 +405,13 @@ namespace e2d { namespace strings
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class format_arg<str16_view> : public format_arg<str16> {
|
||||||
|
public:
|
||||||
|
explicit format_arg(str16_view sv)
|
||||||
|
: format_arg<str16>(sv) {}
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// str32
|
// str32
|
||||||
//
|
//
|
||||||
@@ -410,6 +431,13 @@ namespace e2d { namespace strings
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class format_arg<str32_view> : public format_arg<str32> {
|
||||||
|
public:
|
||||||
|
explicit format_arg(str32_view sv)
|
||||||
|
: format_arg<str32>(sv) {}
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// color
|
// color
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ namespace e2d
|
|||||||
template < typename... Args >
|
template < typename... Args >
|
||||||
std::size_t format(
|
std::size_t format(
|
||||||
char* dst, std::size_t size,
|
char* dst, std::size_t size,
|
||||||
const char* fmt, Args&&... args);
|
str_view fmt, Args&&... args);
|
||||||
|
|
||||||
template < typename... 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);
|
bool wildcard_match(str_view string, str_view pattern);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,8 +238,10 @@ namespace e2d { namespace strings
|
|||||||
|
|
||||||
template < typename Tuple >
|
template < typename Tuple >
|
||||||
std::enable_if_t<std::tuple_size<Tuple>::value <= 10, std::size_t>
|
std::enable_if_t<std::tuple_size<Tuple>::value <= 10, std::size_t>
|
||||||
format_impl(char* dst, std::size_t size, const char* format, const Tuple& targs) {
|
format_impl(char* dst, std::size_t size, str_view fmt, const Tuple& targs) {
|
||||||
if ( !format ) {
|
const char* format_i = fmt.cbegin();
|
||||||
|
const char* const format_e = fmt.cend();
|
||||||
|
if ( !format_i ) {
|
||||||
throw bad_format();
|
throw bad_format();
|
||||||
}
|
}
|
||||||
if ( !dst != !size ) {
|
if ( !dst != !size ) {
|
||||||
@@ -248,20 +250,19 @@ namespace e2d { namespace strings
|
|||||||
std::size_t result = 0;
|
std::size_t result = 0;
|
||||||
const char* const b_dst = dst;
|
const char* const b_dst = dst;
|
||||||
const char* const e_dst = b_dst ? b_dst + size : nullptr;
|
const char* const e_dst = b_dst ? b_dst + size : nullptr;
|
||||||
while ( *format ) {
|
while ( format_i != format_e ) {
|
||||||
if ( dst && dst == e_dst - 1 ) {
|
if ( dst && dst == e_dst - 1 ) {
|
||||||
*dst = '\0';
|
*dst = '\0';
|
||||||
throw bad_format_buffer();
|
throw bad_format_buffer();
|
||||||
}
|
}
|
||||||
if ( *format != '%' ) {
|
if ( *format_i != '%' ) {
|
||||||
if ( dst ) {
|
if ( dst ) {
|
||||||
*dst++ = *format;
|
*dst++ = *format_i;
|
||||||
}
|
}
|
||||||
++result;
|
++result;
|
||||||
++format;
|
++format_i;
|
||||||
} else {
|
} else {
|
||||||
const char n_param = *(++format);
|
if ( ++format_i == format_e ) {
|
||||||
if ( !n_param ) {
|
|
||||||
// "hello%"
|
// "hello%"
|
||||||
if ( dst ) {
|
if ( dst ) {
|
||||||
*dst = '\0';
|
*dst = '\0';
|
||||||
@@ -273,7 +274,7 @@ namespace e2d { namespace strings
|
|||||||
? math::numeric_cast<std::size_t>(e_dst - dst)
|
? math::numeric_cast<std::size_t>(e_dst - dst)
|
||||||
: 0;
|
: 0;
|
||||||
E2D_ASSERT(!dst || dst_tail_size);
|
E2D_ASSERT(!dst || dst_tail_size);
|
||||||
switch ( n_param ) {
|
switch ( *format_i ) {
|
||||||
case '0' :
|
case '0' :
|
||||||
write_arg_r = write_arg_n<0>(dst, dst_tail_size, targs);
|
write_arg_r = write_arg_n<0>(dst, dst_tail_size, targs);
|
||||||
break;
|
break;
|
||||||
@@ -337,7 +338,7 @@ namespace e2d { namespace strings
|
|||||||
dst += write_bytes;
|
dst += write_bytes;
|
||||||
}
|
}
|
||||||
result += write_bytes;
|
result += write_bytes;
|
||||||
++format;
|
++format_i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( dst ) {
|
if ( dst ) {
|
||||||
@@ -353,7 +354,7 @@ namespace e2d { namespace strings
|
|||||||
template < typename... Args >
|
template < typename... Args >
|
||||||
std::size_t format(
|
std::size_t format(
|
||||||
char* dst, std::size_t size,
|
char* dst, std::size_t size,
|
||||||
const char* fmt, Args&&... args)
|
str_view fmt, Args&&... args)
|
||||||
{
|
{
|
||||||
return impl::format_impl(
|
return impl::format_impl(
|
||||||
dst, size, fmt,
|
dst, size, fmt,
|
||||||
@@ -361,7 +362,7 @@ namespace e2d { namespace strings
|
|||||||
}
|
}
|
||||||
|
|
||||||
template < typename... Args >
|
template < typename... Args >
|
||||||
str rformat(const char* fmt, Args&&... args) {
|
str rformat(str_view fmt, Args&&... args) {
|
||||||
auto targs = std::make_tuple(
|
auto targs = std::make_tuple(
|
||||||
impl::wrap_arg(std::forward<Args>(args))...);
|
impl::wrap_arg(std::forward<Args>(args))...);
|
||||||
const std::size_t expected_format_size = impl::format_impl(
|
const std::size_t expected_format_size = impl::format_impl(
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ namespace
|
|||||||
dst.assign(img_size, img_format, std::move(img_buffer));
|
dst.assign(img_size, img_format, std::move(img_buffer));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (std::exception&) {
|
} catch (...) {
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -7,6 +7,16 @@
|
|||||||
#include "_utils.hpp"
|
#include "_utils.hpp"
|
||||||
using namespace e2d;
|
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") {
|
TEST_CASE("strings") {
|
||||||
{
|
{
|
||||||
REQUIRE(make_utf8("hello") == "hello");
|
REQUIRE(make_utf8("hello") == "hello");
|
||||||
@@ -30,11 +40,6 @@ TEST_CASE("strings") {
|
|||||||
REQUIRE(make_utf32(U"hello") == U"hello");
|
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(str_view(null_utf8, 0)) == make_utf8(u""));
|
||||||
REQUIRE(make_utf8(wstr_view(null_wide, 0)) == make_utf8(L""));
|
REQUIRE(make_utf8(wstr_view(null_wide, 0)) == make_utf8(L""));
|
||||||
REQUIRE(make_utf8(str16_view(null_utf16, 0)) == make_utf8(u""));
|
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("", "*") == true);
|
||||||
REQUIRE(wildcard_match("", "?") == false);
|
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(null_view, null_view) == true);
|
||||||
REQUIRE(wildcard_match("a", null_view) == false);
|
REQUIRE(wildcard_match("a", null_view) == false);
|
||||||
REQUIRE(wildcard_match(null_view, "*") == true);
|
REQUIRE(wildcard_match(null_view, "*") == true);
|
||||||
@@ -214,7 +217,6 @@ TEST_CASE("strings") {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
char buf[6];
|
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(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(nullptr, sizeof(buf), "hello"), strings::bad_format_buffer);
|
||||||
REQUIRE_THROWS_AS(strings::format(buf, sizeof(buf), "helloE"), 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::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("%"), strings::bad_format);
|
||||||
REQUIRE_THROWS_AS(strings::rformat("%hell"), strings::bad_format);
|
REQUIRE_THROWS_AS(strings::rformat("%hell"), strings::bad_format);
|
||||||
REQUIRE_THROWS_AS(strings::rformat("he%ll"), 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("hell%y%"), strings::bad_format);
|
||||||
REQUIRE_THROWS_AS(strings::rformat("%z%hell"), 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];
|
char buf[1];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user