acme
Foundational cross-platform layer of the ca2 framework
Loading...
Searching...
No Matches
encoding_impl.h
1// Created by camilo on 2022-11-07 16:02 <3ThomasBorregaardSorensen!!
2#pragma once
3
4
5
6inline ::i32 utf8_o(::i8 cExtraBytes)
7{
8
9 switch (cExtraBytes)
10 {
11 case 0:
12 return 0x00000000UL;
13 case 1:
14 return 0x00003080UL;
15 case 2:
16 return 0x000E2080UL;
17 case 3:
18 return 0x03C82080UL;
19 case 4:
20 return 0xFA082080UL;
21 case 5:
22 return 0x82082080UL;
23 default:
24 return -1;
25 };
26
27}
28
29
30inline ::i8 utf8_e(::u8 c)
31{
32
33 if (c < 192)
34 return 0;
35 else if (c < 192 + 32)
36 return 1;
37 else if (c < 192 + 32 + 16)
38 return 2;
39 else if (c < 192 + 32 + 16 + 8)
40 return 3;
41 else if (c < 192 + 32 + 16 + 8 + 4)
42 return 4;
43 else
44 return 5;
45
46}
47
48
49
50
51inline character_count wd32_to_ansi_char_len(::wd32_character wch)
52{
53 if (wch == 0)
54 {
55 return 0;
56 }
57 else if (wch <= 0x7F)
58 {
59 // Plain ASCII
60 return 1;
61 }
62 else if (wch <= 0x07FF)
63 {
64 // 2-::u8 unicode
65 return 2;
66 }
67 else if (wch <= 0xFFFF)
68 {
69 // 3-::u8 unicode
70 return 3;
71 }
72 else if (wch <= 0x10FFFF)
73 {
74 // 4-::u8 unicode
75 return 4;
76 }
77 else
78 {
79 return -1;
80 }
81}
82
83
84inline character_count wd16_to_wd32_char(::wd32_character * output, const ::wd16_character * input, character_count len)
85{
86
87 if (len < 1)
88 {
89
90 return -1;
91
92 }
93
94 auto _1stSurrogateCandidate = input[0];
95
96 if (_1stSurrogateCandidate == 0)
97 {
98
99 return 0;
100
101 }
102
103 if (utf16_is_2nd_surrogate(_1stSurrogateCandidate))
104 {
105
106 // ERROR Maticki
107
108 return -1;
109
110 }
111 else if (utf16_is_1st_surrogate(_1stSurrogateCandidate))
112 {
113
114 if (len < 2)
115 {
116
117 return -1;
118
119 }
120
121 auto _2ndSurrogateCandidate = input[1];
122
123 if (utf16_is_2nd_surrogate(_2ndSurrogateCandidate))
124 {
125
126 *output = utf16_surrogate_to_utf32(_1stSurrogateCandidate, _2ndSurrogateCandidate);
127
128 return 2;
129
130 }
131 else
132 {
133
134 return -1;
135
136 }
137
138 }
139 else
140 {
141
142 *output = _1stSurrogateCandidate; // just candidate so, not surrogay-tea
143
144 return 1;
145
146 }
147
148}
149
150
151inline character_count ansi_to_wd32_char(::wd32_character * output, const_char_pointer input, character_count srclen)
152{
153
154 ::wd32_character wd32ch = 0;
155
156 ::u8 c;
157 ::i8 extraBytesToRead = utf8_e(*input);
158 ::i32 len = extraBytesToRead + 1;
159 if (srclen < len) return -1;
160 if (*input == '\0') return -1;
161 switch (extraBytesToRead)
162 {
163 case 5:
164 c = *input;
165 if (c == '\0') return -1;
166 wd32ch += c;
167 wd32ch <<= 6;
168 input++;
169 case 4:
170 c = *input;
171 if (c == '\0') return -1;
172 wd32ch += c;
173 wd32ch <<= 6;
174 input++;
175 case 3:
176 c = *input;
177 if (c == '\0') return -1;
178 wd32ch += c;
179 wd32ch <<= 6;
180 input++;
181 case 2:
182 c = *input;
183 if (c == '\0') return -1;
184 wd32ch += c;
185 wd32ch <<= 6;
186 input++;
187 case 1:
188 c = *input;
189 if (c == '\0') return -1;
190 wd32ch += c;
191 wd32ch <<= 6;
192 input++;
193 case 0:
194 c = *input;
195 if (c == '\0') return -1;
196 wd32ch += c;
197 input++;
198 }
199
200 wd32ch -= (::wd32_character)utf8_o(extraBytesToRead);
201 *output = wd32ch;
202
203 return len;
204
205}
206
207
208inline ::i64 _ansi_to_wd32_char(const_char_pointer *ppsz, character_count * psrclen)
209{
210
211 ::wd32_character wd32ch = 0;
212
213 auto used_len = ansi_to_wd32_char(&wd32ch, *ppsz, *psrclen);
214
215 if (used_len < 0)
216 {
217
218 return -1;
219
220 }
221
222 *ppsz += used_len;
223
224 *psrclen -= used_len;
225
226 return wd32ch;
227
228}
229
230
231/* Some fundamental constants */
232#define UNI_REPLACEMENT_CHAR (::wd32_character)0x0000FFFD
233#define UNI_MAX_BMP (::wd32_character)0x0000FFFF
234#define UNI_MAX_UTF16 (::wd32_character)0x0010FFFF
235#define UNI_MAX_UTF32 (::wd32_character)0x7FFFFFFF
236#define UNI_MAX_LEGAL_UTF32 (::wd32_character)0x0010FFFF
237#define UNI_SUR_HIGH_START (::wd32_character)0xD800
238#define UNI_SUR_HIGH_END (::wd32_character)0xDBFF
239#define UNI_SUR_LOW_START (::wd32_character)0xDC00
240#define UNI_SUR_LOW_END (::wd32_character)0xDFFF
241//#define false 0
242//#define true 1
243// /* --------------------------------------------------------------------- */
244// status_resut wd32_to_wd16 (
245// const UTF32** sourceStart, const UTF32* sourceEnd,
246// UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
247// ConversionResult result = conversionOK;
248// const UTF32* source = *sourceStart;
249// UTF16* target = *targetStart;
250// while (source < sourceEnd) {
251// UTF32 ch;
252// if (target >= targetEnd) {
253// result = targetExhausted; break;
254// }
255// ch = *source++;
256// if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
257// /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
258// if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
259// if (flags == strictConversion) {
260// --source; /* return to the illegal value itself */
261// result = sourceIllegal;
262// break;
263// } else {
264// *target++ = UNI_REPLACEMENT_CHAR;
265// }
266// } else {
267// *target++ = (UTF16)ch; /* normal case */
268// }
269// } else if (ch > UNI_MAX_LEGAL_UTF32) {
270// if (flags == strictConversion) {
271// result = sourceIllegal;
272// } else {
273// *target++ = UNI_REPLACEMENT_CHAR;
274// }
275// } else {
276// /* target is a character in range 0xFFFF - 0x10FFFF. */
277// if (target + 1 >= targetEnd) {
278// --source; /* Back up source pointer! */
279// result = targetExhausted; break;
280// }
281// ch -= halfBase;
282// *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
283// *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
284// }
285// }
286// *sourceStart = source;
287// *targetStart = target;
288// return result;
289// }
290
291
292inline character_count wd32_to_wd16_char(::wd16_character * target, ::wd32_character wd32ch)
293{
294
295 const ::i32 halfShift = 10; /* used for shifting by 10 bits */
296 const ::wd32_character halfBase = 0x0010000UL;
297 const ::wd32_character halfMask = 0x3FFUL;
298
299 if (wd32ch <= UNI_MAX_BMP)
300 {
301
302 /* Target is a character <= 0xFFFF */
303 /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
304 if (wd32ch >= UNI_SUR_HIGH_START && wd32ch <= UNI_SUR_LOW_END)
305 {
306
307 //if (flags == strictConversion) {
308 //--source; /* return to the illegal value itself */
309 //result = sourceIllegal;
310 return -1;
311
312 }
313
314 *target = (::wd16_character)wd32ch; /* normal case */
315
316 return 1;
317
318 }
319 else if (wd32ch > UNI_MAX_LEGAL_UTF32)
320 {
321
322 return -1;
323
324 }
325
326 wd32ch -= halfBase;
327
328 *target++ = (::wd16_character)((wd32ch >> halfShift) + UNI_SUR_HIGH_START);
329
330 *target = (::wd16_character)((wd32ch & halfMask) + UNI_SUR_LOW_START);
331
332 return 2;
333
334}
335
336
337inline character_count wd16_to_ansi_char_len(const ::wd16_character ** ppu16a, character_count * plen)
338{
339
340 ::wd32_character wd32ch;
341
342 auto used_len = wd16_to_wd32_char(&wd32ch, *ppu16a, *plen);
343
344 if (used_len < 0)
345 {
346
347 return -1;
348
349 }
350
351 *plen -= used_len;
352
353 *ppu16a += used_len;
354
355 return wd32_to_ansi_char_len(wd32ch);
356
357}
358
359
360inline character_count wd16_to_ansi_char(char_pointer psz, const ::wd16_character ** ppu16a, character_count * plen)
361{
362
363 ::wd32_character wd32ch;
364
365 auto used_len = wd16_to_wd32_char(&wd32ch, *ppu16a, *plen);
366
367 if (used_len < 0)
368 {
369
370 return -1;
371
372 }
373
374 *plen -= used_len;
375
376 *ppu16a += used_len;
377
378 return wd32_to_ansi_char(psz, wd32ch);
379
380}
381
382
383inline character_count wd16_to_wd32_char_len(const ::wd16_character * input, character_count len)
384{
385
386 if (len < 1)
387 {
388
389 return -1;
390
391 }
392
393 auto _1stSurrogateCandidate = input[0];
394
395 if (_1stSurrogateCandidate == 0)
396 {
397
398 return 0;
399
400 }
401
402 if (utf16_is_2nd_surrogate(_1stSurrogateCandidate))
403 {
404
405 // ERROR Maticki
406
407 return -1;
408
409 }
410 else if (utf16_is_1st_surrogate(_1stSurrogateCandidate))
411 {
412
413 if (len < 2)
414 {
415
416 return -1;
417
418 }
419
420 auto _2ndSurrogateCandidate = input[1];
421
422 if (utf16_is_2nd_surrogate(_2ndSurrogateCandidate))
423 {
424
425 return 2;
426
427 }
428 else
429 {
430
431 return -1;
432
433 }
434
435 }
436 else
437 {
438
439 return 1;
440
441 }
442
443}
444
445
446inline character_count wd32_to_ansi_char(char_pointer psz, ::wd32_character wch)
447{
448
449 if (wch <= 0)
450 {
451 return 0;
452 }
453 else if (wch <= 0x7F)
454 {
455 // Plain ASCII
456 psz[0] = (::i8)wch;
457 return 1;
458 }
459 else if (wch <= 0x07FF)
460 {
461 // 2-::u8 unicode
462 psz[0] = (::i8)(((wch >> 6) & 0x1F) | 0xC0);
463 psz[1] = (::i8)(((wch >> 0) & 0x3F) | 0x80);
464 return 2;
465 }
466 else if (wch <= 0xFFFF)
467 {
468 // 3-::u8 unicode
469 psz[0] = (::i8)(((wch >> 12) & 0x0F) | 0xE0);
470 psz[1] = (::i8)(((wch >> 6) & 0x3F) | 0x80);
471 psz[2] = (::i8)(((wch >> 0) & 0x3F) | 0x80);
472 return 3;
473 }
474 else if (wch <= 0x10FFFF)
475 {
476 // 4-::u8 unicode
477 psz[0] = (::i8)(((wch >> 18) & 0x07) | 0xF0);
478 psz[1] = (::i8)(((wch >> 12) & 0x3F) | 0x80);
479 psz[2] = (::i8)(((wch >> 6) & 0x3F) | 0x80);
480 psz[3] = (::i8)(((wch >> 0) & 0x3F) | 0x80);
481 return 4;
482 }
483 else
484 {
485 return -1;
486 }
487}
488
489
490#if WCHAR_T_SIZE == 16
491
492
493inline character_count utf8_to_unichar_len(const_char_pointer psz) { return ansi_to_wd16_len(psz, string_safe_length(psz)); }
494inline character_count utf8_to_unichar_len(const_char_pointer psz, character_count srclen) { return ansi_to_wd16_len(psz, srclen); }
495inline character_count utf8_to_unichar(::wd16_character * pwsz, const_char_pointer psz) { return ansi_to_wd16(pwsz, psz, string_safe_length(psz)); }
496inline character_count utf8_to_unichar(::wd16_character * pwsz, const_char_pointer psz, character_count srclen) { return ansi_to_wd16(pwsz, psz, srclen); }
497
498
499inline character_count unichar_to_utf8_len(const ::wd16_character * pwsz) { return wd16_to_ansi_len(pwsz, string_safe_length(pwsz)); }
500inline character_count unichar_to_utf8_len(const ::wd16_character * pwsz, character_count srclen) { return wd16_to_ansi_len(pwsz, srclen); }
501inline character_count unichar_to_utf8(char_pointer psz, const ::wd16_character * pwsz) { return wd16_to_ansi(psz, pwsz, string_safe_length(pwsz)); }
502inline character_count unichar_to_utf8(char_pointer psz, const ::wd16_character * pwsz, character_count srclen) { return wd16_to_ansi(psz, pwsz, srclen); }
503
504
505#else
506
507
508inline character_count utf8_to_unichar_len(const_char_pointer psz, character_count srclen) { return ansi_to_wd32_len(psz, srclen); }
509inline character_count utf8_to_unichar(::wd32_character * pwsz, const_char_pointer psz, character_count srclen) { return ansi_to_wd32(pwsz, psz, srclen); }
510
511
512inline character_count unichar_to_utf8_len(const ::wd32_character * pwsz, character_count srclen) { return wd32_to_ansi_len(pwsz, srclen); }
513inline character_count unichar_to_utf8(char_pointer psz, const ::wd32_character * pwsz, character_count srclen) { return wd32_to_ansi(psz, pwsz, srclen); }
514
515
516#endif
517
518
519