IceShard 1
A personal game engine project, with development focused on 2D/2.5D games.
Loading...
Searching...
No Matches
i18n_reference.hxx
Go to the documentation of this file.
1#pragma once
2#include <ice/i18n_detail.hxx>
3
4namespace ice
5{
6
7 // a.b.c/error.message lang=ja-JP|Fallback Message
9 {
10 public:
11 constexpr I18NReference() noexcept = default;
12 constexpr I18NReference(ice::String fallback) noexcept;
13 constexpr I18NReference(ice::StringType auto const& fallback) noexcept;
14
15 static constexpr auto from_string(ice::String value) noexcept -> ice::I18NReference;
16
17 [[nodiscard]]
18 constexpr auto reference() const noexcept -> ice::String;
19
20 [[nodiscard]]
21 constexpr auto path() const noexcept -> ice::String;
22
23 [[nodiscard]]
24 constexpr auto key() const noexcept -> ice::String;
25
26 [[nodiscard]]
27 constexpr auto flags() const noexcept -> ice::i18n::I18NFlags;
28
29 [[nodiscard]]
30 constexpr auto fallback() const noexcept -> ice::String;
31
32 [[nodiscard]]
33 constexpr auto fallback_offset() const noexcept -> ice::nindex;
34
35 public:
36 char const* _data = nullptr;
38 ice::u8 _path = 0;
39 ice::u8 _key = 0;
42 };
43
44 constexpr I18NReference::I18NReference(ice::StringType auto const& fallback) noexcept
46 { }
47
49 : _data{ fallback.data() }
50 , _fallback{ fallback.size().u8() }
51 {
52 ICE_ASSERT_CORE(fallback.find_first_of('/') == ice::nindex_none);
53 }
54
56 {
57 if (value.is_empty())
58 {
59 return {};
60 }
61
62 I18NReference result{};
63 if (value.not_empty())
64 {
65 // Assign the data
66 result._data = value.data();
67 result._hash = ice::hash32(value);
68
69 // We assume this is always valid, since we don't want to handle invalid i18n strings anyway
71 value,
72 result._hash,
73 result._path,
74 result._key,
75 result._flags,
76 result._fallback
77 );
78 }
79 return result;
80 }
81
82 constexpr auto I18NReference::reference() const noexcept -> ice::String
83 {
84 // We don't want to subtract anything unless we have at least one character.
85 return { _data, static_cast<ice::ncount::base_type>(_path + _key) };
86 }
87
88 constexpr auto I18NReference::path() const noexcept -> ice::String
89 {
90 return { _data, static_cast<ice::ncount::base_type>(_path - static_cast<bool>(_path)) };
91 }
92
93 constexpr auto I18NReference::key() const noexcept -> ice::String
94 {
95 return { _data + _path, static_cast<ice::ncount::base_type>(_key) };
96 }
97
98 constexpr auto I18NReference::flags() const noexcept -> ice::i18n::I18NFlags
99 {
100 return ice::i18n::I18NFlags{ ice::String{ _data + _path + _key + static_cast<u8>(_flags != 0), _flags } };
101 }
102
103 constexpr auto I18NReference::fallback() const noexcept -> ice::String
104 {
105 return { _data + fallback_offset(), _fallback };
106 }
107
108 constexpr auto I18NReference::fallback_offset() const noexcept -> ice::nindex
109 {
110 ice::u8 const fallback_prefix = _path + _key + _flags;
111 if (_fallback == 0)
112 {
113 return fallback_prefix;
114 }
115 else if (fallback_prefix == 0)
116 {
117 return 0_index;
118 }
119 else
120 {
121 return ice::nindex{ fallback_prefix + static_cast<u8>(_flags != 0) + 1u };
122 }
123 }
124
125 constexpr auto operator""_i18n(char const* text, size_t size) noexcept -> I18NReference
126 {
127 return ice::I18NReference::from_string(ice::String{ text, size });
128 }
129
130
131 // Compile-Time Unit Tests
132
133 static_assert(I18NReference{ "Fallback Only"_str }.fallback() == "Fallback Only"_str, "Assigning a string directly always makes it a 'fallback' value");
134 static_assert(I18NReference{ "Fallback Only"_str }.reference() == ""_str, "Assigned a string results in an empty 'reference' value");
135 static_assert(I18NReference{ "Fallback Only"_str }.path() == ""_str, "Assigned a string results in an empty 'path' value");
136 static_assert(I18NReference{ "Fallback Only"_str }.key() == ""_str, "Assigned a string results in an empty 'key' value");
137 static_assert(I18NReference{ "Fallback Only"_str }.flags() == ""_str, "Assigned a string results in an empty 'flags' value");
138 // static_assert(I18NString{ "a/b"_str }); TODO: Hide behind a special define to test expected errors!
139
140 static_assert("a/b no-builtin"_i18n.fallback() == ""_str, "Assigning the shortest reference returns an empty 'fallback' value");
141 static_assert("a/b no-builtin"_i18n.reference() == "a/b"_str, "Assigning the shortest reference is valid with one character on both 'path' and 'key' values");
142 static_assert("a/b no-builtin"_i18n.path() == "a"_str, "Assigning the shortest reference returns the proper 'path' value");
143 static_assert("a/b no-builtin"_i18n.key() == "b"_str, "Assigning the shortest reference returns the proper 'key' value");
144 static_assert("a/b no-builtin"_i18n.flags() == "no-builtin"_str, "Assigning the shorest reference with 'no-builtin' flags returns that value");
145
146 static_assert("builtin.core.i18n.test/test.id"_i18n.fallback() == ""_str, "Assigning a proper test reference without flags returns an empty 'fallback' value");
147 static_assert("builtin.core.i18n.test/test.id"_i18n.reference() == "builtin.core.i18n.test/test.id"_str, "Assigning a proper test reference returns it's value");
148 static_assert("builtin.core.i18n.test/test.id"_i18n.path() == "builtin.core.i18n.test"_str, "Assigning a proper test reference the 'path' value");
149 static_assert("builtin.core.i18n.test/test.id"_i18n.key() == "test.id"_str, "Assigning a proper test reference returns the 'key' value");
150 static_assert("builtin.core.i18n.test/test.id"_i18n.flags() == ""_str, "Assigning a proper test reference returns empty 'flags' value");
151
152 static_assert("builtin.core.i18n.test/test.id no-flags"_i18n.fallback() == ""_str, "Assigning a reference with flags an empty 'fallback' value");
153 static_assert("builtin.core.i18n.test/test.id no-flags"_i18n.reference() == "builtin.core.i18n.test/test.id"_str, "Assigning a reference with flags returns it's value");
154 static_assert("builtin.core.i18n.test/test.id no-flags"_i18n.path() == "builtin.core.i18n.test"_str, "Assigning a reference with flags the 'path' value");
155 static_assert("builtin.core.i18n.test/test.id no-flags"_i18n.key() == "test.id"_str, "Assigning reference with flags returns the 'key' value");
156 static_assert("builtin.core.i18n.test/test.id no-flags"_i18n.flags() == "no-flags"_str, "Assigning reference with flags returns expected 'flags' value");
157
158 static_assert("builtin.core.i18n.test/test.id|Expected Fallback"_i18n.fallback() == "Expected Fallback"_str, "Assigning a reference with fallback returns expected 'fallback' value");
159 static_assert("builtin.core.i18n.test/test.id|Expected Fallback"_i18n.reference() == "builtin.core.i18n.test/test.id"_str, "Assigning a reference with fallback returns expected 'reference' value");
160 static_assert("builtin.core.i18n.test/test.id|Expected Fallback"_i18n.path() == "builtin.core.i18n.test"_str, "Assigning a reference with fallback the 'path' value");
161 static_assert("builtin.core.i18n.test/test.id|Expected Fallback"_i18n.key() == "test.id"_str, "Assigning reference with fallback returns the 'key' value");
162 static_assert("builtin.core.i18n.test/test.id|Expected Fallback"_i18n.flags() == ""_str, "Assigning reference with fallback returns empty 'flags' value");
163
164 static_assert("builtin.core.i18n.test/test.id no-flags|Expected Fallback"_i18n.fallback() == "Expected Fallback"_str, "Assigning a reference with flags and fallback returns expected 'fallback' value");
165 static_assert("builtin.core.i18n.test/test.id no-flags|Expected Fallback"_i18n.reference() == "builtin.core.i18n.test/test.id"_str, "Assigning a reference with flags and fallback returns expected 'reference' value");
166 static_assert("builtin.core.i18n.test/test.id no-flags|Expected Fallback"_i18n.path() == "builtin.core.i18n.test"_str, "Assigning a reference with flags and fallback the 'path' value");
167 static_assert("builtin.core.i18n.test/test.id no-flags|Expected Fallback"_i18n.key() == "test.id"_str, "Assigning reference with flags and fallback returns the 'key' value");
168 static_assert("builtin.core.i18n.test/test.id no-flags|Expected Fallback"_i18n.flags() == "no-flags"_str, "Assigning reference with flags and fallback returns empty expected 'flags' value");
169
170 // Ensure this fails from time to time remove 'no-builtin' to check
171 // static_assert("a/b |Fallback Message"_i18n.fallback() == "|Fallback Messag"_str, "Fallback message is parsed correctly after a space in the flags' part");
172
173} // namespace ice
#define ICE_ASSERT_CORE(expression)
Definition assert_core.hxx:43
Definition i18n_reference.hxx:9
constexpr I18NReference() noexcept=default
ice::u8 _fallback
Definition i18n_reference.hxx:41
ice::u8 _flags
Definition i18n_reference.hxx:40
constexpr auto fallback() const noexcept -> ice::String
Definition i18n_reference.hxx:103
ice::u8 _key
Definition i18n_reference.hxx:39
constexpr auto flags() const noexcept -> ice::i18n::I18NFlags
Definition i18n_reference.hxx:98
constexpr auto reference() const noexcept -> ice::String
Definition i18n_reference.hxx:82
static constexpr auto from_string(ice::String value) noexcept -> ice::I18NReference
Definition i18n_reference.hxx:55
constexpr auto path() const noexcept -> ice::String
Definition i18n_reference.hxx:88
ice::u32 _hash
Definition i18n_reference.hxx:37
constexpr auto key() const noexcept -> ice::String
Definition i18n_reference.hxx:93
ice::u8 _path
Definition i18n_reference.hxx:38
char const * _data
Definition i18n_reference.hxx:36
constexpr auto fallback_offset() const noexcept -> ice::nindex
Definition i18n_reference.hxx:108
Definition i18n_detail.hxx:6
constexpr void parse(ice::String in_str, ice::u32 &out_hash, ice::u8 &out_path, ice::u8 &out_key, ice::u8 &out_flags, ice::u8 &out_fallback) noexcept
Definition i18n_detail.hxx:81
SPDX-License-Identifier: MIT.
Definition array.hxx:12
ice::BasicString< char > String
Definition string.hxx:82
constexpr auto hash32(ice::String value) noexcept -> ice::u32
Definition string.hxx:105
std::uint32_t u32
Definition types.hxx:26
std::uint8_t u8
Definition types.hxx:24
static constexpr ice::nindex_invalid_t nindex_none
Definition nindex.hxx:56
Definition i18n_detail.hxx:9
ice::detail::nvalue_base_utype base_type
Definition nvalue.hxx:75
Definition nindex.hxx:13