eolib 0.6.1
A core C library for writing applications related to Endless Online
Loading...
Searching...
No Matches
data.c
Go to the documentation of this file.
1#include "eolib/data.h"
2#include "eolib/result.h"
3
4#include <limits.h>
5#include <stdlib.h>
6#include <string.h>
7#include <stdio.h>
8
9static size_t eo_reader_next_break_index(const EoReader *reader);
10
11/* strdup is a POSIX extension, not ISO C - unavailable (or undeclared under
12 * strict -std=c90) on some platforms/compilers. Allocates a 1-byte empty string. */
13static char *eo_empty_string(void)
14{
15 char *result = (char *)malloc(1);
16 if (result)
17 {
18 result[0] = '\0';
19 }
20 return result;
21}
22
23/*
24 * Unicode code points for Windows-1252 bytes 0x80-0x9F.
25 * Index 0 maps to byte 0x80, index 31 maps to byte 0x9F.
26 * A value of 0 means the byte is undefined in Windows-1252.
27 */
28static const uint32_t cp1252_unicode_extras[32] = {
29 0x20AC,
30 0,
31 0x201A,
32 0x0192,
33 0x201E,
34 0x2026,
35 0x2020,
36 0x2021,
37 0x02C6,
38 0x2030,
39 0x0160,
40 0x2039,
41 0x0152,
42 0,
43 0x017D,
44 0,
45 0,
46 0x2018,
47 0x2019,
48 0x201C,
49 0x201D,
50 0x2022,
51 0x2013,
52 0x2014,
53 0x02DC,
54 0x2122,
55 0x0161,
56 0x203A,
57 0x0153,
58 0,
59 0x017E,
60 0x0178,
61};
62
64{
65 int i;
66
67 if (codepoint <= 0x7F)
68 return (uint8_t)codepoint;
69
70 if (codepoint >= 0xA0 && codepoint <= 0xFF)
71 return (uint8_t)codepoint;
72
73 for (i = 0; i < 32; ++i)
74 {
75 if (cp1252_unicode_extras[i] == codepoint)
76 return (uint8_t)(0x80 + i);
77 }
78
79 return '?';
80}
81
82/*
83 * Converts a UTF-8 string to Windows-1252 in-place into `output`.
84 * `output` must be at least `input_len + 1` bytes.
85 * Returns the number of bytes written (excluding the null terminator).
86 * Valid UTF-8 multi-byte sequences are decoded and mapped to Windows-1252.
87 * Characters with no Windows-1252 representation are replaced with '?'.
88 * Bytes that do not form a valid UTF-8 sequence are passed through as-is.
89 */
90static size_t normalize_to_cp1252(const char *input, char *output, size_t input_len)
91{
92 size_t out_pos = 0;
93 size_t i = 0;
94
95 while (i < input_len)
96 {
97 uint8_t b0 = (uint8_t)input[i];
98
99 if (b0 < 0x80)
100 {
101 output[out_pos++] = (char)b0;
102 i++;
103 }
104 else if (b0 >= 0xC2 && b0 <= 0xDF && i + 1 < input_len)
105 {
106 uint8_t b1 = (uint8_t)input[i + 1];
107 if ((b1 & 0xC0) == 0x80)
108 {
109 uint32_t cp = ((uint32_t)(b0 & 0x1F) << 6) | (b1 & 0x3F);
110 output[out_pos++] = (char)unicode_to_cp1252(cp);
111 i += 2;
112 }
113 else
114 {
115 output[out_pos++] = (char)b0;
116 i++;
117 }
118 }
119 else if (b0 >= 0xE0 && b0 <= 0xEF && i + 2 < input_len)
120 {
121 uint8_t b1 = (uint8_t)input[i + 1];
122 uint8_t b2 = (uint8_t)input[i + 2];
123 if ((b1 & 0xC0) == 0x80 && (b2 & 0xC0) == 0x80)
124 {
125 uint32_t cp = ((uint32_t)(b0 & 0x0F) << 12) | ((uint32_t)(b1 & 0x3F) << 6) | (b2 & 0x3F);
126 output[out_pos++] = (char)unicode_to_cp1252(cp);
127 i += 3;
128 }
129 else
130 {
131 output[out_pos++] = (char)b0;
132 i++;
133 }
134 }
135 else if (b0 >= 0xF0 && b0 <= 0xF4 && i + 3 < input_len)
136 {
137 uint8_t b1 = (uint8_t)input[i + 1];
138 uint8_t b2 = (uint8_t)input[i + 2];
139 uint8_t b3 = (uint8_t)input[i + 3];
140 if ((b1 & 0xC0) == 0x80 && (b2 & 0xC0) == 0x80 && (b3 & 0xC0) == 0x80)
141 {
142 /* Code points above U+FFFF have no Windows-1252 representation. */
143 output[out_pos++] = '?';
144 i += 4;
145 }
146 else
147 {
148 output[out_pos++] = (char)b0;
149 i++;
150 }
151 }
152 else
153 {
154 /* Continuation byte in isolation, or other non-UTF-8 byte: treat as raw CP1252. */
155 output[out_pos++] = (char)b0;
156 i++;
157 }
158 }
159
160 output[out_pos] = '\0';
161 return out_pos;
162}
163
164EoResult eo_string_to_windows_1252(const char *value, char **out_value)
165{
166 size_t in_len;
167 char *out;
168
169 if (!out_value)
170 return EO_NULL_PTR;
171
172 if (!value)
173 {
174 *out_value = NULL;
175 return EO_SUCCESS;
176 }
177
178 in_len = strlen(value);
179 out = (char *)malloc(in_len + 1);
180 if (!out)
181 return EO_ALLOC_FAILED;
182
183 normalize_to_cp1252(value, out, in_len);
184 *out_value = out;
185 return EO_SUCCESS;
186}
187
188const char *eo_result_string(EoResult result)
189{
190 switch (result)
191 {
192 case EO_SUCCESS:
193 return "EO_SUCCESS: operation completed successfully";
194 case EO_NULL_PTR:
195 return "EO_NULL_PTR: a required pointer argument was NULL";
196 case EO_OVERFLOW:
197 return "EO_OVERFLOW: internal size calculation would overflow";
198 case EO_ALLOC_FAILED:
199 return "EO_ALLOC_FAILED: memory allocation failed";
201 return "EO_NUMBER_TOO_LARGE: numeric value exceeds EO encoding range";
203 return "EO_BUFFER_UNDERRUN: not enough bytes available for read";
205 return "EO_CHUNKED_MODE_DISABLED: chunked reading mode is not active";
207 return "EO_INVALID_SEQUENCE_RANGE: calculated sequence range is empty";
209 return "EO_SEQUENCE_OUT_OF_RANGE: sequence value out of encodable range";
210 case EO_INVALID_DATA:
211 return "EO_INVALID_DATA: data is structurally invalid";
213 return "EO_STR_OUT_OF_RANGE: string exceeds the allowed fixed length";
214 case EO_STR_TOO_SHORT:
215 return "EO_STR_TOO_SHORT: string is shorter than the required fixed length";
216 case EO_INVALID_CHAR:
217 return "EO_INVALID_CHAR: character value is outside the valid range";
218 case EO_INVALID_SHORT:
219 return "EO_INVALID_SHORT: short integer value is outside the valid range";
220 case EO_INVALID_THREE:
221 return "EO_INVALID_THREE: three-byte integer value is outside the valid range";
222 case EO_INVALID_INT:
223 return "EO_INVALID_INT: integer value is outside the valid range";
224 default:
225 return "unknown EoResult value";
226 }
227}
228
230{
232}
233
235{
236 EoWriter writer;
237 writer.string_sanitization_mode = false;
238 writer.length = 0;
239 writer.capacity = capacity;
240 writer.data = capacity > 0 ? (uint8_t *)malloc(capacity) : NULL;
241 return writer;
242}
243
245{
246 if (!writer)
247 {
248 return;
249 }
250 free(writer->data);
251 writer->data = NULL;
252 writer->length = 0;
253 writer->capacity = 0;
254}
255
256EoResult eo_writer_ensure_capacity(EoWriter *writer, size_t additional)
257{
258 size_t required;
259 size_t new_capacity;
260 uint8_t *new_data;
261
262 if (!writer)
263 {
264 return EO_NULL_PTR;
265 }
266
267 if (SIZE_MAX - writer->length < additional)
268 {
269 return EO_OVERFLOW;
270 }
271
272 required = writer->length + additional;
273 if (writer->capacity >= required)
274 {
275 return EO_SUCCESS;
276 }
277
278 new_capacity = required == 0 ? 1 : required;
279 new_data = (uint8_t *)realloc(writer->data, new_capacity);
280 if (!new_data)
281 {
282 return EO_ALLOC_FAILED;
283 }
284
285 writer->data = new_data;
286 writer->capacity = new_capacity;
287 return EO_SUCCESS;
288}
289
291{
292 uint32_t value;
293 uint32_t original;
294
295 if (!out_bytes)
296 {
297 return EO_NULL_PTR;
298 }
299
300 out_bytes[0] = EO_NUMBER_PADDING;
301 out_bytes[1] = EO_NUMBER_PADDING;
302 out_bytes[2] = EO_NUMBER_PADDING;
303 out_bytes[3] = EO_NUMBER_PADDING;
304
305 value = (uint32_t)number;
306 original = value;
307 if (original >= (uint32_t)EO_INT_MAX)
308 {
309 return EO_NUMBER_TOO_LARGE;
310 }
311
312 if (original >= (uint32_t)EO_THREE_MAX)
313 {
314 out_bytes[3] = (uint8_t)(value / (uint32_t)EO_THREE_MAX) + 1;
315 value %= (uint32_t)EO_THREE_MAX;
316 }
317
318 if (original >= (uint32_t)EO_SHORT_MAX)
319 {
320 out_bytes[2] = (uint8_t)(value / (uint32_t)EO_SHORT_MAX) + 1;
321 value %= (uint32_t)EO_SHORT_MAX;
322 }
323
324 if (original >= (uint32_t)EO_CHAR_MAX)
325 {
326 out_bytes[1] = (uint8_t)(value / (uint32_t)EO_CHAR_MAX) + 1;
327 value %= (uint32_t)EO_CHAR_MAX;
328 }
329
330 out_bytes[0] = (uint8_t)value + 1;
331 return EO_SUCCESS;
332}
333
334int32_t eo_decode_number(const uint8_t *bytes, size_t length)
335{
337 size_t i;
338 uint32_t result;
339
340 for (i = 0; i < 4; ++i)
341 {
342 if (bytes && length > i && bytes[i] != 0)
343 {
344 data[i] = bytes[i];
345 }
346
347 if (data[i] == EO_NUMBER_PADDING)
348 {
349 data[i] = 1;
350 }
351
352 data[i] -= 1;
353 }
354
355 result = (uint32_t)data[3] * (uint32_t)EO_THREE_MAX;
356 result += (uint32_t)data[2] * (uint32_t)EO_SHORT_MAX;
357 result += (uint32_t)data[1] * (uint32_t)EO_CHAR_MAX;
358 result += data[0];
359 return (int32_t)result;
360}
361
362void eo_decode_string(uint8_t *buf, size_t length)
363{
364 size_t i;
365 size_t parity;
366
367 if (!buf || length == 0)
368 {
369 return;
370 }
371
372 for (i = 0; i < length / 2; ++i)
373 {
374 uint8_t tmp = buf[i];
375 buf[i] = buf[length - 1 - i];
376 buf[length - 1 - i] = tmp;
377 }
378
379 parity = (length + 1) % 2;
380 for (i = 0; i < length; ++i)
381 {
382 uint8_t ch = buf[i];
383 int odd = ((i % 2) != parity);
384
385 if (odd && ch >= 34 && ch <= 125)
386 {
387 buf[i] = (uint8_t)(125 - ch + 34);
388 }
389 else if (!odd && ch >= 34 && ch <= 79)
390 {
391 buf[i] = (uint8_t)(79 - ch + 34);
392 }
393 else if (!odd && ch >= 80 && ch <= 125)
394 {
395 buf[i] = (uint8_t)(125 - ch + 80);
396 }
397 }
398}
399
400void eo_encode_string(uint8_t *buf, size_t length)
401{
402 size_t parity;
403 size_t i;
404
405 if (!buf || length == 0)
406 {
407 return;
408 }
409
410 parity = (length + 1) % 2;
411 for (i = 0; i < length; ++i)
412 {
413 uint8_t ch = buf[i];
414 int odd = ((i % 2) != parity);
415
416 if (odd && ch >= 34 && ch <= 125)
417 {
418 buf[i] = (uint8_t)(125 - ch + 34);
419 }
420 else if (!odd && ch >= 34 && ch <= 79)
421 {
422 buf[i] = (uint8_t)(79 - ch + 34);
423 }
424 else if (!odd && ch >= 80 && ch <= 125)
425 {
426 buf[i] = (uint8_t)(125 - ch + 80);
427 }
428 }
429
430 for (i = 0; i < length / 2; ++i)
431 {
432 uint8_t tmp = buf[i];
433 buf[i] = buf[length - 1 - i];
434 buf[length - 1 - i] = tmp;
435 }
436}
437
439{
440 return writer ? writer->string_sanitization_mode : false;
441}
442
444{
445 if (writer)
446 {
447 writer->string_sanitization_mode = enabled;
448 }
449}
450
452{
453 EoResult result;
454
455 if (!writer)
456 {
457 return EO_NULL_PTR;
458 }
459
460 if ((result = eo_writer_ensure_capacity(writer, 1)) != EO_SUCCESS)
461 {
462 return result;
463 }
464
465 writer->data[writer->length++] = value;
466 return EO_SUCCESS;
467}
468
470{
471 EoResult result;
472 uint8_t bytes[4];
473
474 if (!writer)
475 {
476 return EO_NULL_PTR;
477 }
478
479 if (value < 0 || value > EO_CHAR_MAX)
480 {
481 return EO_INVALID_CHAR;
482 }
483
484 if ((result = eo_writer_ensure_capacity(writer, 1)) != EO_SUCCESS)
485 {
486 return result;
487 }
488
489 if ((result = eo_encode_number(value, bytes)) != EO_SUCCESS)
490 {
491 return result;
492 }
493
494 writer->data[writer->length++] = bytes[0];
495
496 return EO_SUCCESS;
497}
498
500{
501 EoResult result;
502 uint8_t bytes[4];
503
504 if (!writer)
505 {
506 return EO_NULL_PTR;
507 }
508
509 if (value < 0 || value > EO_SHORT_MAX)
510 {
511 return EO_INVALID_SHORT;
512 }
513
514 if ((result = eo_writer_ensure_capacity(writer, 2)) != EO_SUCCESS)
515 {
516 return result;
517 }
518
519 if ((result = eo_encode_number(value, bytes)) != EO_SUCCESS)
520 {
521 return result;
522 }
523
524 writer->data[writer->length++] = bytes[0];
525 writer->data[writer->length++] = bytes[1];
526
527 return EO_SUCCESS;
528}
529
531{
532 EoResult result;
533 uint8_t bytes[4];
534
535 if (!writer)
536 {
537 return EO_NULL_PTR;
538 }
539
540 if (value < 0 || value > EO_THREE_MAX)
541 {
542 return EO_INVALID_THREE;
543 }
544
545 if ((result = eo_writer_ensure_capacity(writer, 3)) != EO_SUCCESS)
546 {
547 return result;
548 }
549
550 if ((result = eo_encode_number(value, bytes)) != EO_SUCCESS)
551 {
552 return result;
553 }
554
555 writer->data[writer->length++] = bytes[0];
556 writer->data[writer->length++] = bytes[1];
557 writer->data[writer->length++] = bytes[2];
558 return EO_SUCCESS;
559}
560
562{
563 EoResult result;
564 uint8_t bytes[4];
565
566 if (!writer)
567 {
568 return EO_NULL_PTR;
569 }
570
571 if (value < 0 && (uint32_t)value >= (uint32_t)EO_INT_MAX)
572 {
573 return EO_INVALID_INT;
574 }
575
576 if ((result = eo_writer_ensure_capacity(writer, 4)) != EO_SUCCESS)
577 {
578 return result;
579 }
580
581 if ((result = eo_encode_number(value, bytes)) != EO_SUCCESS)
582 {
583 return result;
584 }
585
586 writer->data[writer->length++] = bytes[0];
587 writer->data[writer->length++] = bytes[1];
588 writer->data[writer->length++] = bytes[2];
589 writer->data[writer->length++] = bytes[3];
590
591 return EO_SUCCESS;
592}
593
594EoResult eo_writer_add_string(EoWriter *writer, const char *value)
595{
596 size_t in_len;
597 char *normalized;
598 size_t length;
599 EoResult result;
600
601 if (!writer)
602 {
603 return EO_NULL_PTR;
604 }
605
606 /* Ignore NULL strings, treat them as empty strings */
607 if (!value)
608 {
609 return EO_SUCCESS;
610 }
611
612 in_len = strlen(value);
613 normalized = (char *)malloc(in_len + 1);
614 if (!normalized)
615 {
616 return EO_ALLOC_FAILED;
617 }
618 length = normalize_to_cp1252(value, normalized, in_len);
619
620 if ((result = eo_writer_ensure_capacity(writer, length)) != EO_SUCCESS)
621 {
622 free(normalized);
623 return result;
624 }
625
626 if (writer->string_sanitization_mode)
627 {
628 size_t k;
629
630 for (k = 0; k < length; ++k)
631 {
632 writer->data[writer->length++] =
633 (normalized[k] == (char)EO_BREAK_BYTE) ? 0x79 : (uint8_t)normalized[k];
634 }
635 }
636 else
637 {
638 memcpy(writer->data + writer->length, normalized, length);
639 writer->length += length;
640 }
641
642 free(normalized);
643 return EO_SUCCESS;
644}
645
647{
648 size_t in_len;
649 char *normalized;
650 size_t length;
651 EoResult result;
652 uint8_t *encoded;
653
654 if (!writer)
655 {
656 return EO_NULL_PTR;
657 }
658
659 /* Ignore NULL strings, treat them as empty strings */
660 if (!value)
661 {
662 return EO_SUCCESS;
663 }
664
665 in_len = strlen(value);
666 normalized = (char *)malloc(in_len + 1);
667 if (!normalized)
668 {
669 return EO_ALLOC_FAILED;
670 }
671 length = normalize_to_cp1252(value, normalized, in_len);
672
673 if ((result = eo_writer_ensure_capacity(writer, length)) != EO_SUCCESS)
674 {
675 free(normalized);
676 return result;
677 }
678
679 encoded = (uint8_t *)malloc(length);
680 if (!encoded)
681 {
682 free(normalized);
683 return EO_ALLOC_FAILED;
684 }
685
686 if (writer->string_sanitization_mode)
687 {
688 size_t k;
689
690 for (k = 0; k < length; ++k)
691 {
692 encoded[k] = (normalized[k] == (char)EO_BREAK_BYTE) ? 0x79 : (uint8_t)normalized[k];
693 }
694 }
695 else
696 {
697 memcpy(encoded, normalized, length);
698 }
699
700 free(normalized);
701
702 eo_encode_string(encoded, length);
703 memcpy(writer->data + writer->length, encoded, length);
704 writer->length += length;
705
706 free(encoded);
707
708 return EO_SUCCESS;
709}
710
711EoResult eo_writer_add_fixed_string(EoWriter *writer, const char *value, size_t length, bool padded)
712{
713 size_t in_len;
714 char *normalized;
715 size_t value_len;
716 EoResult result;
717
718 if (!writer)
719 {
720 return EO_NULL_PTR;
721 }
722
723 /* Ignore NULL strings, treat them as empty strings */
724 if (!value)
725 {
726 return EO_SUCCESS;
727 }
728
729 in_len = strlen(value);
730 normalized = (char *)malloc(in_len + 1);
731 if (!normalized)
732 {
733 return EO_ALLOC_FAILED;
734 }
735 value_len = normalize_to_cp1252(value, normalized, in_len);
736
737 if (padded && value_len > length)
738 {
739 free(normalized);
740 return EO_STR_OUT_OF_RANGE;
741 }
742
743 if (!padded && value_len != length)
744 {
745 free(normalized);
746 return EO_STR_TOO_SHORT;
747 }
748
749 if ((result = eo_writer_ensure_capacity(writer, length)) != EO_SUCCESS)
750 {
751 free(normalized);
752 return result;
753 }
754
755 if (writer->string_sanitization_mode)
756 {
757 size_t k;
758
759 for (k = 0; k < value_len; ++k)
760 {
761 writer->data[writer->length++] =
762 (normalized[k] == (char)EO_BREAK_BYTE) ? 0x79 : (uint8_t)normalized[k];
763 }
764 }
765 else
766 {
767 size_t to_copy = padded ? value_len : length;
768 memcpy(writer->data + writer->length, normalized, to_copy);
769 writer->length += to_copy;
770 }
771
772 free(normalized);
773
774 if (padded)
775 {
776 size_t remaining;
777 size_t i;
778
779 remaining = length > value_len ? length - value_len : 0;
780 for (i = 0; i < remaining; ++i)
781 {
782 writer->data[writer->length++] = EO_BREAK_BYTE;
783 }
784 }
785
786 return EO_SUCCESS;
787}
788
789EoResult eo_writer_add_fixed_encoded_string(EoWriter *writer, const char *value, size_t length, bool padded)
790{
791 size_t in_len;
792 char *normalized;
793 size_t value_len;
794 EoResult result;
795 uint8_t *encoded;
796
797 if (!writer)
798 {
799 return EO_NULL_PTR;
800 }
801
802 /* Ignore NULL strings, treat them as empty strings */
803 if (!value)
804 {
805 return EO_SUCCESS;
806 }
807
808 in_len = strlen(value);
809 normalized = (char *)malloc(in_len + 1);
810 if (!normalized)
811 {
812 return EO_ALLOC_FAILED;
813 }
814 value_len = normalize_to_cp1252(value, normalized, in_len);
815
816 if (padded && value_len > length)
817 {
818 free(normalized);
819 return EO_STR_OUT_OF_RANGE;
820 }
821
822 if (!padded && value_len != length)
823 {
824 free(normalized);
825 return EO_STR_TOO_SHORT;
826 }
827
828 if ((result = eo_writer_ensure_capacity(writer, length)) != EO_SUCCESS)
829 {
830 free(normalized);
831 return result;
832 }
833
834 encoded = (uint8_t *)malloc(length);
835 if (!encoded)
836 {
837 free(normalized);
838 return EO_ALLOC_FAILED;
839 }
840
841 if (writer->string_sanitization_mode)
842 {
843 size_t k;
844
845 for (k = 0; k < value_len; ++k)
846 {
847 encoded[k] = (normalized[k] == (char)EO_BREAK_BYTE) ? 0x79 : (uint8_t)normalized[k];
848 }
849 }
850 else
851 {
852 size_t to_copy = padded ? value_len : length;
853 memcpy(encoded, normalized, to_copy);
854 }
855
856 free(normalized);
857
858 if (padded)
859 {
860 size_t remaining;
861 size_t i;
862
863 remaining = length > value_len ? length - value_len : 0;
864 for (i = 0; i < remaining; ++i)
865 {
866 encoded[value_len + i] = EO_BREAK_BYTE;
867 }
868 }
869
870 eo_encode_string(encoded, length);
871
872 memcpy(writer->data + writer->length, encoded, length);
873 writer->length += length;
874
875 free(encoded);
876
877 return EO_SUCCESS;
878}
879
880EoResult eo_writer_add_bytes(EoWriter *writer, const uint8_t *data, size_t length)
881{
882 EoResult result;
883
884 if (!writer || !data)
885 {
886 return EO_NULL_PTR;
887 }
888
889 if ((result = eo_writer_ensure_capacity(writer, length)) != EO_SUCCESS)
890 {
891 return result;
892 }
893
894 memcpy(writer->data + writer->length, data, length);
895 writer->length += length;
896
897 return EO_SUCCESS;
898}
899
900EoReader eo_reader_init(const uint8_t *data, size_t length)
901{
902 EoReader reader;
903 reader.data = data;
904 reader.length = length;
905 reader.offset = 0;
906 reader.chunked_reading_mode = false;
907 reader.chunk_offset = 0;
908 reader.next_chunk_offset = 0;
909 return reader;
910}
911
913{
914 return reader ? reader->chunked_reading_mode : false;
915}
916
918{
919 if (reader && !reader->chunked_reading_mode)
920 {
921 reader->chunked_reading_mode = true;
923 }
924}
925
926size_t eo_reader_remaining(const EoReader *reader)
927{
928 if (!reader)
929 {
930 return 0;
931 }
932
933 if (reader->offset >= reader->length)
934 {
935 return 0;
936 }
937
938 if (reader->chunked_reading_mode)
939 {
940 size_t next_break = reader->next_chunk_offset;
941 if (next_break < reader->offset)
942 {
943 return 0;
944 }
945
946 return next_break - reader->offset;
947 }
948
949 return reader->length - reader->offset;
950}
951
953{
954 if (!reader)
955 {
956 return EO_NULL_PTR;
957 }
958
959 if (!reader->chunked_reading_mode)
960 {
962 }
963
964 reader->offset = reader->next_chunk_offset;
965 if (reader->offset < reader->length)
966 {
967 reader->offset += 1; /* Skip the EO_BREAK_BYTE break byte */
968 }
969
970 reader->chunk_offset = reader->offset;
972
973 return EO_SUCCESS;
974}
975
976static size_t eo_reader_next_break_index(const EoReader *reader)
977{
978 size_t i;
979
980 if (!reader || !reader->chunked_reading_mode)
981 {
982 return reader ? reader->length : 0;
983 }
984
985 for (i = reader->chunk_offset; i < reader->length; ++i)
986 {
987 if (reader->data[i] == (uint8_t)EO_BREAK_BYTE)
988 {
989 return i;
990 }
991 }
992
993 return reader->length;
994}
995
997{
998 uint8_t value;
999
1000 if (!reader || !out_value)
1001 {
1002 return EO_NULL_PTR;
1003 }
1004
1005 if (reader->offset > reader->length || reader->length - reader->offset < 1)
1006 {
1007 if (reader->chunked_reading_mode)
1008 {
1009 *out_value = 0;
1010 return EO_SUCCESS;
1011 }
1012
1013 return EO_BUFFER_UNDERRUN;
1014 }
1015
1016 value = reader->data[reader->offset++];
1017 if (out_value)
1018 {
1019 *out_value = value;
1020 }
1021
1022 return EO_SUCCESS;
1023}
1024
1026{
1027 uint8_t bytes[1];
1028
1029 if (!reader || !out_value)
1030 {
1031 return EO_NULL_PTR;
1032 }
1033
1034 if (reader->offset > reader->length || reader->length - reader->offset < 1)
1035 {
1036 if (reader->chunked_reading_mode)
1037 {
1038 *out_value = 0;
1039 return EO_SUCCESS;
1040 }
1041
1042 return EO_BUFFER_UNDERRUN;
1043 }
1044
1045 bytes[0] = reader->data[reader->offset++];
1046 if (out_value)
1047 {
1048 *out_value = eo_decode_number(bytes, 1);
1049 }
1050
1051 return EO_SUCCESS;
1052}
1053
1055{
1056 uint8_t bytes[2];
1057
1058 if (!reader || !out_value)
1059 {
1060 return EO_NULL_PTR;
1061 }
1062
1063 if (reader->offset > reader->length || reader->length - reader->offset < 2)
1064 {
1065 if (reader->chunked_reading_mode)
1066 {
1067 *out_value = 0;
1068 return EO_SUCCESS;
1069 }
1070
1071 return EO_BUFFER_UNDERRUN;
1072 }
1073
1074 bytes[0] = reader->data[reader->offset++];
1075 bytes[1] = reader->data[reader->offset++];
1076 if (out_value)
1077 {
1078 *out_value = eo_decode_number(bytes, 2);
1079 }
1080
1081 return EO_SUCCESS;
1082}
1083
1085{
1086 uint8_t bytes[3];
1087
1088 if (!reader || !out_value)
1089 {
1090 return EO_NULL_PTR;
1091 }
1092
1093 if (reader->offset > reader->length || reader->length - reader->offset < 3)
1094 {
1095 if (reader->chunked_reading_mode)
1096 {
1097 *out_value = 0;
1098 return EO_SUCCESS;
1099 }
1100
1101 return EO_BUFFER_UNDERRUN;
1102 }
1103
1104 bytes[0] = reader->data[reader->offset++];
1105 bytes[1] = reader->data[reader->offset++];
1106 bytes[2] = reader->data[reader->offset++];
1107 if (out_value)
1108 {
1109 *out_value = eo_decode_number(bytes, 3);
1110 }
1111
1112 return EO_SUCCESS;
1113}
1114
1116{
1117 uint8_t bytes[4];
1118
1119 if (!reader || !out_value)
1120 {
1121 return EO_NULL_PTR;
1122 }
1123
1124 if (reader->offset > reader->length || reader->length - reader->offset < 4)
1125 {
1126 if (reader->chunked_reading_mode)
1127 {
1128 *out_value = 0;
1129 return EO_SUCCESS;
1130 }
1131
1132 return EO_BUFFER_UNDERRUN;
1133 }
1134
1135 bytes[0] = reader->data[reader->offset++];
1136 bytes[1] = reader->data[reader->offset++];
1137 bytes[2] = reader->data[reader->offset++];
1138 bytes[3] = reader->data[reader->offset++];
1139 if (out_value)
1140 {
1141 *out_value = eo_decode_number(bytes, 4);
1142 }
1143
1144 return EO_SUCCESS;
1145}
1146
1147EoResult eo_reader_get_string(EoReader *reader, char **out_value)
1148{
1149 size_t length;
1150
1151 if (!reader || !out_value)
1152 {
1153 return EO_NULL_PTR;
1154 }
1155
1156 length = eo_reader_remaining(reader);
1157 if (length == 0)
1158 {
1159 *out_value = eo_empty_string();
1160 return EO_SUCCESS;
1161 }
1162
1163 return eo_reader_get_fixed_string(reader, length, out_value);
1164}
1165
1167{
1168 size_t length;
1169
1170 if (!reader || !out_value)
1171 {
1172 return EO_NULL_PTR;
1173 }
1174
1175 length = eo_reader_remaining(reader);
1176 if (length == 0)
1177 {
1178 *out_value = eo_empty_string();
1179 return EO_SUCCESS;
1180 }
1181
1182 return eo_reader_get_fixed_encoded_string(reader, length, out_value);
1183}
1184
1185EoResult eo_reader_get_fixed_string(EoReader *reader, size_t length, char **out_value)
1186{
1187 if (!reader || !out_value)
1188 {
1189 return EO_NULL_PTR;
1190 }
1191
1192 if (reader->offset > reader->length ||
1193 reader->length - reader->offset < length)
1194 {
1195 if (reader->chunked_reading_mode)
1196 {
1197 *out_value = eo_empty_string();
1198 return EO_SUCCESS;
1199 }
1200
1201 return EO_BUFFER_UNDERRUN;
1202 }
1203
1204 *out_value = (char *)malloc(length + 1);
1205 if (!*out_value)
1206 {
1207 return EO_ALLOC_FAILED;
1208 }
1209
1210 memcpy(*out_value, reader->data + reader->offset, length);
1211 (*out_value)[length] = '\0';
1212 reader->offset += length;
1213 return EO_SUCCESS;
1214}
1215
1216EoResult eo_reader_get_fixed_encoded_string(EoReader *reader, size_t length, char **out_value)
1217{
1218 if (!reader || !out_value)
1219 {
1220 return EO_NULL_PTR;
1221 }
1222
1223 if (reader->offset > reader->length || reader->length - reader->offset < length)
1224 {
1225 if (reader->chunked_reading_mode)
1226 {
1227 *out_value = eo_empty_string();
1228 return EO_SUCCESS;
1229 }
1230
1231 return EO_BUFFER_UNDERRUN;
1232 }
1233
1234 *out_value = (char *)malloc(length + 1);
1235 if (!*out_value)
1236 {
1237 return EO_ALLOC_FAILED;
1238 }
1239
1240 memcpy(*out_value, reader->data + reader->offset, length);
1241 eo_decode_string((uint8_t *)*out_value, length);
1242 (*out_value)[length] = '\0';
1243 reader->offset += length;
1244 return EO_SUCCESS;
1245}
1246
1247EoResult eo_reader_get_bytes(EoReader *reader, size_t length, uint8_t **out_value)
1248{
1249 if (!reader || !out_value)
1250 {
1251 return EO_NULL_PTR;
1252 }
1253
1254 if (reader->offset > reader->length || reader->length - reader->offset < length)
1255 {
1256 if (reader->chunked_reading_mode)
1257 {
1258 *out_value = NULL;
1259 return EO_SUCCESS;
1260 }
1261
1262 return EO_BUFFER_UNDERRUN;
1263 }
1264
1265 *out_value = (uint8_t *)malloc(length);
1266 if (!*out_value)
1267 {
1268 return EO_ALLOC_FAILED;
1269 }
1270
1271 memcpy(*out_value, reader->data + reader->offset, length);
1272 reader->offset += length;
1273 return EO_SUCCESS;
1274}
EoResult eo_writer_add_string(EoWriter *writer, const char *value)
Definition data.c:594
static const uint32_t cp1252_unicode_extras[32]
Definition data.c:28
EoResult eo_string_to_windows_1252(const char *value, char **out_value)
Definition data.c:164
EoResult eo_reader_get_fixed_encoded_string(EoReader *reader, size_t length, char **out_value)
Definition data.c:1216
bool eo_reader_get_chunked_reading_mode(const EoReader *reader)
Definition data.c:912
EoResult eo_reader_get_string(EoReader *reader, char **out_value)
Definition data.c:1147
void eo_reader_activate_chunked_reading(EoReader *reader)
Definition data.c:917
EoResult eo_reader_get_encoded_string(EoReader *reader, char **out_value)
Definition data.c:1166
EoResult eo_writer_add_encoded_string(EoWriter *writer, const char *value)
Definition data.c:646
EoResult eo_writer_add_fixed_string(EoWriter *writer, const char *value, size_t length, bool padded)
Definition data.c:711
EoResult eo_reader_get_int(EoReader *reader, int32_t *out_value)
Definition data.c:1115
int32_t eo_decode_number(const uint8_t *bytes, size_t length)
Definition data.c:334
EoResult eo_writer_add_byte(EoWriter *writer, uint8_t value)
Definition data.c:451
EoWriter eo_writer_init_with_capacity(size_t capacity)
Definition data.c:234
static size_t eo_reader_next_break_index(const EoReader *reader)
Definition data.c:976
EoResult eo_reader_get_short(EoReader *reader, int32_t *out_value)
Definition data.c:1054
const char * eo_result_string(EoResult result)
Definition data.c:188
EoResult eo_reader_next_chunk(EoReader *reader)
Definition data.c:952
static uint8_t unicode_to_cp1252(uint32_t codepoint)
Definition data.c:63
EoResult eo_reader_get_char(EoReader *reader, int32_t *out_value)
Definition data.c:1025
static size_t normalize_to_cp1252(const char *input, char *output, size_t input_len)
Definition data.c:90
EoResult eo_writer_add_short(EoWriter *writer, int32_t value)
Definition data.c:499
void eo_encode_string(uint8_t *buf, size_t length)
Definition data.c:400
EoResult eo_writer_add_bytes(EoWriter *writer, const uint8_t *data, size_t length)
Definition data.c:880
bool eo_writer_get_string_sanitization_mode(const EoWriter *writer)
Definition data.c:438
EoResult eo_writer_add_char(EoWriter *writer, int32_t value)
Definition data.c:469
EoResult eo_writer_ensure_capacity(EoWriter *writer, size_t additional)
Definition data.c:256
static char * eo_empty_string(void)
Definition data.c:13
EoWriter eo_writer_init(void)
Definition data.c:229
EoResult eo_reader_get_three(EoReader *reader, int32_t *out_value)
Definition data.c:1084
EoResult eo_writer_add_three(EoWriter *writer, int32_t value)
Definition data.c:530
EoResult eo_writer_add_int(EoWriter *writer, int32_t value)
Definition data.c:561
EoResult eo_writer_add_fixed_encoded_string(EoWriter *writer, const char *value, size_t length, bool padded)
Definition data.c:789
void eo_writer_free(EoWriter *writer)
Definition data.c:244
EoReader eo_reader_init(const uint8_t *data, size_t length)
Definition data.c:900
void eo_decode_string(uint8_t *buf, size_t length)
Definition data.c:362
EoResult eo_reader_get_bytes(EoReader *reader, size_t length, uint8_t **out_value)
Definition data.c:1247
void eo_writer_set_string_sanitization_mode(EoWriter *writer, bool enabled)
Definition data.c:443
size_t eo_reader_remaining(const EoReader *reader)
Definition data.c:926
EoResult eo_reader_get_fixed_string(EoReader *reader, size_t length, char **out_value)
Definition data.c:1185
EoResult eo_encode_number(int32_t number, uint8_t out_bytes[4])
Definition data.c:290
EoResult eo_reader_get_byte(EoReader *reader, uint8_t *out_value)
Definition data.c:996
#define EO_NUMBER_PADDING
Definition data.h:18
#define EO_BREAK_BYTE
Definition data.h:20
#define EO_CHAR_MAX
Definition data.h:10
#define EO_THREE_MAX
Definition data.h:14
#define EO_SHORT_MAX
Definition data.h:12
#define EO_INT_MAX
Definition data.h:16
EoResult
Definition result.h:12
@ EO_NULL_PTR
Definition result.h:22
@ EO_INVALID_INT
Definition result.h:137
@ EO_INVALID_SHORT
Definition result.h:121
@ EO_OVERFLOW
Definition result.h:30
@ EO_INVALID_CHAR
Definition result.h:113
@ EO_INVALID_THREE
Definition result.h:129
@ EO_BUFFER_UNDERRUN
Definition result.h:55
@ EO_INVALID_SEQUENCE_RANGE
Definition result.h:72
@ EO_SEQUENCE_OUT_OF_RANGE
Definition result.h:80
@ EO_INVALID_DATA
Definition result.h:89
@ EO_STR_TOO_SHORT
Definition result.h:105
@ EO_ALLOC_FAILED
Definition result.h:38
@ EO_NUMBER_TOO_LARGE
Definition result.h:47
@ EO_SUCCESS
Definition result.h:14
@ EO_CHUNKED_MODE_DISABLED
Definition result.h:63
@ EO_STR_OUT_OF_RANGE
Definition result.h:97
#define SIZE_MAX
Definition stdint.h:206
unsigned int uint32_t
Definition stdint.h:80
signed int int32_t
Definition stdint.h:77
unsigned char uint8_t
Definition stdint.h:78
size_t next_chunk_offset
Definition data.h:39
size_t offset
Definition data.h:36
size_t chunk_offset
Definition data.h:38
const uint8_t * data
Definition data.h:34
size_t length
Definition data.h:35
bool chunked_reading_mode
Definition data.h:37
bool string_sanitization_mode
Definition data.h:27
size_t length
Definition data.h:26
size_t capacity
Definition data.h:28
uint8_t * data
Definition data.h:25