Lely core libraries 2.3.4
val.c
Go to the documentation of this file.
1
24#include "co.h"
25#include <lely/co/sdo.h>
26#include <lely/co/val.h>
27#include <lely/libc/string.h>
28// This include is required for <inttypes.h> when using Newlib.
29#include <lely/libc/sys/types.h>
30#include <lely/util/cmp.h>
31#include <lely/util/diag.h>
32#include <lely/util/endian.h>
33#if !LELY_NO_STDIO
34#include <lely/util/frbuf.h>
35#include <lely/util/fwbuf.h>
36#include <lely/util/lex.h>
37#include <lely/util/print.h>
38#endif
39#include <lely/util/ustring.h>
40
41#include <assert.h>
42#if !LELY_NO_STDIO
43#include <inttypes.h>
44#endif
45#if !LELY_NO_MALLOC
46#include <stdlib.h>
47#endif
48
49#define CO_ARRAY_HDR_OFFSET \
50 ALIGN(sizeof(struct co_array_hdr), _Alignof(union co_val))
51
52static inline struct co_array_hdr *co_array_get_hdr(const void *val);
53
54static int co_array_alloc(void *val, size_t size);
55static void co_array_free(void *val);
56static void co_array_init(void *val, size_t size);
57static void co_array_fini(void *val);
58
59static size_t co_array_sizeof(const void *val);
60
61int
62co_val_init(co_unsigned16_t type, void *val)
63{
64 union co_val *u = val;
65 assert(u);
66
67#if LELY_NO_MALLOC
68 if (co_type_is_array(type)) {
69 co_array_init(val, 0);
70 return 0;
71 }
72#endif
73
74 switch (type) {
75#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
76 case CO_DEFTYPE_##a: \
77 u->c = (co_##b##_t)CO_##a##_INIT; \
78 return 0;
79#include <lely/co/def/basic.def>
80#include <lely/co/def/time.def>
81#if !LELY_NO_MALLOC
82#include <lely/co/def/array.def>
83#endif // !LELY_NO_MALLOC
84#undef LELY_CO_DEFINE_TYPE
85 default: set_errnum(ERRNUM_INVAL); return -1;
86 }
87}
88
89int
90co_val_init_min(co_unsigned16_t type, void *val)
91{
92 union co_val *u = val;
93 assert(u);
94
95#if LELY_NO_MALLOC
96 if (co_type_is_array(type)) {
97 co_array_init(val, 0);
98 return 0;
99 }
100#endif
101
102 switch (type) {
103#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
104 case CO_DEFTYPE_##a: \
105 u->c = (co_##b##_t)CO_##a##_MIN; \
106 return 0;
107#include <lely/co/def/basic.def>
108#include <lely/co/def/time.def>
109#if !LELY_NO_MALLOC
110#include <lely/co/def/array.def>
111#endif // !LELY_NO_MALLOC
112#undef LELY_CO_DEFINE_TYPE
113 default: set_errnum(ERRNUM_INVAL); return -1;
114 }
115}
116
117int
118co_val_init_max(co_unsigned16_t type, void *val)
119{
120 union co_val *u = val;
121 assert(u);
122
123#if LELY_NO_MALLOC
124 if (co_type_is_array(type)) {
125 co_array_init(val, 0);
126 return 0;
127 }
128#endif
129
130 switch (type) {
131#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
132 case CO_DEFTYPE_##a: \
133 u->c = (co_##b##_t)CO_##a##_MAX; \
134 return 0;
135#include <lely/co/def/basic.def>
136#include <lely/co/def/time.def>
137#if !LELY_NO_MALLOC
138#include <lely/co/def/array.def>
139#endif // !LELY_NO_MALLOC
140#undef LELY_CO_DEFINE_TYPE
141 default: set_errnum(ERRNUM_INVAL); return -1;
142 }
143}
144
145int
146co_val_init_vs(char **val, const char *vs)
147{
148 if (vs)
149 return co_val_init_vs_n(val, vs, strlen(vs));
150
151 co_array_fini(val);
152
153 return 0;
154}
155
156int
157co_val_init_vs_n(char **val, const char *vs, size_t n)
158{
159 assert(val);
160
161 if (n) {
162 if (co_array_alloc(val, n + 1) == -1)
163 return -1;
164 assert(*val);
165 co_array_init(val, n);
166 if (vs)
167 // Using strncpy() here might cause a compiler warning
168 // because we omit the terminating nul byte, which is
169 // already set by co_array_init().
170 memcpy(*val, vs, n);
171 } else {
172 co_array_fini(val);
173 }
174
175 return 0;
176}
177
178int
179co_val_init_os(uint_least8_t **val, const uint_least8_t *os, size_t n)
180{
181 assert(val);
182
183 if (n) {
184 if (co_array_alloc(val, n + 1) == -1)
185 return -1;
186 assert(*val);
187 co_array_init(val, n);
188 if (os)
189 memcpy(*val, os, n);
190 } else {
191 co_array_fini(val);
192 }
193
194 return 0;
195}
196
197int
198co_val_init_us(char16_t **val, const char16_t *us)
199{
200 assert(val);
201
202 if (us)
203 return co_val_init_us_n(val, us, str16len(us));
204
205 co_array_fini(val);
206
207 return 0;
208}
209
210int
211co_val_init_us_n(char16_t **val, const char16_t *us, size_t n)
212{
213 assert(val);
214
215 if (n) {
216 if (co_array_alloc(val, 2 * (n + 1)) == -1)
217 return -1;
218 assert(*val);
219 co_array_init(val, 2 * n);
220 if (us)
221 str16ncpy(*val, us, n);
222 } else {
223 co_array_fini(val);
224 }
225
226 return 0;
227}
228
229int
230co_val_init_dom(void **val, const void *dom, size_t n)
231{
232 assert(val);
233
234 if (n) {
235 if (co_array_alloc(val, n) == -1)
236 return -1;
237 assert(*val);
238 co_array_init(val, n);
239 if (dom)
240 memcpy(*val, dom, n);
241 } else {
242 co_array_fini(val);
243 }
244
245 return 0;
246}
247
248void
249co_val_fini(co_unsigned16_t type, void *val)
250{
251 assert(val);
252
253 if (co_type_is_array(type)) {
254 co_array_free(val);
255 co_array_fini(val);
256 }
257}
258
259const void *
260co_val_addressof(co_unsigned16_t type, const void *val)
261{
262 if (!val)
263 return NULL;
264
265 return co_type_is_array(type) ? *(const void **)val : val;
266}
267
268size_t
269co_val_sizeof(co_unsigned16_t type, const void *val)
270{
271 if (!val)
272 return 0;
273
274 // clang-format off
275 return co_type_is_array(type)
276 ? co_array_sizeof(val)
277 : co_type_sizeof(type);
278 // clang-format on
279}
280
281size_t
282co_val_make(co_unsigned16_t type, void *val, const void *ptr, size_t n)
283{
284 assert(val);
285
286 switch (type) {
288 n = ptr ? strlen(ptr) : 0;
289 if (co_val_init_vs(val, ptr) == -1)
290 return 0;
291 break;
293 if (!ptr)
294 n = 0;
295 if (co_val_init_os(val, ptr, n) == -1)
296 return 0;
297 break;
299 n = ptr ? str16len(ptr) : 0;
300 if (co_val_init_us(val, ptr) == -1)
301 return 0;
302 break;
304 if (!ptr)
305 n = 0;
306 if (co_val_init_dom(val, ptr, n) == -1)
307 return 0;
308 break;
309 default:
310 if (!ptr || co_type_sizeof(type) != n)
311 return 0;
312 memcpy(val, ptr, n);
313 }
314 return n;
315}
316
317size_t
318co_val_copy(co_unsigned16_t type, void *dst, const void *src)
319{
320 assert(dst);
321 assert(src);
322
323 size_t n;
324 if (co_type_is_array(type)) {
325 const void *ptr = co_val_addressof(type, src);
326 n = co_val_sizeof(type, src);
327 switch (type) { // LCOV_EXCL_BR_LINE
329 if (co_val_init_vs(dst, ptr) == -1)
330 return 0;
331 break;
333 if (co_val_init_os(dst, ptr, n) == -1)
334 return 0;
335 break;
337 if (co_val_init_us(dst, ptr) == -1)
338 return 0;
339 break;
341 if (co_val_init_dom(dst, ptr, n) == -1)
342 return 0;
343 break;
344 default: return 0; // We can never get here. [LCOV_EXCL_LINE]
345 }
346 } else {
347 n = co_type_sizeof(type);
348 memcpy(dst, src, n);
349 }
350 return n;
351}
352
353size_t
354co_val_move(co_unsigned16_t type, void *dst, void *src)
355{
356 assert(dst);
357 assert(src);
358
359 size_t n = co_type_sizeof(type);
360 memcpy(dst, src, n);
361
362 if (co_type_is_array(type))
363 *(char **)src = NULL;
364
365 return n;
366}
367
368int
369co_val_cmp(co_unsigned16_t type, const void *v1, const void *v2)
370{
371 if (v1 == v2)
372 return 0;
373
374 if (!v1)
375 return -1;
376 if (!v2)
377 return 1;
378
379 int cmp = 0;
380 if (co_type_is_array(type)) {
381 const void *p1 = co_val_addressof(type, v1);
382 const void *p2 = co_val_addressof(type, v2);
383
384 if (p1 == p2)
385 return 0;
386
387 if (!p1)
388 return -1;
389 if (!p2)
390 return 1;
391
392 size_t n1 = co_val_sizeof(type, v1);
393 size_t n2 = co_val_sizeof(type, v2);
394 switch (type) { // LCOV_EXCL_BR_LINE
396 cmp = strncmp(p1, p2, MIN(n1, n2));
397 break;
399 cmp = memcmp(p1, p2, MIN(n1, n2));
400 break;
402 cmp = str16ncmp(p1, p2, MIN(n1, n2) / 2);
403 break;
405 cmp = memcmp(p1, p2, MIN(n1, n2));
406 break;
407 default: return 0; // We can never get here. [LCOV_EXCL_LINE]
408 }
409 if (!cmp)
410 cmp = (n1 > n2) - (n1 < n2);
411 return cmp;
412 } else {
413 const union co_val *u1 = v1;
414 const union co_val *u2 = v2;
415 switch (type) {
416 case CO_DEFTYPE_BOOLEAN: return bool_cmp(v1, v2);
417 case CO_DEFTYPE_INTEGER8: return int8_cmp(v1, v2);
418 case CO_DEFTYPE_INTEGER16: return int16_cmp(v1, v2);
419 case CO_DEFTYPE_INTEGER32: return int32_cmp(v1, v2);
420 case CO_DEFTYPE_UNSIGNED8: return uint8_cmp(v1, v2);
421 case CO_DEFTYPE_UNSIGNED16: return uint16_cmp(v1, v2);
422 case CO_DEFTYPE_UNSIGNED32: return uint32_cmp(v1, v2);
423 case CO_DEFTYPE_REAL32: return flt_cmp(v1, v2);
425 cmp = uint16_cmp(&u1->t.days, &u2->t.days);
426 if (!cmp)
427 cmp = uint32_cmp(&u1->t.ms, &u2->t.ms);
428 return cmp;
430 cmp = uint16_cmp(&u1->td.days, &u2->td.days);
431 if (!cmp)
432 cmp = uint32_cmp(&u1->td.ms, &u2->td.ms);
433 return cmp;
434 case CO_DEFTYPE_INTEGER24: return int32_cmp(v1, v2);
435 case CO_DEFTYPE_REAL64: return dbl_cmp(v1, v2);
436 case CO_DEFTYPE_INTEGER40: return int64_cmp(v1, v2);
437 case CO_DEFTYPE_INTEGER48: return int64_cmp(v1, v2);
438 case CO_DEFTYPE_INTEGER56: return int64_cmp(v1, v2);
439 case CO_DEFTYPE_INTEGER64: return int64_cmp(v1, v2);
440 case CO_DEFTYPE_UNSIGNED24: return uint32_cmp(v1, v2);
441 case CO_DEFTYPE_UNSIGNED40: return uint64_cmp(v1, v2);
442 case CO_DEFTYPE_UNSIGNED48: return uint64_cmp(v1, v2);
443 case CO_DEFTYPE_UNSIGNED56: return uint64_cmp(v1, v2);
444 case CO_DEFTYPE_UNSIGNED64: return uint64_cmp(v1, v2);
445 default: return 0;
446 }
447 }
448}
449
450size_t
451co_val_read(co_unsigned16_t type, void *val, const uint_least8_t *begin,
452 const uint_least8_t *end)
453{
454 assert(begin || begin == end);
455 assert(end >= begin);
456
457 size_t n = end - begin;
458
459 if (co_type_is_array(type)) {
460 if (val) {
461 switch (type) { // LCOV_EXCL_BR_LINE
463 // clang-format off
464 if (co_val_init_vs_n(val, (const char *)begin,
465 n) == -1)
466 // clang-format on
467 return 0;
468 break;
470 if (co_val_init_os(val, begin, n) == -1)
471 return 0;
472 break;
474 if (co_val_init_us_n(val, NULL, n / 2) == -1)
475 return 0;
476 if (n) {
477 char16_t *us = *(char16_t **)val;
478 assert(us);
479 for (size_t i = 0; i + 1 < n; i += 2)
480 us[i / 2] = ldle_u16(begin + i);
481 }
482 break;
484 if (co_val_init_dom(val, begin, n) == -1)
485 return 0;
486 break;
487 // We can never get here
488 default: return 0; // LCOV_EXCL_LINE
489 }
490 }
491 return n;
492 } else {
493 union co_val *u = val;
494 switch (type) {
496 if (n < 1)
497 return 0;
498 if (u)
499 u->b = (*begin != 0);
500 return 1;
502 if (n < 1)
503 return 0;
504 if (u)
505 u->i8 = *(const co_integer8_t *)begin;
506 return 1;
508 if (n < 2)
509 return 0;
510 if (u)
511 u->i16 = ldle_i16(begin);
512 return 2;
514 if (n < 4)
515 return 0;
516 if (u)
517 u->i32 = ldle_i32(begin);
518 return 4;
520 if (n < 1)
521 return 0;
522 if (u)
523 u->u8 = *(const co_unsigned8_t *)begin;
524 return 1;
526 if (n < 2)
527 return 0;
528 if (u)
529 u->u16 = ldle_u16(begin);
530 return 2;
532 if (n < 4)
533 return 0;
534 if (u)
535 u->u32 = ldle_u32(begin);
536 return 4;
538 if (n < 4)
539 return 0;
540 if (u)
541 u->r32 = ldle_flt32(begin);
542 return 4;
545 if (n < 6)
546 return 0;
547 if (u) {
548 u->t.ms = ldle_u32(begin)
549 & UINT32_C(0x0fffffff);
550 u->t.days = ldle_u16(begin + 4);
551 }
552 return 6;
554 if (n < 3)
555 return 0;
556 if (u) {
557 co_unsigned24_t u24 = 0;
558 for (size_t i = 0; i < 3; i++)
559 u24 |= (co_unsigned24_t)*begin++
560 << 8 * i;
561 u->i24 = u24 > CO_INTEGER24_MAX
562 ? -(CO_UNSIGNED24_MAX + 1 - u24)
563 : u24;
564 }
565 return 3;
567 if (n < 8)
568 return 0;
569 if (u)
570 u->r64 = ldle_flt64(begin);
571 return 8;
573 if (n < 5)
574 return 0;
575 if (u) {
576 co_unsigned40_t u40 = 0;
577 for (size_t i = 0; i < 5; i++)
578 u40 |= (co_unsigned40_t)*begin++
579 << 8 * i;
580 u->i40 = u40 > CO_INTEGER40_MAX
581 ? -(CO_UNSIGNED40_MAX + 1 - u40)
582 : u40;
583 }
584 return 5;
586 if (n < 6)
587 return 0;
588 if (u) {
589 co_unsigned48_t u48 = 0;
590 for (size_t i = 0; i < 6; i++)
591 u48 |= (co_unsigned48_t)*begin++
592 << 8 * i;
593 u->i48 = u48 > CO_INTEGER48_MAX
594 ? -(CO_UNSIGNED48_MAX + 1 - u48)
595 : u48;
596 }
597 return 6;
599 if (n < 7)
600 return 0;
601 if (u) {
602 co_unsigned56_t u56 = 0;
603 for (size_t i = 0; i < 7; i++)
604 u56 |= (co_unsigned56_t)*begin++
605 << 8 * i;
606 u->i56 = u56 > CO_INTEGER56_MAX
607 ? -(CO_UNSIGNED56_MAX + 1 - u56)
608 : u56;
609 }
610 return 7;
612 if (n < 8)
613 return 0;
614 if (u)
615 u->i64 = ldle_i64(begin);
616 return 8;
618 if (n < 3)
619 return 0;
620 if (u) {
621 u->u24 = 0;
622 for (size_t i = 0; i < 3; i++)
623 u->u24 |= (co_unsigned24_t)*begin++
624 << 8 * i;
625 }
626 return 3;
628 if (n < 5)
629 return 0;
630 if (u) {
631 u->u40 = 0;
632 for (size_t i = 0; i < 5; i++)
633 u->u40 |= (co_unsigned40_t)*begin++
634 << 8 * i;
635 }
636 return 5;
638 if (n < 6)
639 return 0;
640 if (u) {
641 u->u48 = 0;
642 for (size_t i = 0; i < 6; i++)
643 u->u48 |= (co_unsigned48_t)*begin++
644 << 8 * i;
645 }
646 return 6;
648 if (n < 7)
649 return 0;
650 if (u) {
651 u->u56 = 0;
652 for (size_t i = 0; i < 7; i++)
653 u->u56 |= (co_unsigned56_t)*begin++
654 << 8 * i;
655 }
656 return 7;
658 if (n < 8)
659 return 0;
660 if (u)
661 u->u64 = ldle_u64(begin);
662 return 8;
663 default: set_errnum(ERRNUM_INVAL); return 0;
664 }
665 }
666}
667
668#if !LELY_NO_STDIO
669
670size_t
671co_val_read_file(co_unsigned16_t type, void *val, const char *filename)
672{
673 frbuf_t *buf = frbuf_create(filename);
674 if (buf) {
675 int errc = get_errc();
676 set_errc(0);
677 size_t size = co_val_read_frbuf(type, val, buf);
678 if (!size && get_errc()) {
679 errc = get_errc();
680 diag(DIAG_ERROR, get_errc(), "%s", filename);
681 }
682 frbuf_destroy(buf);
683 set_errc(errc);
684 return size;
685 } else {
686 diag(DIAG_ERROR, get_errc(), "%s", filename);
687 return 0;
688 }
689}
690
691size_t
692co_val_read_frbuf(co_unsigned16_t type, void *val, frbuf_t *buf)
693{
694 intmax_t size = frbuf_get_size(buf);
695 if (size == -1)
696 return 0;
697 assert(size >= 0);
698
699 intmax_t pos = frbuf_get_pos(buf);
700 if (pos == -1)
701 return 0;
702 assert(pos >= 0);
703
704 if (pos > size)
705 pos = size;
706 size -= pos;
707
708 if (co_type_is_array(type)) {
709 size_t n = (size_t)size;
710 if (val) {
711 switch (type) {
713 if (co_val_init_vs_n(val, NULL, n) == -1)
714 return 0;
715 char *vs = *(char **)val;
716 if (frbuf_read(buf, vs, n) != (ssize_t)n)
717 return 0;
718 break;
720 if (co_val_init_os(val, NULL, n) == -1)
721 return 0;
722 uint_least8_t *os = *(uint_least8_t **)val;
723 if (frbuf_read(buf, os, n) != (ssize_t)n)
724 return 0;
725 break;
727 if (co_val_init_us_n(val, NULL, n / 2) == -1)
728 return 0;
729 char16_t *us = *(char16_t **)val;
730 if (frbuf_read(buf, us, n) != (ssize_t)n)
731 return 0;
732 // Update the byte order in-place.
733 const uint_least8_t *begin =
734 (const uint_least8_t *)us;
735 assert(us);
736 for (size_t i = 0; i + 1 < n; i += 2)
737 us[i / 2] = ldle_u16(begin + i);
738 break;
740 if (co_val_init_dom(val, NULL, n) == -1)
741 return 0;
742 void *dom = *(void **)val;
743 if (frbuf_read(buf, dom, n) != (ssize_t)n)
744 return 0;
745 break;
746 // We can never get here
747 default: return 0;
748 }
749 }
750 return n;
751 } else {
752 size_t n = co_type_sizeof(type);
753 n = MIN(n, (size_t)size);
754 union co_val tmp;
755 assert(n <= sizeof(tmp));
756 if (frbuf_read(buf, &tmp, n) != (ssize_t)n)
757 return 0;
758 const uint_least8_t *begin = (const uint_least8_t *)&tmp;
759 const uint_least8_t *end = begin + n;
760 return co_val_read(type, val, begin, end);
761 }
762}
763
764#endif // !LELY_NO_STDIO
765
766co_unsigned32_t
767co_val_read_sdo(co_unsigned16_t type, void *val, const void *ptr, size_t n)
768{
769 int errc = get_errc();
770 co_unsigned32_t ac = 0;
771
772 const uint_least8_t *begin = ptr;
773 const uint_least8_t *end = begin ? begin + n : NULL;
774 if (n && !co_val_read(type, val, begin, end)) {
775#if LELY_NO_ERRNO
776 ac = CO_SDO_AC_ERROR;
777#else
778 // clang-format off
779 ac = get_errnum() == ERRNUM_NOMEM
782 // clang-format on
783#endif
784 set_errc(errc);
785 }
786
787 return ac;
788}
789
790size_t
791co_val_write(co_unsigned16_t type, const void *val, uint_least8_t *begin,
792 uint_least8_t *end)
793{
794 assert(val);
795
796 if (co_type_is_array(type)) {
797 const void *ptr = co_val_addressof(type, val);
798 size_t n = co_val_sizeof(type, val);
799 if (!ptr || !n)
800 return 0;
801 if (begin && (!end || end - begin >= (ptrdiff_t)n)) {
802 switch (type) { // LCOV_EXCL_BR_LINE
805 case CO_DEFTYPE_DOMAIN: memcpy(begin, ptr, n); break;
807 const char16_t *us = ptr;
808 for (size_t i = 0; i + 1 < n; i += 2)
809 stle_u16(begin + i, us[i / 2]);
810 break;
811 }
812 // We can never get here.
813 default: return 0; // LCOV_EXCL_LINE
814 }
815 }
816 return n;
817 } else {
818 const union co_val *u = val;
819 switch (type) {
821 if (begin && (!end || end - begin >= 1)) {
822 if (u->b != 0)
823 *(co_boolean_t *)begin = 1;
824 else
825 *(co_boolean_t *)begin = 0;
826 }
827 return 1;
829 if (begin && (!end || end - begin >= 1))
830 *(co_integer8_t *)begin = u->i8;
831 return 1;
833 if (begin && (!end || end - begin >= 2))
834 stle_i16(begin, u->i16);
835 return 2;
837 if (begin && (!end || end - begin >= 4))
838 stle_i32(begin, u->i32);
839 return 4;
841 if (begin && (!end || end - begin >= 1))
842 *(co_unsigned8_t *)begin = u->u8;
843 return 1;
845 if (begin && (!end || end - begin >= 2))
846 stle_u16(begin, u->u16);
847 return 2;
849 if (begin && (!end || end - begin >= 4))
850 stle_u32(begin, u->u32);
851 return 4;
853 if (begin && (!end || end - begin >= 4))
854 stle_flt32(begin, u->r32);
855 return 4;
858 if (begin && (!end || end - begin >= 6)) {
859 stle_u32(begin, u->t.ms & UINT32_C(0x0fffffff));
860 stle_u16(begin + 4, u->t.days);
861 }
862 return 6;
864 if (begin && (!end || end - begin >= 3)) {
865 co_unsigned24_t u24 = u->i24 < 0
866 ? CO_UNSIGNED24_MAX + 1 + u->i24
867 : (co_unsigned24_t)u->i24;
868 for (size_t i = 0; i < 3; i++)
869 *begin++ = (u24 >> 8 * i) & 0xff;
870 }
871 return 3;
873 if (begin && (!end || end - begin >= 8))
874 stle_flt64(begin, u->r64);
875 return 8;
877 if (begin && (!end || end - begin >= 5)) {
878 co_unsigned40_t u40 = u->i40 < 0
879 ? CO_UNSIGNED40_MAX + 1 + u->i40
880 : (co_unsigned40_t)u->i40;
881 for (size_t i = 0; i < 5; i++)
882 *begin++ = (u40 >> 8 * i) & 0xff;
883 }
884 return 5;
886 if (begin && (!end || end - begin >= 6)) {
887 co_unsigned48_t u48 = u->i48 < 0
888 ? CO_UNSIGNED48_MAX + 1 + u->i48
889 : (co_unsigned48_t)u->i48;
890 for (size_t i = 0; i < 6; i++)
891 *begin++ = (u48 >> 8 * i) & 0xff;
892 }
893 return 6;
895 if (begin && (!end || end - begin >= 7)) {
896 co_unsigned56_t u56 = u->i56 < 0
897 ? CO_UNSIGNED56_MAX + 1 + u->i56
898 : (co_unsigned56_t)u->i56;
899 for (size_t i = 0; i < 7; i++)
900 *begin++ = (u56 >> 8 * i) & 0xff;
901 }
902 return 7;
904 if (begin && (!end || end - begin >= 8))
905 stle_i64(begin, u->i64);
906 return 8;
908 if (begin && (!end || end - begin >= 3)) {
909 for (size_t i = 0; i < 3; i++)
910 *begin++ = (u->u24 >> 8 * i) & 0xff;
911 }
912 return 3;
914 if (begin && (!end || end - begin >= 5)) {
915 for (size_t i = 0; i < 5; i++)
916 *begin++ = (u->u40 >> 8 * i) & 0xff;
917 }
918 return 5;
920 if (begin && (!end || end - begin >= 6)) {
921 for (size_t i = 0; i < 6; i++)
922 *begin++ = (u->u48 >> 8 * i) & 0xff;
923 }
924 return 6;
926 if (begin && (!end || end - begin >= 7)) {
927 for (size_t i = 0; i < 7; i++)
928 *begin++ = (u->u56 >> 8 * i) & 0xff;
929 }
930 return 7;
932 if (begin && (!end || end - begin >= 8))
933 stle_u64(begin, u->u64);
934 return 8;
935 default: set_errnum(ERRNUM_INVAL); return 0;
936 }
937 }
938}
939
940#if !LELY_NO_STDIO
941
942size_t
943co_val_write_file(co_unsigned16_t type, const void *val, const char *filename)
944{
945 fwbuf_t *buf = fwbuf_create(filename);
946 if (buf) {
947 int errc = get_errc();
948 set_errc(0);
949 size_t size = co_val_write_fwbuf(type, val, buf);
950 if (!size && get_errc()) {
951 errc = get_errc();
952 diag(DIAG_ERROR, get_errc(), "%s", filename);
953 }
954 fwbuf_destroy(buf);
955 set_errc(errc);
956 return size;
957 } else {
958 diag(DIAG_ERROR, get_errc(), "%s", filename);
959 return 0;
960 }
961}
962
963size_t
964co_val_write_fwbuf(co_unsigned16_t type, const void *val, fwbuf_t *buf)
965{
966 if (co_type_is_array(type)) {
967 const void *ptr = co_val_addressof(type, val);
968 size_t n = co_val_sizeof(type, val);
969 if (!ptr || !n)
970 return 0;
971 switch (type) {
975 if (fwbuf_write(buf, ptr, n) != (ssize_t)n)
976 return 0;
977 break;
979 const char16_t *us = ptr;
980 for (size_t i = 0; i + 1 < n; i += 2) {
981 uint_least8_t tmp[2];
982 stle_u16(tmp, us[i / 2]);
983 if (fwbuf_write(buf, tmp, 2) != 2)
984 return 0;
985 }
986 break;
987 }
988 // We can never get here.
989 default: return 0;
990 }
991 if (fwbuf_commit(buf) == -1)
992 return 0;
993 return n;
994 } else {
995 union co_val tmp;
996 uint_least8_t *begin = (uint_least8_t *)&tmp;
997 uint_least8_t *end = begin + sizeof(tmp);
998 size_t n = co_val_write(type, val, begin, end);
999 if (!n)
1000 return 0;
1001 if (fwbuf_write(buf, &tmp, n) != (ssize_t)n)
1002 return 0;
1003 if (fwbuf_commit(buf) == -1)
1004 return 0;
1005 return n;
1006 }
1007}
1008
1009size_t
1010co_val_lex(co_unsigned16_t type, void *val, const char *begin, const char *end,
1011 struct floc *at)
1012{
1013 assert(begin);
1014 assert(!end || end >= begin);
1015
1016 // Prevent a previous range error from triggering a spurious warning.
1017 if (get_errnum() == ERRNUM_RANGE)
1018 set_errnum(0);
1019
1020 const char *cp = begin;
1021 size_t chars = 0;
1022
1023 union co_val u;
1024 switch (type) {
1025 case CO_DEFTYPE_BOOLEAN:
1026 chars = lex_c99_u8(cp, end, NULL, &u.u8);
1027 if (chars) {
1028 cp += chars;
1029 if (u.u8 > CO_BOOLEAN_MAX) {
1030 u.u8 = CO_BOOLEAN_MAX;
1033 "boolean truth value overflow");
1034 }
1035 if (val)
1036 *(co_boolean_t *)val = u.u8;
1037 }
1038 break;
1040 chars = lex_c99_i8(cp, end, NULL, &u.i8);
1041 if (chars) {
1042 cp += chars;
1043#ifdef INT8_MIN
1044 if (get_errnum() == ERRNUM_RANGE && u.i8 == INT8_MIN) {
1045#else
1046 if (u.i8 < CO_INTEGER8_MIN) {
1047 u.i8 = CO_INTEGER8_MIN;
1049#endif
1051 "8-bit signed integer underflow");
1052#ifdef INT8_MAX
1053 } else if (get_errnum() == ERRNUM_RANGE
1054 && u.i8 == INT8_MAX) {
1055#else
1056 } else if (u.i8 > CO_INTEGER8_MAX) {
1057 u.i8 = CO_INTEGER8_MAX;
1059#endif
1061 "8-bit signed integer overflow");
1062 }
1063 if (val)
1064 *(co_integer8_t *)val = u.i8;
1065 }
1066 break;
1068 chars = lex_c99_i16(cp, end, NULL, &u.i16);
1069 if (chars) {
1070 cp += chars;
1071#ifdef INT16_MIN
1072 if (get_errnum() == ERRNUM_RANGE
1073 && u.i16 == INT16_MIN) {
1074#else
1075 if (u.i16 < CO_INTEGER16_MIN) {
1076 u.i16 = CO_INTEGER16_MIN;
1078#endif
1080 "16-bit signed integer underflow");
1081#ifdef INT16_MAX
1082 } else if (get_errnum() == ERRNUM_RANGE
1083 && u.i16 == INT16_MAX) {
1084#else
1085 } else if (u.i16 > CO_INTEGER16_MAX) {
1086 u.i16 = CO_INTEGER16_MAX;
1088#endif
1090 "16-bit signed integer overflow");
1091 }
1092 if (val)
1093 *(co_integer16_t *)val = u.i16;
1094 }
1095 break;
1097 chars = lex_c99_i32(cp, end, NULL, &u.i32);
1098 if (chars) {
1099 cp += chars;
1100#ifdef INT32_MIN
1101 if (get_errnum() == ERRNUM_RANGE
1102 && u.i32 == INT32_MIN) {
1103#else
1104 if (u.i32 < CO_INTEGER32_MIN) {
1105 u.i32 = CO_INTEGER32_MIN;
1107#endif
1109 "32-bit signed integer underflow");
1110#ifdef INT32_MAX
1111 } else if (get_errnum() == ERRNUM_RANGE
1112 && u.i32 == INT32_MAX) {
1113#else
1114 } else if (u.i32 > CO_INTEGER32_MAX) {
1115 u.i32 = CO_INTEGER32_MAX;
1117#endif
1119 "32-bit signed integer overflow");
1120 }
1121 if (val)
1122 *(co_integer32_t *)val = u.i32;
1123 }
1124 break;
1126 chars = lex_c99_u8(cp, end, NULL, &u.u8);
1127 if (chars) {
1128 cp += chars;
1129#ifdef UINT8_MAX
1130 if (get_errnum() == ERRNUM_RANGE && u.u8 == UINT8_MAX) {
1131#else
1132 if (u.u8 > CO_UNSIGNED8_MAX) {
1133 u.u8 = CO_UNSIGNED8_MAX;
1135#endif
1137 "8-bit unsigned integer overflow");
1138 }
1139 if (val)
1140 *(co_unsigned8_t *)val = u.u8;
1141 }
1142 break;
1144 chars = lex_c99_u16(cp, end, NULL, &u.u16);
1145 if (chars) {
1146 cp += chars;
1147#ifdef UINT16_MAX
1148 if (get_errnum() == ERRNUM_RANGE
1149 && u.u16 == UINT16_MAX) {
1150#else
1151 if (u.u16 > CO_UNSIGNED16_MAX) {
1152 u.u16 = CO_UNSIGNED16_MAX;
1154#endif
1156 "16-bit unsigned integer overflow");
1157 }
1158 if (val)
1159 *(co_unsigned16_t *)val = u.u16;
1160 }
1161 break;
1163 chars = lex_c99_u32(cp, end, NULL, &u.u32);
1164 if (chars) {
1165 cp += chars;
1166#ifdef UINT32_MAX
1167 if (get_errnum() == ERRNUM_RANGE
1168 && u.u32 == UINT32_MAX) {
1169#else
1170 if (u.u32 > CO_UNSIGNED32_MAX) {
1171 u.u32 = CO_UNSIGNED32_MAX;
1173#endif
1175 "32-bit unsigned integer overflow");
1176 }
1177 if (val)
1178 *(co_unsigned32_t *)val = u.u32;
1179 }
1180 break;
1181 case CO_DEFTYPE_REAL32:
1182 chars = lex_c99_u32(cp, end, NULL, &u.u32);
1183 if (chars) {
1184 cp += chars;
1185 if (get_errnum() == ERRNUM_RANGE
1186 && u.u32 == UINT_LEAST32_MAX)
1188 "32-bit unsigned integer overflow");
1189 // clang-format off
1190 u.r32 = ((union {
1191 uint_least32_t u32;
1192 co_real32_t r32;
1193 }){ u.u32 }).r32;
1194 // clang-format on
1195 if (val)
1196 *(co_real32_t *)val = u.r32;
1197 }
1198 break;
1200 size_t n = 0;
1201 chars = lex_c99_str(cp, end, NULL, NULL, &n);
1202 if (val) {
1203 if (co_val_init_vs_n(val, 0, n) == -1) {
1205 "unable to create value of type VISIBLE_STRING");
1206 return 0;
1207 }
1208 // Parse the characters.
1209 char *vs = *(void **)val;
1210 assert(vs);
1211 lex_c99_str(cp, end, NULL, vs, &n);
1212 }
1213 cp += chars;
1214 break;
1215 }
1217 size_t n = 0;
1218 chars = lex_base64(cp, end, NULL, NULL, &n);
1219 if (val) {
1220 if (co_val_init_os(val, NULL, n) == -1) {
1222 "unable to create value of type OCTET_STRING");
1223 return 0;
1224 }
1225 // Parse the octets.
1226 uint_least8_t *os = *(void **)val;
1227 assert(!n || os);
1228 lex_base64(cp, end, NULL, os, &n);
1229 }
1230 cp += chars;
1231 break;
1232 }
1234 size_t n = 0;
1235 chars = lex_base64(cp, end, NULL, NULL, &n);
1236 if (val) {
1237 if (co_val_init_us_n(val, NULL, n / 2) == -1) {
1239 "unable to create value of type UNICODE_STRING");
1240 return 0;
1241 }
1242 // Parse the Unicode characters.
1243 char16_t *us = *(void **)val;
1244 assert(us);
1245 lex_base64(cp, end, NULL, us, &n);
1246 for (size_t i = 0; i + 1 < n; i += 2)
1247 us[i / 2] = letoh16(us[i / 2]);
1248 }
1249 cp += chars;
1250 break;
1251 }
1254 chars = lex_c99_u16(cp, end, NULL, &u.t.days);
1255 if (!chars)
1256 return 0;
1257 cp += chars;
1258 cp += lex_ctype(&isblank, cp, end, NULL);
1259 chars = lex_c99_u32(cp, end, NULL, &u.t.ms);
1260 if (!chars)
1261 return 0;
1262 cp += chars;
1263 if (val)
1264 *(co_time_of_day_t *)val = u.t;
1265 break;
1266 case CO_DEFTYPE_DOMAIN: {
1267 size_t n = 0;
1268 chars = lex_base64(cp, end, NULL, NULL, &n);
1269 if (val) {
1270 if (co_val_init_dom(val, NULL, n) == -1) {
1272 "unable to create value of type DOMAIN");
1273 return 0;
1274 }
1275 void *dom = *(void **)val;
1276 assert(!n || dom);
1277 lex_base64(cp, end, NULL, dom, &n);
1278 }
1279 cp += chars;
1280 break;
1281 }
1283 chars = lex_c99_i32(cp, end, NULL, &u.i32);
1284 if (chars) {
1285 cp += chars;
1286 if (u.i32 < CO_INTEGER24_MIN) {
1287 u.i32 = CO_INTEGER24_MIN;
1290 "24-bit signed integer underflow");
1291 } else if (u.i32 > CO_INTEGER24_MAX) {
1292 u.i32 = CO_INTEGER24_MAX;
1295 "24-bit signed integer overflow");
1296 }
1297 if (val)
1298 *(co_integer24_t *)val = u.i32;
1299 }
1300 break;
1301 case CO_DEFTYPE_REAL64:
1302 chars = lex_c99_u64(cp, end, NULL, &u.u64);
1303 if (chars) {
1304 cp += chars;
1305 if (get_errnum() == ERRNUM_RANGE
1306 && u.u64 == UINT_LEAST64_MAX)
1308 "64-bit unsigned integer overflow");
1309 // clang-format off
1310 u.r64 = ((union {
1311 uint_least64_t u64;
1312 co_real64_t r64;
1313 }){ u.u64 }).r64;
1314 // clang-format on
1315 if (val)
1316 *(co_real64_t *)val = u.r64;
1317 }
1318 break;
1320 chars = lex_c99_i64(cp, end, NULL, &u.i64);
1321 if (chars) {
1322 cp += chars;
1323 if (u.i64 < CO_INTEGER40_MIN) {
1324 u.i64 = CO_INTEGER40_MIN;
1327 "40-bit signed integer underflow");
1328 } else if (u.i64 > CO_INTEGER40_MAX) {
1329 u.i64 = CO_INTEGER40_MAX;
1332 "40-bit signed integer overflow");
1333 }
1334 if (val)
1335 *(co_integer40_t *)val = u.i64;
1336 }
1337 break;
1339 chars = lex_c99_i64(cp, end, NULL, &u.i64);
1340 if (chars) {
1341 cp += chars;
1342 if (u.i64 < CO_INTEGER48_MIN) {
1343 u.i64 = CO_INTEGER48_MIN;
1346 "48-bit signed integer underflow");
1347 } else if (u.i64 > CO_INTEGER48_MAX) {
1348 u.i64 = CO_INTEGER48_MAX;
1351 "48-bit signed integer overflow");
1352 }
1353 if (val)
1354 *(co_integer48_t *)val = u.i64;
1355 }
1356 break;
1358 chars = lex_c99_i64(cp, end, NULL, &u.i64);
1359 if (chars) {
1360 cp += chars;
1361 if (u.i64 < CO_INTEGER56_MIN) {
1362 u.i64 = CO_INTEGER56_MIN;
1365 "56-bit signed integer underflow");
1366 } else if (u.i64 > CO_INTEGER56_MAX) {
1367 u.i64 = CO_INTEGER56_MAX;
1370 "56-bit signed integer overflow");
1371 }
1372 if (val)
1373 *(co_integer56_t *)val = u.i64;
1374 }
1375 break;
1377 chars = lex_c99_i64(cp, end, NULL, &u.i64);
1378 if (chars) {
1379 cp += chars;
1380#ifdef INT64_MIN
1381 if (get_errnum() == ERRNUM_RANGE
1382 && u.i64 == INT64_MIN) {
1383#else
1384 if (u.i64 > CO_INTEGER64_MIN) {
1385 u.i64 = CO_INTEGER64_MIN;
1387#endif
1389 "64-bit signed integer underflow");
1390#ifdef INT64_MAX
1391 } else if (get_errnum() == ERRNUM_RANGE
1392 && u.i64 == INT64_MAX) {
1393#else
1394 } else if (u.i64 < CO_INTEGER64_MAX) {
1395 u.i64 = CO_INTEGER64_MAX;
1397#endif
1399 "64-bit signed integer overflow");
1400 }
1401 if (val)
1402 *(co_integer64_t *)val = u.i64;
1403 }
1404 break;
1406 chars = lex_c99_u32(cp, end, NULL, &u.u32);
1407 if (chars) {
1408 cp += chars;
1409 if (u.u32 > CO_UNSIGNED24_MAX) {
1410 u.u32 = CO_UNSIGNED24_MAX;
1413 "24-bit unsigned integer overflow");
1414 }
1415 if (val)
1416 *(co_unsigned24_t *)val = u.u32;
1417 }
1418 break;
1420 chars = lex_c99_u64(cp, end, NULL, &u.u64);
1421 if (chars) {
1422 cp += chars;
1423 if (u.u64 > CO_UNSIGNED40_MAX) {
1424 u.u64 = CO_UNSIGNED40_MAX;
1427 "40-bit unsigned integer overflow");
1428 }
1429 if (val)
1430 *(co_unsigned40_t *)val = u.u64;
1431 }
1432 break;
1434 chars = lex_c99_u64(cp, end, NULL, &u.u64);
1435 if (chars) {
1436 cp += chars;
1437 if (u.u64 > CO_UNSIGNED48_MAX) {
1438 u.u64 = CO_UNSIGNED48_MAX;
1441 "48-bit unsigned integer overflow");
1442 }
1443 if (val)
1444 *(co_unsigned48_t *)val = u.u64;
1445 }
1446 break;
1448 chars = lex_c99_u64(cp, end, NULL, &u.u64);
1449 if (chars) {
1450 cp += chars;
1451 if (u.u64 > CO_UNSIGNED56_MAX) {
1452 u.u64 = CO_UNSIGNED56_MAX;
1455 "56-bit unsigned integer overflow");
1456 }
1457 if (val)
1458 *(co_unsigned56_t *)val = u.u64;
1459 }
1460 break;
1462 chars = lex_c99_u64(cp, end, NULL, &u.u64);
1463 if (chars) {
1464 cp += chars;
1465#ifdef UINT64_MAX
1466 if (get_errnum() == ERRNUM_RANGE
1467 && u.u64 == UINT64_MAX) {
1468#else
1469 if (u.u64 > CO_UNSIGNED64_MAX) {
1470 u.u64 = CO_UNSIGNED64_MAX;
1472#endif
1474 "64-bit unsigned integer overflow");
1475 }
1476 if (val)
1477 *(co_unsigned64_t *)val = u.u64;
1478 }
1479 break;
1480 default:
1481 diag_if(DIAG_ERROR, 0, at, "cannot parse value of type 0x%04X",
1482 type);
1483 break;
1484 }
1485
1486 return floc_lex(at, begin, cp);
1487}
1488
1489size_t
1490co_val_print(co_unsigned16_t type, const void *val, char **pbegin, char *end)
1491{
1492 if (co_type_is_array(type)) {
1493 const void *ptr = co_val_addressof(type, val);
1494 size_t n = co_val_sizeof(type, val);
1495 if (!ptr || !n)
1496 return 0;
1497 switch (type) {
1499 return print_c99_str(pbegin, end, ptr, n);
1501 return print_base64(pbegin, end, ptr, n);
1502 }
1504#if LELY_NO_MALLOC
1505 if (n > CO_ARRAY_CAPACITY) {
1507 return -1;
1508 }
1509 char16_t us[CO_ARRAY_CAPACITY / 2];
1510#else
1511 char16_t *us = malloc(n);
1512 if (!us)
1513 return 0;
1514#endif
1515 memcpy(us, ptr, n);
1516 for (size_t i = 0; i + 1 < n; i += 2)
1517 us[i / 2] = htole16(us[i / 2]);
1518 size_t chars = print_base64(pbegin, end, us, n);
1519#if !LELY_NO_MALLOC
1520 free(us);
1521#endif
1522 return chars;
1523 }
1524 case CO_DEFTYPE_DOMAIN:
1525 return print_base64(pbegin, end, ptr, n);
1526 default:
1527 // We can never get here.
1528 return 0;
1529 }
1530 } else {
1531 const union co_val *u = val;
1532 assert(u);
1533 switch (type) {
1534 case CO_DEFTYPE_BOOLEAN:
1535 return print_c99_u8(pbegin, end, !!u->b);
1537 return print_c99_i8(pbegin, end, u->i8);
1539 return print_c99_i16(pbegin, end, u->i16);
1541 return print_c99_i32(pbegin, end, u->i32);
1543 return print_fmt(pbegin, end, "0x%02" PRIx8, u->u8);
1545 return print_fmt(pbegin, end, "0x%04" PRIx16, u->u16);
1547 return print_fmt(pbegin, end, "0x%08" PRIx32, u->u32);
1548 case CO_DEFTYPE_REAL32:
1549 return print_c99_u32(pbegin, end, u->u32);
1551 case CO_DEFTYPE_TIME_DIFF: {
1552 size_t chars = 0;
1553 chars += print_c99_u16(pbegin, end, u->t.days);
1554 chars += print_char(pbegin, end, ' ');
1555 chars += print_c99_u32(pbegin, end, u->t.ms);
1556 return chars;
1557 }
1559 return print_c99_i32(pbegin, end, u->i24);
1560 case CO_DEFTYPE_REAL64:
1561 return print_fmt(pbegin, end, "0x%016" PRIx64, u->u64);
1563 return print_c99_i64(pbegin, end, u->i40);
1565 return print_c99_i64(pbegin, end, u->i48);
1567 return print_c99_i64(pbegin, end, u->i56);
1569 return print_c99_i64(pbegin, end, u->i64);
1571 return print_fmt(pbegin, end, "0x%06" PRIx32, u->u24);
1573 return print_fmt(pbegin, end, "0x%010" PRIx64, u->u40);
1575 return print_fmt(pbegin, end, "0x%012" PRIx64, u->u48);
1577 return print_fmt(pbegin, end, "0x%014" PRIx64, u->u56);
1579 return print_fmt(pbegin, end, "0x%016" PRIx64, u->u64);
1580 default: set_errnum(ERRNUM_INVAL); return 0;
1581 }
1582 }
1583}
1584
1585#endif // !LELY_NO_STDIO
1586
1587static inline struct co_array_hdr *
1588co_array_get_hdr(const void *val)
1589{
1590 assert(val);
1591
1592 char *ptr = *(char **)val;
1593 return ptr ? (void *)(ptr - CO_ARRAY_HDR_OFFSET) : NULL;
1594}
1595
1596static int
1597co_array_alloc(void *val, size_t size)
1598{
1599 assert(val);
1600
1601#if LELY_NO_MALLOC
1602 struct co_array_hdr *hdr = co_array_get_hdr(val);
1603 if (!hdr || hdr->capacity < size) {
1605 return -1;
1606 }
1607 hdr->size = 0;
1608#else
1609 if (size) {
1610 // cppcheck-suppress AssignmentAddressToInteger
1611 struct co_array_hdr *hdr = malloc(CO_ARRAY_HDR_OFFSET + size);
1612 if (!hdr) {
1613#if !LELY_NO_ERRNO
1614 set_errc(errno2c(errno));
1615#endif
1616 return -1;
1617 }
1618 *hdr = (struct co_array_hdr){ size, 0 };
1619 *(char **)val = (char *)hdr + CO_ARRAY_HDR_OFFSET;
1620 } else {
1621 *(char **)val = NULL;
1622 }
1623#endif
1624
1625 return 0;
1626}
1627
1628static void
1629co_array_free(void *val)
1630{
1631#if LELY_NO_MALLOC
1632 (void)val;
1633#else
1634 struct co_array_hdr *hdr = co_array_get_hdr(val);
1635 if (hdr)
1636 free(hdr);
1637#endif
1638}
1639
1640static void
1641co_array_init(void *val, size_t size)
1642{
1643 struct co_array_hdr *hdr = co_array_get_hdr(val);
1644 assert(val || !size);
1645
1646 if (hdr) {
1647 memset(*(char **)val, 0, hdr->capacity);
1648 assert(size <= hdr->capacity);
1649 hdr->size = size;
1650 }
1651}
1652
1653static void
1654co_array_fini(void *val)
1655{
1656#if LELY_NO_MALLOC
1657 co_array_init(val, 0);
1658#else
1659 assert(val);
1660
1661 *(char **)val = NULL;
1662#endif
1663}
1664
1665static size_t
1666co_array_sizeof(const void *val)
1667{
1668 const struct co_array_hdr *hdr = co_array_get_hdr(val);
1669
1670 return hdr ? hdr->size : 0;
1671}
This header file is part of the utilities library; it contains the comparison function definitions.
This header file is part of the utilities library; it contains the diagnostic declarations.
size_t floc_lex(struct floc *at, const char *begin, const char *end)
Increments a file location by reading characters from a memory buffer.
Definition diag.c:65
@ DIAG_WARNING
A warning.
Definition diag.h:55
@ DIAG_ERROR
An error.
Definition diag.h:57
void diag_if(enum diag_severity severity, int errc, const struct floc *at, const char *format,...)
Emits a diagnostic message occurring at a location in a text file.
Definition diag.c:205
void diag(enum diag_severity severity, int errc, const char *format,...)
Emits a diagnostic message.
Definition diag.c:171
This header file is part of the utilities library; it contains the byte order (endianness) function d...
void stle_u64(uint_least8_t dst[8], uint_least64_t x)
Stores a 64-bit unsigned integer in little-endian byte order.
Definition endian.h:672
uint_least16_t htole16(uint_least16_t x)
Converts a 16-bit unsigned integer from host to little-endian byte order.
Definition endian.h:351
uint_least32_t ldle_u32(const uint_least8_t src[4])
Loads a 32-bit unsigned integer in little-endian byte order.
Definition endian.h:596
void stle_i64(uint_least8_t dst[8], int_least64_t x)
Stores a 64-bit signed integer in little-endian byte order.
Definition endian.h:660
int_least32_t ldle_i32(const uint_least8_t src[4])
Loads a 32-bit signed integer in little-endian byte order.
Definition endian.h:576
int_least16_t ldle_i16(const uint_least8_t src[2])
Loads a 16-bit signed integer in little-endian byte order.
Definition endian.h:498
int_least64_t ldle_i64(const uint_least8_t src[8])
Loads a 64-bit signed integer in little-endian byte order.
Definition endian.h:666
uint_least16_t ldle_u16(const uint_least8_t src[2])
Loads a 16-bit unsigned integer in little-endian byte order.
Definition endian.h:516
void stle_i16(uint_least8_t dst[2], int_least16_t x)
Stores a 16-bit signed integer in little-endian byte order.
Definition endian.h:492
uint_least64_t ldle_u64(const uint_least8_t src[8])
Loads a 64-bit unsigned integer in little-endian byte order.
Definition endian.h:690
void stle_i32(uint_least8_t dst[4], int_least32_t x)
Stores a 32-bit signed integer in little-endian byte order.
Definition endian.h:570
void stle_u16(uint_least8_t dst[2], uint_least16_t x)
Stores a 16-bit unsigned integer in little-endian byte order.
Definition endian.h:504
void stle_u32(uint_least8_t dst[4], uint_least32_t x)
Stores a 32-bit unsigned integer in little-endian byte order.
Definition endian.h:582
@ ERRNUM_RANGE
Result too large.
Definition errnum.h:218
@ ERRNUM_NOMEM
Not enough space.
Definition errnum.h:172
@ ERRNUM_INVAL
Invalid argument.
Definition errnum.h:132
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition errnum.c:932
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition errnum.c:944
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition errnum.c:46
errnum_t get_errnum(void)
Returns the last (thread-specific) platform-independent error number set by a system call or library ...
Definition errnum.h:418
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition errnum.h:424
This header file is part of the utilities library; it contains the read file buffer declarations.
intmax_t frbuf_get_size(frbuf_t *buf)
Returns the size (in bytes) of the a read file buffer, or -1 on error.
Definition frbuf.c:172
void frbuf_destroy(frbuf_t *buf)
Destroys a read file buffer.
Definition frbuf.c:163
intmax_t frbuf_get_pos(frbuf_t *buf)
Returns the current offset (in bytes) of a read file buffer with respect to the beginning of the file...
Definition frbuf.c:217
frbuf_t * frbuf_create(const char *filename)
Creates a new read file buffer.
Definition frbuf.c:138
ssize_t frbuf_read(frbuf_t *buf, void *ptr, size_t size)
Reads bytes from the current position in a read file buffer.
Definition frbuf.c:275
This header file is part of the utilities library; it contains the (atomic) write file buffer declara...
ssize_t fwbuf_write(fwbuf_t *buf, const void *ptr, size_t size)
Writes bytes to the current position in a write file buffer.
Definition fwbuf.c:489
void fwbuf_destroy(fwbuf_t *buf)
Destroys a write file buffer.
Definition fwbuf.c:330
int fwbuf_commit(fwbuf_t *buf)
Commits all changes to a write file buffer to disk if all previous file operations were successful,...
Definition fwbuf.c:979
fwbuf_t * fwbuf_create(const char *filename)
Creates a new (atomic) write file buffer.
Definition fwbuf.c:305
This header file is part of the CANopen library; it contains the Service Data Object (SDO) declaratio...
#define CO_SDO_AC_ERROR
SDO abort code: General error.
Definition sdo.h:150
#define CO_SDO_AC_NO_MEM
SDO abort code: Out of memory.
Definition sdo.h:81
#define MIN(a, b)
Returns the minimum of a and b.
Definition util.h:57
This header file is part of the utilities library; it contains the lexer function declarations.
size_t lex_c99_i16(const char *begin, const char *end, struct floc *at, int_least16_t *pi16)
Lexes a C99 int_least16_t from a memory buffer.
Definition lex.c:452
size_t lex_ctype(int(*ctype)(int), const char *begin, const char *end, struct floc *at)
Greedily lexes a sequence of characters of the specified class from a memory buffer.
Definition lex.c:54
size_t lex_c99_u8(const char *begin, const char *end, struct floc *at, uint_least8_t *pu8)
Lexes a C99 uint_least8_t from a memory buffer.
Definition lex.c:547
size_t lex_base64(const char *begin, const char *end, struct floc *at, void *ptr, size_t *pn)
Lexes and decodes the Base64 representation of binary data from a memory buffer.
Definition lex.c:689
size_t lex_c99_str(const char *begin, const char *end, struct floc *at, char *s, size_t *pn)
Lexes a UTF-8 encoded Unicode string from a memory buffer.
Definition lex.c:250
size_t lex_c99_i8(const char *begin, const char *end, struct floc *at, int_least8_t *pi8)
Lexes a C99 int_least8_t from a memory buffer.
Definition lex.c:428
size_t lex_c99_u32(const char *begin, const char *end, struct floc *at, uint_least32_t *pu32)
Lexes a C99 uint_least32_t from a memory buffer.
Definition lex.c:585
size_t lex_c99_u64(const char *begin, const char *end, struct floc *at, uint_least64_t *pu64)
Lexes a C99 uint_least64_t from a memory buffer.
Definition lex.c:608
size_t lex_c99_i32(const char *begin, const char *end, struct floc *at, int_least32_t *pi32)
Lexes a C99 int_least32_t from a memory buffer.
Definition lex.c:476
size_t lex_c99_u16(const char *begin, const char *end, struct floc *at, uint_least16_t *pu16)
Lexes a C99 uint_least16_t from a memory buffer.
Definition lex.c:566
size_t lex_c99_i64(const char *begin, const char *end, struct floc *at, int_least64_t *pi64)
Lexes a C99 int_least64_t from a memory buffer.
Definition lex.c:508
This header file is part of the utilities library; it contains the printing function declarations.
size_t print_c99_i8(char **pbegin, char *end, int_least8_t i8)
Prints a C99 int_least8_t to a memory buffer.
Definition print.c:242
size_t print_c99_str(char **pbegin, char *end, const char *s, size_t n)
Prints a UTF-8 encoded Unicode string to a memory buffer.
Definition print.c:193
size_t print_char(char **pbegin, char *end, int c)
Prints a single character to a memory buffer.
Definition print.h:286
size_t print_c99_u8(char **pbegin, char *end, uint_least8_t u8)
Prints a C99 uint_least8_t to a memory buffer.
Definition print.c:250
size_t print_c99_i32(char **pbegin, char *end, int_least32_t i32)
Prints a C99 int_least32_t to a memory buffer.
Definition print.c:244
size_t print_c99_u32(char **pbegin, char *end, uint_least32_t u32)
Prints a C99 uint_least32_t to a memory buffer.
Definition print.c:252
size_t print_base64(char **pbegin, char *end, const void *ptr, size_t n)
Prints the Base64 representation of binary data to a memory buffer.
Definition print.c:262
size_t print_c99_i16(char **pbegin, char *end, int_least16_t i16)
Prints a C99 int_least16_t to a memory buffer.
Definition print.c:243
size_t print_c99_i64(char **pbegin, char *end, int_least64_t i64)
Prints a C99 int_least64_t to a memory buffer.
Definition print.c:248
size_t print_c99_u16(char **pbegin, char *end, uint_least16_t u16)
Prints a C99 uint_least16_t to a memory buffer.
Definition print.c:251
size_t print_fmt(char **pbegin, char *end, const char *format,...)
Prints a formatted string to a memory buffer.
Definition print.c:43
This is the internal header file of the CANopen library.
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
This header file is part of the C11 and POSIX compatibility library; it includes <string....
An read file buffer struct.
Definition frbuf.c:52
An (atomic) write file buffer struct.
Definition fwbuf.c:59
The header directly preceding the bytes in a CANopen array.
Definition val.h:280
size_t size
The current size (in bytes).
Definition val.h:284
size_t capacity
The total capacity (in bytes).
Definition val.h:282
A location in a text file.
Definition diag.h:39
#define CO_DEFTYPE_UNICODE_STRING
The data type (and object index) of an array of (16-bit) Unicode characters.
Definition type.h:62
#define CO_DEFTYPE_UNSIGNED16
The data type (and object index) of a 16-bit unsigned integer.
Definition type.h:47
#define CO_DEFTYPE_INTEGER24
The data type (and object index) of a 24-bit signed integer.
Definition type.h:80
#define CO_DEFTYPE_UNSIGNED48
The data type (and object index) of a 48-bit unsigned integer.
Definition type.h:104
#define CO_DEFTYPE_INTEGER48
The data type (and object index) of a 48-bit signed integer.
Definition type.h:89
#define CO_DEFTYPE_VISIBLE_STRING
The data type (and object index) of an array of visible characters.
Definition type.h:56
#define CO_DEFTYPE_UNSIGNED40
The data type (and object index) of a 40-bit unsigned integer.
Definition type.h:101
int co_type_is_array(co_unsigned16_t type)
Returns 1 if the specified (static) data type is an array, and 0 if not.
Definition type.c:40
#define CO_DEFTYPE_INTEGER56
The data type (and object index) of a 56-bit signed integer.
Definition type.h:92
#define CO_DEFTYPE_UNSIGNED64
The data type (and object index) of a 64-bit unsigned integer.
Definition type.h:110
#define CO_DEFTYPE_INTEGER8
The data type (and object index) of an 8-bit signed integer.
Definition type.h:35
#define CO_DEFTYPE_DOMAIN
The data type (and object index) of an arbitrary large block of data.
Definition type.h:77
#define CO_DEFTYPE_UNSIGNED24
The data type (and object index) of a 24-bit unsigned integer.
Definition type.h:98
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
Definition type.h:44
#define CO_DEFTYPE_REAL64
The data type (and object index) of a 64-bit IEEE-754 floating-point number.
Definition type.h:83
#define CO_DEFTYPE_BOOLEAN
The data type (and object index) of a boolean truth value.
Definition type.h:32
#define CO_DEFTYPE_INTEGER40
The data type (and object index) of a 40-bit signed integer.
Definition type.h:86
#define CO_DEFTYPE_TIME_OF_DAY
The data type (and object index) of a 48-bit structure representing the absolute time.
Definition type.h:68
size_t co_type_sizeof(co_unsigned16_t type)
Returns the native size (in bytes) of a value of the specified data type, or 1 if it is not a static ...
Definition type.c:52
#define CO_DEFTYPE_INTEGER32
The data type (and object index) of a 32-bit signed integer.
Definition type.h:41
#define CO_DEFTYPE_INTEGER64
The data type (and object index) of a 64-bit signed integer.
Definition type.h:95
#define CO_DEFTYPE_UNSIGNED56
The data type (and object index) of a 56-bit unsigned integer.
Definition type.h:107
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
Definition type.h:50
#define CO_DEFTYPE_INTEGER16
The data type (and object index) of a 16-bit signed integer.
Definition type.h:38
#define CO_DEFTYPE_OCTET_STRING
The data type (and object index) of an array of octets.
Definition type.h:59
#define CO_DEFTYPE_REAL32
The data type (and object index) of a 32-bit IEEE-754 floating-point number.
Definition type.h:53
#define CO_DEFTYPE_TIME_DIFF
The data type (and object index) of a 48-bit structure representing a time difference.
Definition type.h:74
This header file is part of the C11 and POSIX compatibility library; it includes <sys/types....
ptrdiff_t ssize_t
Used for a count of bytes or an error indication.
Definition types.h:43
A union of the CANopen static data types.
Definition val.h:273
This header file is part of the utilities library; it contains (16-bit) Unicode string functions.
int str16ncmp(const char16_t *s1, const char16_t *s2, size_t n)
Compares two (16-bit) Unicode strings.
Definition ustring.h:100
char16_t * str16ncpy(char16_t *dst, const char16_t *src, size_t n)
Copies n (16-bit) Unicode characters from the string at src to dst.
Definition ustring.h:88
size_t str16len(const char16_t *s)
Returns the number of (16-bit) Unicode characters, excluding the terminating null bytes,...
Definition ustring.h:78
size_t co_val_read_frbuf(co_unsigned16_t type, void *val, frbuf_t *buf)
Reads a value of the specified data type from the current position in a read file buffer.
Definition val.c:692
size_t co_val_read(co_unsigned16_t type, void *val, const uint_least8_t *begin, const uint_least8_t *end)
Reads a value of the specified data type from a memory buffer.
Definition val.c:451
int co_val_init(co_unsigned16_t type, void *val)
Initializes a value of the specified data type to zero.
Definition val.c:62
size_t co_val_move(co_unsigned16_t type, void *dst, void *src)
Moves one value to another.
Definition val.c:354
const void * co_val_addressof(co_unsigned16_t type, const void *val)
Returns the address of the first byte in a value of the specified data type.
Definition val.c:260
int co_val_init_os(uint_least8_t **val, const uint_least8_t *os, size_t n)
Initializes an array of octets (CO_DEFTYPE_OCTET_STRING).
Definition val.c:179
size_t co_val_write(co_unsigned16_t type, const void *val, uint_least8_t *begin, uint_least8_t *end)
Writes a value of the specified data type to a memory buffer.
Definition val.c:791
int co_val_init_dom(void **val, const void *dom, size_t n)
Initializes an arbitrary large block of data (CO_DEFTYPE_DOMAIN).
Definition val.c:230
size_t co_val_copy(co_unsigned16_t type, void *dst, const void *src)
Copies one value to another.
Definition val.c:318
size_t co_val_sizeof(co_unsigned16_t type, const void *val)
Returns the size (in bytes) of a value of the specified data type.
Definition val.c:269
int co_val_init_us_n(char16_t **val, const char16_t *us, size_t n)
Initializes an array of (16-bit) Unicode characters (CO_DEFTYPE_UNICODE_STRING).
Definition val.c:211
int co_val_init_vs_n(char **val, const char *vs, size_t n)
Initializes an array of visible characters (CO_DEFTYPE_VISIBLE_STRING).
Definition val.c:157
size_t co_val_read_file(co_unsigned16_t type, void *val, const char *filename)
Reads a value of the specified data type from a file.
Definition val.c:671
int co_val_init_us(char16_t **val, const char16_t *us)
Initializes an array of (16-bit) Unicode characters (CO_DEFTYPE_UNICODE_STRING).
Definition val.c:198
int co_val_cmp(co_unsigned16_t type, const void *v1, const void *v2)
Compares two values of the specified data type.
Definition val.c:369
co_unsigned32_t co_val_read_sdo(co_unsigned16_t type, void *val, const void *ptr, size_t n)
Reads a value of the specified data type from an SDO buffer.
Definition val.c:767
int co_val_init_min(co_unsigned16_t type, void *val)
Initializes a value of the specified data type with its lower limit.
Definition val.c:90
size_t co_val_print(co_unsigned16_t type, const void *val, char **pbegin, char *end)
Prints a value of the specified data type to a memory buffer.
Definition val.c:1490
size_t co_val_make(co_unsigned16_t type, void *val, const void *ptr, size_t n)
Constructs a value of the specified data type.
Definition val.c:282
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition val.c:249
int co_val_init_vs(char **val, const char *vs)
Initializes an array of visible characters (CO_DEFTYPE_VISIBLE_STRING).
Definition val.c:146
size_t co_val_write_file(co_unsigned16_t type, const void *val, const char *filename)
Writes a value of the specified data type to a file.
Definition val.c:943
size_t co_val_lex(co_unsigned16_t type, void *val, const char *begin, const char *end, struct floc *at)
Lexes a value of the specified data type from a memory buffer.
Definition val.c:1010
size_t co_val_write_fwbuf(co_unsigned16_t type, const void *val, fwbuf_t *buf)
Writes a value of the specified data type to the current position in a write file buffer.
Definition val.c:964
int co_val_init_max(co_unsigned16_t type, void *val)
Initializes a value of the specified data type with its upper limit.
Definition val.c:118
This header file is part of the CANopen library; it contains the CANopen value declarations.
#define CO_INTEGER8_MIN
The minimum value of an 8-bit signed integer.
Definition val.h:51
#define CO_INTEGER64_MAX
The maximum value of a 64-bit signed integer.
Definition val.h:225
#define CO_INTEGER32_MAX
The maximum value of a 32-bit signed integer.
Definition val.h:72
#define CO_INTEGER24_MAX
The maximum value of a 24-bit signed integer (encoded as an int32_t).
Definition val.h:180
#define CO_UNSIGNED8_MAX
The maximum value of an 8-bit unsigned integer.
Definition val.h:81
#define CO_INTEGER16_MAX
The maximum value of a 16-bit signed integer.
Definition val.h:63
#define CO_ARRAY_CAPACITY
The default capacity (in bytes) of a statically allocated CANopen array.
Definition val.h:292
#define CO_UNSIGNED32_MAX
The maximum value of a 32-bit unsigned integer.
Definition val.h:99
#define CO_INTEGER48_MAX
The maximum value of a 48-bit signed integer (encoded as an int64_t).
Definition val.h:207
#define CO_INTEGER24_MIN
The minimum value of a 24-bit signed integer (encoded as an int32_t).
Definition val.h:177
#define CO_BOOLEAN_MAX
The maximum value of a boolean truth value (true).
Definition val.h:45
#define CO_UNSIGNED64_MAX
The maximum value of a 64-bit unsigned integer.
Definition val.h:270
#define CO_INTEGER32_MIN
The minimum value of a 32-bit signed integer.
Definition val.h:69
#define CO_INTEGER40_MAX
The maximum value of a 40-bit signed integer (encoded as an int64_t).
Definition val.h:198
#define CO_UNSIGNED40_MAX
The maximum value of a 40-bit unsigned integer (encoded as a uint64_t).
Definition val.h:243
#define CO_INTEGER64_MIN
The minimum value of a 64-bit signed integer.
Definition val.h:222
#define CO_UNSIGNED56_MAX
The maximum value of a 56-bit unsigned integer (encoded as a uint64_t).
Definition val.h:261
#define CO_INTEGER48_MIN
The minimum value of a 48-bit signed integer (encoded as an int64_t).
Definition val.h:204
#define CO_UNSIGNED48_MAX
The maximum value of a 48-bit unsigned integer (encoded as a uint64_t).
Definition val.h:252
#define CO_INTEGER56_MAX
The maximum value of a 56-bit signed integer (encoded as an int64_t).
Definition val.h:216
#define CO_INTEGER40_MIN
The minimum value of a 40-bit signed integer (encoded as an int64_t).
Definition val.h:195
#define CO_UNSIGNED24_MAX
The maximum value of a 24-bit unsigned integer (encoded as a uint32_t).
Definition val.h:234
#define CO_INTEGER16_MIN
The minimum value of a 16-bit signed integer.
Definition val.h:60
#define CO_INTEGER56_MIN
The minimum value of a 56-bit signed integer (encoded as an int64_t).
Definition val.h:213
#define CO_UNSIGNED16_MAX
The maximum value of a 16-bit unsigned integer.
Definition val.h:90
#define CO_INTEGER8_MAX
The maximum value of an 8-bit signed integer.
Definition val.h:54