Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
UTFConvert.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Characters_UTFConvert_h_
5#define _Stroika_Foundation_Characters_UTFConvert_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <optional>
10#include <span>
11
12#if __has_include("boost/locale/encoding_utf.hpp")
13#include <boost/locale/encoding_utf.hpp>
14#endif
15
17
18/**
19 * \file
20 * This module is designed to provide mappings between various UTF encodings of UNICODE characters.
21 */
22
24
25 /**
26 * \brief list of external UNICODE character encodings, for file IO (eDEFAULT = eUTF8)
27 *
28 * \note - UTF-7 **not** supported because very few places support it/ever used it, and
29 * https://en.wikipedia.org/wiki/UTF-7 says its obsolete. So don't bother.
30 */
32 eUTF8,
33 eUTF16_BE,
34 eUTF16_LE,
35 eUTF16 = std::endian::native == std::endian::big ? eUTF16_BE : eUTF16_LE,
36 eUTF32_BE,
37 eUTF32_LE,
38 eUTF32 = std::endian::native == std::endian::big ? eUTF32_BE : eUTF32_LE,
39
40 eDEFAULT = eUTF8,
41 };
42
43 /**
44 * \brief UTFConvert is designed to provide mappings between various UTF encodings of UNICODE characters.
45 *
46 * This area of C++ is a confusingly broken cluster-fuck. Its pretty simple, and well defined, but painful todo
47 * with std::codecvt variants...
48 *
49 * Available (plausible) implementations:
50 * o std C++ code_cvt (on windows, slow)
51 * o Boost locale utf_to_utf (untested so not sure about this)
52 * o Windows API (appears most performant)
53 * o Stroika portable implementation, based on libutfxx (slow but portable, and works)
54 * o nemtrif/utfcpp (haven't tried yet)
55 * o simdutf (allegedly fastest, but haven't tried yet)
56 *
57 * Design Choices:
58 * o Could have API to COMPUTE size of output buffer. But thats as much work to compute as actually doing the conversion (generally close).
59 * So - instead - have ComputeTargetBufferSize () API, which quickly computes a reasonable buffer size, and just
60 * assert we never run out of space. Not a great plan, but probably pretty good, most of the time.
61 *
62 * API setup so the compute-buf-size routine COULD walk the source and compute the exact needed size, without changing API.
63 * o Invalid character handling - defaults to generating exception, but can specify options.fInvalidCharacterReplacement in CTOR.
64 *
65 * \note Byte Order Markers
66 * UTFConvert does NOT support byte order marks (BOM) - for that - see Streams::BinaryToText::Reader, and Streams::TextToBinary::Writer or TextConvert
67 * The reason is - the conversion methods are templated on the char8_t, char16_t e etc char TYPE, and this doesn't work well with
68 * dynamically detecting the character type at runtime.
69 *
70 * \notes about mbstate_t
71 * mbstate_t is used by the std::codecvt apis and nothing else, and seems opaque and not any obvious use, so just
72 * not used in this API, and faked when needed for codecvt.
73 *
74 * Web Pages/ Specs:
75 * o https://en.wikipedia.org/wiki/UTF-8
76 * o https://en.wikipedia.org/wiki/UTF-16
77 *
78 * Though you can construct your own UTFConvert with different options, a typical application will just use
79 * \code
80 * UTFConvert::kThe
81 * \endcode
82 */
83 class UTFConvert final {
84 public:
85 /**
86 */
87 struct Options {
88 /**
89 * if fInvalidCharacterReplacement is nullopt (the default) - throw on invalid characters, and
90 * otherwise use the value provided in fInvalidCharacterReplacement as the replacement.
91 *
92 * \see kDefaultMissingReplacementCharacter
93 */
94 optional<Character> fInvalidCharacterReplacement;
95
96 /**
97 * Sensible replacement character (value for fInvalidCharacterReplacement)
98 * 'UNI_REPLACEMENT_CHAR' from https://github.com/codebrainz/libutfxx/blob/master/utf/ConvertUTF.h
99 */
100 static inline constexpr Character kDefaultMissingReplacementCharacter = Character{(char32_t)0x0000FFFD};
101
102 /**
103 * Different implementations of UTF character conversion
104 */
105 enum class Implementation {
106
107 // Based on libutfxx
108 eStroikaPortable,
109
110#if __has_include("boost/locale/encoding_utf.hpp")
111 // unteseted/unimplmeneted so far
112 eBoost_Locale,
113#endif
114
115#if qStroika_Platform_Windows
116 // Seems fastest for windows
117 eWindowsAPIWide2FromMultibyte,
118#endif
119
120 // CPPREFERENCE docs on std::codecvt somewhat confusing about what is deprecated, but it appears the interface as a whole is still viable as of C++20
121 // and just several sub-interfaces are deprecated -- LGP 2023-06-28
122 // https://cplusplus.github.io/LWG/issue3767
123 eCodeCVT,
124
125 // @todo LIBS TO LOOK AT
126 // https://github.com/nemtrif/utfcpp
127 // https://github.com/simdutf/simdutf ((probably best/fastest - so try))
128 };
129
130 /**
131 * \note that since not all implementations support all APIs, this is just a hint. Other implementations maybe
132 * used as needed.
133 */
134 optional<Implementation> fPreferredImplementation;
135 };
136
137 public:
138 /**
139 * As of Stroika v3.0d2, if options.fInvalidCharacterReplacement specified, options.fPreferredImplementation must be null or eStroikaPortable.
140 * That limitation could be lifted in the future.
141 *
142 * A converter is copyable (but thats not super helpful). It maintains essentially no state, except for the options its constructed with.
143 */
144#if qCompilerAndStdLib_default_member_initializer_needed_within_enclosing_class_Buggy
145 constexpr UTFConvert (const Options& options);
146 constexpr UTFConvert (); ///< \brief Same as UTFConvert{Options{}}
147#else
148 constexpr UTFConvert (const Options& options = {});
149#endif
150 constexpr UTFConvert (const UTFConvert&) noexcept = default;
151
152 public:
153 /**
154 */
155 constexpr Options GetOptions () const;
156
157 public:
158 /**
159 * Quickly compute the buffer size needed for a call to Convert (or ConvertSpan)
160 *
161 * This will frequently (greatly) over-estimate the amount of space needed but it will always produce a sufficient answer without much computation.
162 *
163 * \note buffer size NOT in 'bytes' but in units of 'TO' - so char32_t, or char8_t, or whatever.
164 *
165 * \note future implementations might do more work to compute a sometimes smaller, less wasteful buffer size. Maybe
166 * look at size, and if small just overestimate, but if input span is large, maybe worth the trouble and count
167 * multibyte characters?
168 *
169 * For the overload taking a size, and not the actual FROM span, this computes the upper bound size required.
170 *
171 * @See ConvertQuietly ()
172 * @See Convert ()
173 * @aliases used to be called QuickComputeConversionOutputBufferSize
174 */
175 template <IUNICODECanUnambiguouslyConvertTo TO, IUNICODECanUnambiguouslyConvertFrom FROM>
176 static constexpr size_t ComputeTargetBufferSize (span<const FROM> src)
177 requires (not is_const_v<TO>);
178 template <IUNICODECanUnambiguouslyConvertTo TO, IUNICODECanUnambiguouslyConvertFrom FROM>
179 static constexpr size_t ComputeTargetBufferSize (span<FROM> src)
180 requires (not is_const_v<TO>);
181 template <IUNICODECanUnambiguouslyConvertTo TO, IUNICODECanUnambiguouslyConvertFrom FROM>
182 static constexpr size_t ComputeTargetBufferSize (size_t srcSize);
183
184 public:
185 /**
186 * Check if each character in the span fits in a 2-byte encoding (ie no UTF-16 surrogate pairs)
187 */
188 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
189 static constexpr bool AllFitsInTwoByteEncoding (span<const CHAR_T> s) noexcept;
190
191 public:
192 /**
193 * \brief Convert between UTF-N encoded (including the special case of ASCII, and Latin1) character spans (e.g. UTF8 to UTF32), throw on failure, resulting span<>.
194 *
195 * Compared with the Convert () API, this loses information (number of source characters consumed).
196 * Not a general purpose API. But very frequently this is all you need, for the next stage, a new span,
197 * and for that case, this saves a little typing.
198 *
199 * NOTE - the returned span is ALWAYS (not necessarily proper) sub-span of its 'target' argument
200 *
201 * \par Example Usage
202 * \code
203 * StackBuffer<wchar_t> buf{Memory::eUninitialized, UTFConvert::ComputeTargetBufferSize<wchar_t> (src)};
204 * span<wchar_t> spanOfTargetBufferUsed = UTFConvert::kThe.ConvertSpan (src, span{buf});
205 * return String{spanOfTargetBufferUsed};
206 * \endcode
207 */
208 template <IUNICODECanUnambiguouslyConvertFrom SRC_T, IUNICODECanUnambiguouslyConvertTo TRG_T>
209 nonvirtual span<TRG_T> ConvertSpan (span<const SRC_T> source, span<TRG_T> target) const
210 requires (not is_const_v<TRG_T>);
211 template <IUNICODECanUnambiguouslyConvertFrom SRC_T, IUNICODECanUnambiguouslyConvertTo TRG_T>
212 nonvirtual span<TRG_T> ConvertSpan (span<SRC_T> source, span<TRG_T> target) const
213 requires (not is_const_v<TRG_T>);
214
215 public:
216 /**
217 * Result of Convert() call - saying how much of the source was consumed, and how many units of the target were produced.
218 * units depend on the call, char8_ts, or char16_ts, or char32_ts.
219 */
221 size_t fSourceConsumed{};
222 size_t fTargetProduced{};
223 };
224
225 public:
226 /**
227 * \brief Convert between UTF-N encoded strings/spans (including the special case of ASCII, and Latin1) (e.g. UTF8 to UTF32), throw on failure
228 *
229 * \note Failures
230 * Failures can be because of illegal input code-point or source exhausted. If you want to deal with partial characters,
231 * you must use the ConvertQuietly API.
232 *
233 * For overloads taking a target span:
234 * \pre size of target span must be at least as large as specified by ComputeTargetBufferSize
235 *
236 * Wrapper on ConvertQuietly, that throws when bad source data input, and asserts out when bad target size (insuffient for buffer).
237 *
238 * Variations from char8_t are overloaded to optionally take a multibyteConversionState parameter.
239 *
240 * The types
241 * o char
242 * o wchar_t
243 * are mapped to the appropriate above type.
244 *
245 * Source and target spans can be of any IUNICODECanUnambiguouslyConvertFrom character type (but source const and target non-const)
246 * (or basic_string of said)...
247 *
248 * \par Example Usage
249 * \code
250 * StackBuffer<wchar_t> buf{Memory::eUninitialized, UTFConvert::ComputeTargetBufferSize<wchar_t> (src)};
251 * auto result = UTFConvert::kThe.Convert (src, span{buf});
252 * return String{buf.begin (), buf.begin () + result.fTargetProduced}; // OR better yet see ConvertSpan
253 * \endcode
254 *
255 * @see ConvertQuietly for span overloads
256 *
257 * String overloads are simple wrappers on the span code but with simpler to use arguments:
258 * \par Example Usage
259 * \code
260 * wstring wide_fred = UTFConvert::kThe.Convert<wstring> (u8"fred");
261 * u16string u16_fred = UTFConvert::kThe.Convert<u16string> (U"fred");
262 * \endcode
263 */
264 template <IUNICODECanUnambiguouslyConvertFrom SRC_T, IUNICODECanUnambiguouslyConvertTo TRG_T>
265 nonvirtual ConversionResult Convert (span<const SRC_T> source, span<TRG_T> target) const;
266 template <IUNICODECanUnambiguouslyConvertFrom SRC_T, IUNICODECanUnambiguouslyConvertTo TRG_T>
267 nonvirtual ConversionResult Convert (span<SRC_T> source, span<TRG_T> target) const;
268 template <typename TO, typename FROM>
269 nonvirtual TO Convert (const FROM& from) const
270 requires ((same_as<TO, string> or same_as<TO, wstring> or same_as<TO, u8string> or same_as<TO, u16string> or same_as<TO, u32string>) and
271 (same_as<FROM, string> or same_as<FROM, wstring> or same_as<FROM, u8string> or same_as<FROM, u16string> or same_as<FROM, u32string>));
272
273 public:
274 /**
275 * \brief used for ConvertQuietly
276 *
277 * \note no need to have status code for 'targetExhausted' because we assert error in that case. DONT DO IT.
278 */
280 /**
281 * conversion successful
282 */
283 ok,
284
285 /**
286 * partial character in source, but hit end: what is there is a legal start of a character, so the rest may
287 * come in a later call. A byte that can never begin a character is sourceIllegal, even at the end.
288 */
289 sourceExhausted,
290
291 /**
292 * Source sequence is illegal/malformed - only generated if fOptions.fInvalidCharacterReplacement == nullopt
293 * (otherwise the replacement is used, and conversion goes on)
294 */
295 sourceIllegal
296 };
297
298 public:
299 /**
300 */
301 struct ConversionResultWithStatus : ConversionResult {
302 ConversionStatusFlag fStatus{};
303 };
304
305 public:
306 /**
307 * \brief Convert UTF encoded (char8_t, char16_t, char32_t, char, wchar_t, ASCII, Latin1) characters to from each other without format exceptions (still may raise memory exceptions if not enuf space)
308 *
309 * \see Convert () above for details. This only differs from Convert, in that it returns a result flag instead
310 * of throwing on errors.
311 *
312 * \note - possible error status values include 'illegal source', and 'source exhausted'. Source exhausted isn't always an
313 * error, but it is more often than not, so its treated as an error, and you must special case handling if you want
314 * to treat otherwise.
315 *
316 * So - ConvertQuietly () of many characters, but where the LAST character is complete WILL convert all the data up to the last
317 * character, return the number of characters consumed and produced, but ALSO indicate the source exhausted status - not OK.
318 *
319 * In case of errors, the return value still indicates how many characters were consumed before the error occurred, and the
320 * target produced before the error occured.
321 *
322 * Source and target spans can be of any IUNICODECanUnambiguouslyConvertFrom character type (but source const and target non-const)
323 *
324 * \pre target.size () >= ComputeTargetBufferSize<TRG_T> (source)
325 *
326 * \note, if given illegal UTF-8, or illegal ascii (ASCII) source input, the will either return
327 * with fStatus==sourceIllegal (if fOptions.fInvalidCharacterReplacement == nullopt), or will just use that
328 * fInvalidCharacterReplacement character, and treat this as not an error.
329 *
330 * \note multibyteConversionState is often ignored, but since some implementations may use it, it is required (to allow
331 * interface as a whole to always work without knowing which implementations require it).
332 */
333 template <IUNICODECanUnambiguouslyConvertFrom SRC_T, IUNICODECanUnambiguouslyConvertTo TRG_T>
334 nonvirtual ConversionResultWithStatus ConvertQuietly (span<const SRC_T> source, span<TRG_T> target) const
335 requires (not is_const_v<TRG_T>);
336
337 public:
338 /**
339 * See what the given offset in the source text translates to in the target text
340 *
341 * For example, if you are translating UTF32 text to UTF8 text, the 3rd character in
342 * UTF32 text would start at offset 3, but in the corresponding UTF8 text it might
343 * start at offset 6.
344 */
345 template <IUNICODECanUnambiguouslyConvertTo TRG_T, IUNICODECanUnambiguouslyConvertFrom SRC_T>
346 nonvirtual size_t ConvertOffset (span<const SRC_T> source, size_t srcIndex) const;
347
348 public:
349 /**
350 * Given a span, return the number of code-point units in the (full UNICODE) character, or return nullopt if the span of characters is invalid or incomplete
351 *
352 * if argument span empty, or insufficient to complete a character, this returns nullopt.
353 *
354 * For example, if CHAR_T == char32_t, or Character, this returns 1.
355 * If CHAR_T is ASCII, this returns 1.
356 */
357 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
358 static constexpr optional<size_t> NextCharacter (span<const CHAR_T> s);
359
360 public:
361 /**
362 * Given a span of UTF-encoded characters, return the number of characters (unicode code points) in the span, or nullopt if any character is incomplete/invalid
363 * (should we throw or skip or ???) - not sure
364 *
365 * \note for 'char' - the characters are ASSUMED/REQUIRED to be ASCII
366 */
367 template <IUNICODECanUnambiguouslyConvertFrom CHAR_T>
368 static constexpr optional<size_t> ComputeCharacterLength (span<const CHAR_T> s);
369
370 public:
371 /**
372 * \brief Nearly always use this default UTFConvert.
373 */
374 static const UTFConvert kThe;
375
376 public:
377 static void Throw (ConversionStatusFlag cr, size_t errorAtSourceOffset);
378
379 private:
380 // find same size, and then remove_const, and then add back const
381 template <typename SRC_OF_CONSTNESS_T, typename TYPE_T>
382 using AddConstIfMatching_ = conditional_t<is_const_v<SRC_OF_CONSTNESS_T>, add_const_t<TYPE_T>, TYPE_T>;
383 template <typename TYPE_T>
384 using MapSizes_ =
385 conditional_t<sizeof (TYPE_T) == 1, conditional_t<same_as<TYPE_T, Latin1>, TYPE_T, char8_t>, conditional_t<sizeof (TYPE_T) == 2, char16_t, char32_t>>;
386 template <typename TYPE_T>
387 using CompatibleT_ = AddConstIfMatching_<TYPE_T, MapSizes_<TYPE_T>>;
388
389 private:
390 // need generic way to convert char to char8_t, and wchar_t to char16_t or char32_t, Character etc
391 template <IUNICODECanUnambiguouslyConvertFrom FromT>
392 static constexpr span<CompatibleT_<FromT>> ConvertToPrimitiveSpan_ (span<FromT> f);
393
394 private:
395 Options fOriginalOptions_;
396 Options fUsingOptions;
397
398#if qStroika_Platform_Windows
399 private:
400 static ConversionResultWithStatus ConvertQuietly_Win32_ (span<const char8_t> source, span<char16_t> target);
401 static ConversionResultWithStatus ConvertQuietly_Win32_ (span<const char16_t> source, span<char8_t> target);
402#endif
403
404 private:
405 static ConversionResultWithStatus ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement,
406 span<const char8_t> source, span<char16_t> target);
407 static ConversionResultWithStatus ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement,
408 span<const char8_t> source, span<char32_t> target);
409 static ConversionResultWithStatus ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement,
410 span<const char16_t> source, span<char32_t> target);
411 static ConversionResultWithStatus ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement,
412 span<const char32_t> source, span<char16_t> target);
413 static ConversionResultWithStatus ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement,
414 span<const char32_t> source, span<char8_t> target);
415 static ConversionResultWithStatus ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement,
416 span<const char16_t> source, span<char8_t> target);
417
418#if __has_include("boost/locale/encoding_utf.hpp")
419 private:
420 static ConversionResultWithStatus ConvertQuietly_boost_locale_ (span<const char8_t> source, const span<char16_t> target);
421#endif
422
423 private:
424 static ConversionResultWithStatus ConvertQuietly_codeCvt_ (span<const char8_t> source, span<char16_t> target);
425 static ConversionResultWithStatus ConvertQuietly_codeCvt_ (span<const char8_t> source, span<char32_t> target);
426 static ConversionResultWithStatus ConvertQuietly_codeCvt_ (span<const char16_t> source, span<char8_t> target);
427 static ConversionResultWithStatus ConvertQuietly_codeCvt_ (span<const char32_t> source, span<char8_t> target);
428
429 private:
430 static void ThrowIf_ (ConversionStatusFlag cr, size_t errorAtSourceOffset);
431
432 //********************** DEPRECATED BELOW ****************************
433 public:
434 enum [[deprecated ("Since Stroika v3.0d1, use class UTFConvert")]] LEGACY_ConversionResult {
435 conversionOK, /* conversion successful */
436 sourceExhausted, /* partial character in source, but hit end */
437 targetExhausted, /* insuff. room in target for conversion */
438 sourceIllegal /* source sequence is illegal/malformed */
439 };
440 enum [[deprecated ("Since Stroika v3.0d1, use class UTFConvert")]] ConversionFlags {
441 strictConversion = 0,
442 lenientConversion
443 };
444
445 /**
446 */
447 [[deprecated ("Since Stroika v3.0d1, could support, but not clearly any reason")]] static bool IsLegalUTF8Sequence (const char* source,
448 const char* sourceEnd);
449 [[deprecated ("Since Stroika v3.0d1, could support, but not clearly any reason")]] static bool IsLegalUTF8Sequence (const char8_t* source,
450 const char8_t* sourceEnd);
451
452 template <typename FROM, typename TO>
453 [[deprecated ("Since Stroika v3.0d1, use class UTFConvert")]] static inline size_t
454 QuickComputeConversionOutputBufferSize (const FROM* sourceStart, const FROM* sourceEnd)
455 {
456 return UTFConvert::ComputeTargetBufferSize<TO> (span<const FROM>{sourceStart, sourceEnd});
457 }
458 DISABLE_COMPILER_MSC_WARNING_START (4996);
459 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wdeprecated-declarations\"");
460 DISABLE_COMPILER_CLANG_WARNING_START ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
461 template <typename FROM, typename TO>
462 [[deprecated ("Since Stroika v3.0d1, use class UTFConvert::kThe")]] static LEGACY_ConversionResult
463 ConvertQuietly (const FROM** sourceStart, const FROM* sourceEnd, TO** targetStart, TO* targetEnd, ConversionFlags flags)
464 {
465 auto r = UTFConvert::kThe.ConvertQuietly (span{*sourceStart, sourceEnd}, span{*targetStart, targetEnd});
466 *sourceStart += get<1> (r);
467 *targetStart += get<2> (r);
468 switch (get<0> (r)) {
470 return LEGACY_ConversionResult::conversionOK;
472 return LEGACY_ConversionResult::sourceExhausted;
474 return LEGACY_ConversionResult::sourceIllegal;
475 default:
477 return LEGACY_ConversionResult::sourceIllegal;
478 }
479 }
480 template <typename FROM, typename TO>
481 [[deprecated ("Since Stroika v3.0d1, use class UTFConvert::kThe")]] static inline void
482 Convert (const FROM** sourceStart, const FROM* sourceEnd, TO** targetStart, TO* targetEnd, ConversionFlags /*flags*/)
483 {
484 RequireNotNull (sourceStart);
485 RequireNotNull (targetStart);
486 Require ((static_cast<size_t> (targetEnd - *targetStart) >= QuickComputeConversionOutputBufferSize<FROM, TO> (*sourceStart, sourceEnd)));
487
488 auto r = UTFConvert::kThe.Convert (span{*sourceStart, sourceEnd}, span{*targetStart, targetEnd});
489 *sourceStart += get<0> (r);
490 *targetStart += get<1> (r);
491 }
492 DISABLE_COMPILER_MSC_WARNING_END (4996);
493 DISABLE_COMPILER_GCC_WARNING_END ("GCC diagnostic ignored \"-Wdeprecated-declarations\"");
494 DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
495 };
496
497 /**
498 * This is a function that takes a span of bytes, and an OPTIONAL mbstate_t (TBD), and targetBuffer, translates into targetBuffer, and returns the changes.
499 * This utility wrapper funciton is meant to capture what you can easily put together from a (configured or default) UTFConvert,
500 * but in a form more easily used/consumed by a the BinaryToText::Reader code.
501 *
502 * @todo NEED EXAMPLE OR TO LOSE THIS... -- LGP 2023-09-12
503 */
504 template <typename OUTPUT_CHAR_T>
505 using UTFCodeConverter = function<UTFConvert::ConversionResult (span<const byte> source, span<OUTPUT_CHAR_T> targetBuffer)>;
506
507}
508
509/*
510 ********************************************************************************
511 ***************************** Implementation Details ***************************
512 ********************************************************************************
513 */
514#include "UTFConvert.inl"
515
516#endif /*_Stroika_Foundation_Characters_UTFConvert_h_*/
#define RequireNotNull(p)
Definition Assertions.h:350
#define AssertNotReached()
Definition Assertions.h:358
UTFConvert is designed to provide mappings between various UTF encodings of UNICODE characters.
Definition UTFConvert.h:83
nonvirtual ConversionResult Convert(span< const SRC_T > source, span< TRG_T > target) const
Convert between UTF-N encoded strings/spans (including the special case of ASCII, and Latin1) (e....
static const UTFConvert kThe
Nearly always use this default UTFConvert.
Definition UTFConvert.h:374
nonvirtual ConversionResultWithStatus ConvertQuietly(span< const SRC_T > source, span< TRG_T > target) const
Convert UTF encoded (char8_t, char16_t, char32_t, char, wchar_t, ASCII, Latin1) characters to from ea...
static constexpr bool AllFitsInTwoByteEncoding(span< const CHAR_T > s) noexcept
ConversionStatusFlag
used for ConvertQuietly
Definition UTFConvert.h:279
static constexpr optional< size_t > ComputeCharacterLength(span< const CHAR_T > s)
static constexpr optional< size_t > NextCharacter(span< const CHAR_T > s)
nonvirtual span< TRG_T > ConvertSpan(span< const SRC_T > source, span< TRG_T > target) const
Convert between UTF-N encoded (including the special case of ASCII, and Latin1) character spans (e....
nonvirtual size_t ConvertOffset(span< const SRC_T > source, size_t srcIndex) const
static constexpr size_t ComputeTargetBufferSize(span< const FROM > src)
UnicodeExternalEncodings
list of external UNICODE character encodings, for file IO (eDEFAULT = eUTF8)
Definition UTFConvert.h:31
function< UTFConvert::ConversionResult(span< const byte > source, span< OUTPUT_CHAR_T > targetBuffer)> UTFCodeConverter
Definition UTFConvert.h:505