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