Lely core libraries 1.9.2
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#include <lely/util/cmp.h>
29#include <lely/util/diag.h>
30#include <lely/util/endian.h>
31#include <lely/util/lex.h>
32#include <lely/util/print.h>
33
34#include <assert.h>
35#include <inttypes.h>
36#include <stdlib.h>
37
38#define CO_BOOLEAN_INIT 0
39#define CO_INTEGER8_INIT 0
40#define CO_INTEGER16_INIT 0
41#define CO_INTEGER32_INIT 0
42#define CO_UNSIGNED8_INIT 0
43#define CO_UNSIGNED16_INIT 0
44#define CO_UNSIGNED32_INIT 0
45#define CO_REAL32_INIT 0
46#define CO_VISIBLE_STRING_INIT NULL
47#define CO_OCTET_STRING_INIT NULL
48#define CO_UNICODE_STRING_INIT NULL
49#define CO_TIME_OF_DAY_INIT \
50 { \
51 0, 0 \
52 }
53#define CO_TIME_DIFF_INIT CO_TIME_OF_DAY_INIT
54#define CO_DOMAIN_INIT NULL
55#define CO_INTEGER24_INIT 0
56#define CO_REAL64_INIT 0
57#define CO_INTEGER40_INIT 0
58#define CO_INTEGER48_INIT 0
59#define CO_INTEGER56_INIT 0
60#define CO_INTEGER64_INIT 0
61#define CO_UNSIGNED24_INIT 0
62#define CO_UNSIGNED40_INIT 0
63#define CO_UNSIGNED48_INIT 0
64#define CO_UNSIGNED56_INIT 0
65#define CO_UNSIGNED64_INIT 0
66
67#define CO_VISIBLE_STRING_MIN NULL
68#define CO_VISIBLE_STRING_MAX NULL
69
70#define CO_OCTET_STRING_MIN NULL
71#define CO_OCTET_STRING_MAX NULL
72
73#define CO_UNICODE_STRING_MIN NULL
74#define CO_UNICODE_STRING_MAX NULL
75
76#define CO_DOMAIN_MIN NULL
77#define CO_DOMAIN_MAX NULL
78
79#define CO_ARRAY_OFFSET ALIGN(sizeof(size_t), _Alignof(union co_val))
80
81static int co_array_alloc(void *val, size_t size);
82static void co_array_free(void *val);
83static void co_array_init(void *val, size_t size);
84static void co_array_fini(void *val);
85
86static size_t co_array_sizeof(const void *val);
87
92static size_t str16len(const char16_t *s);
93
105static char16_t *str16ncpy(char16_t *dst, const char16_t *src, size_t n);
106
117static int str16ncmp(const char16_t *s1, const char16_t *s2, size_t n);
118
119int
120co_val_init(co_unsigned16_t type, void *val)
121{
122 union co_val *u = val;
123 assert(u);
124
125 switch (type) {
126#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
127 case CO_DEFTYPE_##a: \
128 u->c = (co_##b##_t)CO_##a##_INIT; \
129 return 0;
130#include <lely/co/def/type.def>
131#undef LELY_CO_DEFINE_TYPE
132 default: set_errnum(ERRNUM_INVAL); return -1;
133 }
134}
135
136int
137co_val_init_min(co_unsigned16_t type, void *val)
138{
139 union co_val *u = val;
140 assert(u);
141
142 switch (type) {
143#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
144 case CO_DEFTYPE_##a: \
145 u->c = (co_##b##_t)CO_##a##_MIN; \
146 return 0;
147#include <lely/co/def/type.def>
148#undef LELY_CO_DEFINE_TYPE
149 default: set_errnum(ERRNUM_INVAL); return -1;
150 }
151}
152
153int
154co_val_init_max(co_unsigned16_t type, void *val)
155{
156 union co_val *u = val;
157 assert(u);
158
159 switch (type) {
160#define LELY_CO_DEFINE_TYPE(a, b, c, d) \
161 case CO_DEFTYPE_##a: \
162 u->c = (co_##b##_t)CO_##a##_MAX; \
163 return 0;
164#include <lely/co/def/type.def>
165#undef LELY_CO_DEFINE_TYPE
166 default: set_errnum(ERRNUM_INVAL); return -1;
167 }
168}
169
170int
171co_val_init_vs(char **val, const char *vs)
172{
173 assert(val);
174
175 if (vs)
176 return co_val_init_vs_n(val, vs, strlen(vs));
177
178 *val = NULL;
179
180 return 0;
181}
182
183int
184co_val_init_vs_n(char **val, const char *vs, size_t n)
185{
186 assert(val);
187
188 if (n) {
189 if (__unlikely(co_array_alloc(val, n + 1) == -1))
190 return -1;
191 assert(*val);
192 co_array_init(val, n);
193 if (vs)
194 strncpy(*val, vs, n);
195 } else {
196 *val = NULL;
197 }
198
199 return 0;
200}
201
202int
203co_val_init_os(uint8_t **val, const uint8_t *os, size_t n)
204{
205 assert(val);
206
207 if (n) {
208 if (__unlikely(co_array_alloc(val, n + 1) == -1))
209 return -1;
210 assert(*val);
211 co_array_init(val, n);
212 if (os)
213 memcpy(*val, os, n);
214 } else {
215 *val = NULL;
216 }
217
218 return 0;
219}
220
221int
222co_val_init_us(char16_t **val, const char16_t *us)
223{
224 assert(val);
225
226 if (us)
227 return co_val_init_us_n(val, us, str16len(us));
228
229 *val = NULL;
230
231 return 0;
232}
233
234int
235co_val_init_us_n(char16_t **val, const char16_t *us, size_t n)
236{
237 assert(val);
238
239 if (n) {
240 if (__unlikely(co_array_alloc(val, 2 * (n + 1)) == -1))
241 return -1;
242 assert(*val);
243 co_array_init(val, 2 * n);
244 if (us)
245 str16ncpy(*val, us, n);
246 } else {
247 *val = NULL;
248 }
249
250 return 0;
251}
252
253int
254co_val_init_dom(void **val, const void *dom, size_t n)
255{
256 assert(val);
257
258 if (n) {
259 if (__unlikely(co_array_alloc(val, n) == -1))
260 return -1;
261 assert(*val);
262 co_array_init(val, n);
263 if (dom)
264 memcpy(*val, dom, n);
265 } else {
266 *val = NULL;
267 }
268
269 return 0;
270}
271
272void
273co_val_fini(co_unsigned16_t type, void *val)
274{
275 assert(val);
276
277 if (co_type_is_array(type)) {
278 co_array_free(val);
279 co_array_fini(val);
280 }
281}
282
283const void *
284co_val_addressof(co_unsigned16_t type, const void *val)
285{
286 if (__unlikely(!val))
287 return NULL;
288
289 return co_type_is_array(type) ? *(const void **)val : val;
290}
291
292size_t
293co_val_sizeof(co_unsigned16_t type, const void *val)
294{
295 if (__unlikely(!val))
296 return 0;
297
298 // clang-format off
299 return co_type_is_array(type)
300 ? co_array_sizeof(val)
301 : co_type_sizeof(type);
302 // clang-format on
303}
304
305size_t
306co_val_make(co_unsigned16_t type, void *val, const void *ptr, size_t n)
307{
308 assert(val);
309
310 if (!ptr)
311 n = 0;
312
313 switch (type) {
315 n = ptr ? strlen(ptr) : 0;
316 co_val_init_vs(val, ptr);
317 break;
318 case CO_DEFTYPE_OCTET_STRING: co_val_init_os(val, ptr, n); break;
320 n = ptr ? str16len(ptr) : 0;
321 co_val_init_us(val, ptr);
322 break;
323 case CO_DEFTYPE_DOMAIN: co_val_init_dom(val, ptr, n); break;
324 default:
325 if (__unlikely(!ptr || co_type_sizeof(type) != n))
326 return 0;
327 memcpy(val, ptr, n);
328 }
329 return n;
330}
331
332size_t
333co_val_copy(co_unsigned16_t type, void *dst, const void *src)
334{
335 assert(dst);
336 assert(src);
337
338 size_t n;
339 if (co_type_is_array(type)) {
340 const void *ptr = co_val_addressof(type, src);
341 n = co_val_sizeof(type, src);
342 switch (type) {
344 if (__unlikely(co_val_init_vs(dst, ptr) == -1))
345 return 0;
346 break;
348 if (__unlikely(co_val_init_os(dst, ptr, n) == -1))
349 return 0;
350 break;
352 if (__unlikely(co_val_init_us(dst, ptr) == -1))
353 return 0;
354 break;
356 if (__unlikely(co_val_init_dom(dst, ptr, n) == -1))
357 return 0;
358 break;
359 default:
360 // We can never get here.
361 return 0;
362 }
363 } else {
364 n = co_type_sizeof(type);
365 memcpy(dst, src, n);
366 }
367 return n;
368}
369
370size_t
371co_val_move(co_unsigned16_t type, void *dst, void *src)
372{
373 assert(dst);
374 assert(src);
375
376 size_t n = co_type_sizeof(type);
377 memcpy(dst, src, n);
378
379 if (co_type_is_array(type))
380 co_array_fini(src);
381
382 return n;
383}
384
385int
386co_val_cmp(co_unsigned16_t type, const void *v1, const void *v2)
387{
388 if (v1 == v2)
389 return 0;
390
391 if (__unlikely(!v1))
392 return -1;
393 if (__unlikely(!v2))
394 return 1;
395
396 int cmp = 0;
397 if (co_type_is_array(type)) {
398 const void *p1 = co_val_addressof(type, v1);
399 const void *p2 = co_val_addressof(type, v2);
400
401 if (p1 == p2)
402 return 0;
403
404 if (!p1)
405 return -1;
406 if (!p2)
407 return 1;
408
409 size_t n1 = co_val_sizeof(type, v1);
410 size_t n2 = co_val_sizeof(type, v2);
411 switch (type) {
413 cmp = strncmp(p1, p2, MIN(n1, n2));
414 break;
416 cmp = memcmp(p1, p2, MIN(n1, n2));
417 break;
419 cmp = str16ncmp(p1, p2, MIN(n1, n2) / 2);
420 break;
422 cmp = memcmp(p1, p2, MIN(n1, n2));
423 break;
424 default:
425 // We can never get here.
426 return 0;
427 }
428 if (!cmp)
429 cmp = (n1 > n2) - (n1 < n2);
430 return cmp;
431 } else {
432 const union co_val *u1 = v1;
433 const union co_val *u2 = v2;
434 switch (type) {
435 case CO_DEFTYPE_BOOLEAN: return bool_cmp(v1, v2);
436 case CO_DEFTYPE_INTEGER8: return int8_cmp(v1, v2);
437 case CO_DEFTYPE_INTEGER16: return int16_cmp(v1, v2);
438 case CO_DEFTYPE_INTEGER32: return int32_cmp(v1, v2);
439 case CO_DEFTYPE_UNSIGNED8: return uint8_cmp(v1, v2);
440 case CO_DEFTYPE_UNSIGNED16: return uint16_cmp(v1, v2);
441 case CO_DEFTYPE_UNSIGNED32: return uint32_cmp(v1, v2);
442 case CO_DEFTYPE_REAL32: return flt_cmp(v1, v2);
444 cmp = uint32_cmp(&u1->t.ms, &u2->t.ms);
445 if (!cmp)
446 cmp = uint16_cmp(&u1->t.days, &u2->t.days);
447 return cmp;
449 cmp = uint32_cmp(&u1->td.ms, &u2->td.ms);
450 if (!cmp)
451 cmp = uint16_cmp(&u1->td.days, &u2->td.days);
452 return cmp;
453 case CO_DEFTYPE_INTEGER24: return int32_cmp(v1, v2);
454 case CO_DEFTYPE_REAL64: return dbl_cmp(v1, v2);
455 case CO_DEFTYPE_INTEGER40: return int64_cmp(v1, v2);
456 case CO_DEFTYPE_INTEGER48: return int64_cmp(v1, v2);
457 case CO_DEFTYPE_INTEGER56: return int64_cmp(v1, v2);
458 case CO_DEFTYPE_INTEGER64: return int64_cmp(v1, v2);
459 case CO_DEFTYPE_UNSIGNED24: return uint32_cmp(v1, v2);
460 case CO_DEFTYPE_UNSIGNED40: return uint64_cmp(v1, v2);
461 case CO_DEFTYPE_UNSIGNED48: return uint64_cmp(v1, v2);
462 case CO_DEFTYPE_UNSIGNED56: return uint64_cmp(v1, v2);
463 case CO_DEFTYPE_UNSIGNED64: return uint64_cmp(v1, v2);
464 default: return 0;
465 }
466 }
467}
468
469size_t
470co_val_read(co_unsigned16_t type, void *val, const uint8_t *begin,
471 const uint8_t *end)
472{
473 assert(begin || begin == end);
474 assert(!end || end >= begin);
475
476 size_t n = end - begin;
477
478 if (co_type_is_array(type)) {
479 if (val) {
480 switch (type) {
482 // clang-format off
484 (const char *)begin, n) == -1))
485 // clang-format on
486 return 0;
487 break;
489 // clang-format off
490 if (__unlikely(co_val_init_os(val, begin, n)
491 == -1))
492 // clang-format on
493 return 0;
494 break;
496 // clang-format off
497 if (__unlikely(co_val_init_us_n(val, NULL,
498 n / 2) == -1))
499 // clang-format on
500 return 0;
501 if (n) {
502 char16_t *us = *(char16_t **)val;
503 assert(us);
504 for (size_t i = 0; i + 1 < n; i += 2)
505 us[i / 2] = ldle_u16(begin + i);
506 }
507 break;
509 // clang-format off
510 if (__unlikely(co_val_init_dom(val, begin, n)
511 == -1))
512 // clang-format on
513 return 0;
514 break;
515 default:
516 // We can never get here.
517 return 0;
518 }
519 }
520 return n;
521 } else {
522 union co_val *u = val;
523 switch (type) {
525 if (__unlikely(n < 1))
526 return 0;
527 if (u)
528 u->b = !!*(const co_boolean_t *)begin;
529 return 1;
531 if (__unlikely(n < 1))
532 return 0;
533 if (u)
534 u->i8 = *(const co_integer8_t *)begin;
535 return 1;
537 if (__unlikely(n < 2))
538 return 0;
539 if (u)
540 u->i16 = ldle_i16(begin);
541 return 2;
543 if (__unlikely(n < 4))
544 return 0;
545 if (u)
546 u->i32 = ldle_i32(begin);
547 return 4;
549 if (__unlikely(n < 1))
550 return 0;
551 if (u)
552 u->u8 = *(const co_unsigned8_t *)begin;
553 return 1;
555 if (__unlikely(n < 2))
556 return 0;
557 if (u)
558 u->u16 = ldle_u16(begin);
559 return 2;
561 if (__unlikely(n < 4))
562 return 0;
563 if (u)
564 u->u32 = ldle_u32(begin);
565 return 4;
567 if (__unlikely(n < 4))
568 return 0;
569 if (u)
570 u->r32 = ldle_flt32(begin);
571 return 4;
574 if (__unlikely(n < 6))
575 return 0;
576 if (u) {
577 u->t.ms = ldle_u32(begin)
578 & UINT32_C(0x0fffffff);
579 u->t.days = ldle_u16(begin + 4);
580 }
581 return 6;
583 if (__unlikely(n < 3))
584 return 0;
585 if (u) {
586 co_unsigned24_t u24 = 0;
587 for (size_t i = 0; i < 3; i++)
588 u24 |= (co_unsigned24_t)*begin++
589 << 8 * i;
590 u->i24 = u24 > CO_INTEGER24_MAX
591 ? -(CO_UNSIGNED24_MAX + 1 - u24)
592 : u24;
593 }
594 return 3;
596 if (__unlikely(n < 8))
597 return 0;
598 if (u)
599 u->r64 = ldle_flt64(begin);
600 return 8;
602 if (__unlikely(n < 5))
603 return 0;
604 if (u) {
605 co_unsigned40_t u40 = 0;
606 for (size_t i = 0; i < 5; i++)
607 u40 |= (co_unsigned40_t)*begin++
608 << 8 * i;
609 u->i40 = u40 > CO_INTEGER40_MAX
610 ? -(CO_UNSIGNED40_MAX + 1 - u40)
611 : u40;
612 }
613 return 5;
615 if (__unlikely(n < 6))
616 return 0;
617 if (u) {
618 co_unsigned48_t u48 = 0;
619 for (size_t i = 0; i < 6; i++)
620 u48 |= (co_unsigned48_t)*begin++
621 << 8 * i;
622 u->i48 = u48 > CO_INTEGER48_MAX
623 ? -(CO_UNSIGNED48_MAX + 1 - u48)
624 : u48;
625 }
626 return 6;
628 if (__unlikely(n < 7))
629 return 0;
630 if (u) {
631 co_unsigned56_t u56 = 0;
632 for (size_t i = 0; i < 7; i++)
633 u56 |= (co_unsigned56_t)*begin++
634 << 8 * i;
635 u->i56 = u56 > CO_INTEGER56_MAX
636 ? -(CO_UNSIGNED56_MAX + 1 - u56)
637 : u56;
638 }
639 return 7;
641 if (__unlikely(n < 8))
642 return 0;
643 if (u)
644 u->i64 = ldle_i64(begin);
645 return 8;
647 if (__unlikely(n < 3))
648 return 0;
649 if (u) {
650 u->u24 = 0;
651 for (size_t i = 0; i < 3; i++)
652 u->u24 |= (co_unsigned24_t)*begin++
653 << 8 * i;
654 }
655 return 3;
657 if (__unlikely(n < 5))
658 return 0;
659 if (u) {
660 u->u40 = 0;
661 for (size_t i = 0; i < 5; i++)
662 u->u40 |= (co_unsigned40_t)*begin++
663 << 8 * i;
664 }
665 return 5;
667 if (__unlikely(n < 6))
668 return 0;
669 if (u) {
670 u->u48 = 0;
671 for (size_t i = 0; i < 6; i++)
672 u->u48 |= (co_unsigned48_t)*begin++
673 << 8 * i;
674 }
675 return 6;
677 if (__unlikely(n < 7))
678 return 0;
679 if (u) {
680 u->u56 = 0;
681 for (size_t i = 0; i < 7; i++)
682 u->u56 |= (co_unsigned56_t)*begin++
683 << 8 * i;
684 }
685 return 7;
687 if (__unlikely(n < 8))
688 return 0;
689 if (u)
690 u->u64 = ldle_u64(begin);
691 return 8;
692 default: set_errnum(ERRNUM_INVAL); return 0;
693 }
694 }
695}
696
697co_unsigned32_t
698co_val_read_sdo(co_unsigned16_t type, void *val, const void *ptr, size_t n)
699{
700 int errc = get_errc();
701 co_unsigned32_t ac = 0;
702
703 const uint8_t *begin = ptr;
704 const uint8_t *end = begin ? begin + n : NULL;
705 if (__unlikely(n && !co_val_read(type, val, begin, end))) {
706 // clang-format off
707 ac = get_errnum() == ERRNUM_NOMEM
710 // clang-format on
711 set_errc(errc);
712 }
713
714 return ac;
715}
716
717size_t
718co_val_write(co_unsigned16_t type, const void *val, uint8_t *begin,
719 uint8_t *end)
720{
721 assert(val);
722
723 if (co_type_is_array(type)) {
724 const void *ptr = co_val_addressof(type, val);
725 size_t n = co_val_sizeof(type, val);
726 if (!ptr || !n)
727 return 0;
728 if (begin && (!end || end - begin >= (ptrdiff_t)n)) {
729 switch (type) {
731 memcpy(begin, ptr, n);
732 break;
734 memcpy(begin, ptr, n);
735 break;
737 const char16_t *us = ptr;
738 for (size_t i = 0; i + 1 < n; i += 2)
739 stle_u16(begin + i, us[i / 2]);
740 break;
741 }
742 case CO_DEFTYPE_DOMAIN: memcpy(begin, ptr, n); break;
743 default:
744 // We can never get here.
745 return 0;
746 }
747 }
748 return n;
749 } else {
750 const union co_val *u = val;
751 switch (type) {
753 if (begin && (!end || end - begin >= 1))
754 *(co_boolean_t *)begin = !!u->b;
755 return 1;
757 if (begin && (!end || end - begin >= 1))
758 *(co_integer8_t *)begin = u->i8;
759 return 1;
761 if (begin && (!end || end - begin >= 2))
762 stle_i16(begin, u->i16);
763 return 2;
765 if (begin && (!end || end - begin >= 4))
766 stle_i32(begin, u->i32);
767 return 4;
769 if (begin && (!end || end - begin >= 1))
770 *(co_unsigned8_t *)begin = u->u8;
771 return 1;
773 if (begin && (!end || end - begin >= 2))
774 stle_u16(begin, u->u16);
775 return 2;
777 if (begin && (!end || end - begin >= 4))
778 stle_u32(begin, u->u32);
779 return 4;
781 if (begin && (!end || end - begin >= 4))
782 stle_flt32(begin, u->r32);
783 return 4;
786 if (begin && (!end || end - begin >= 6)) {
787 stle_u32(begin, u->t.ms & UINT32_C(0x0fffffff));
788 stle_u16(begin + 4, u->t.days);
789 }
790 return 6;
792 if (begin && (!end || end - begin >= 3)) {
793 co_unsigned24_t u24 = u->i24 < 0
794 ? CO_UNSIGNED24_MAX + 1 + u->i24
795 : (co_unsigned24_t)u->i24;
796 for (size_t i = 0; i < 3; i++)
797 *begin++ = (u24 >> 8 * i) & 0xff;
798 }
799 return 3;
801 if (begin && (!end || end - begin >= 8))
802 stle_flt64(begin, u->r64);
803 return 8;
805 if (begin && (!end || end - begin >= 5)) {
806 co_unsigned40_t u40 = u->i40 < 0
807 ? CO_UNSIGNED40_MAX + 1 + u->i40
808 : (co_unsigned40_t)u->i40;
809 for (size_t i = 0; i < 5; i++)
810 *begin++ = (u40 >> 8 * i) & 0xff;
811 }
812 return 5;
814 if (begin && (!end || end - begin >= 6)) {
815 co_unsigned48_t u48 = u->i48 < 0
816 ? CO_UNSIGNED48_MAX + 1 + u->i48
817 : (co_unsigned48_t)u->i48;
818 for (size_t i = 0; i < 6; i++)
819 *begin++ = (u48 >> 8 * i) & 0xff;
820 }
821 return 6;
823 if (begin && (!end || end - begin >= 7)) {
824 co_unsigned56_t u56 = u->i56 < 0
825 ? CO_UNSIGNED56_MAX + 1 + u->i56
826 : (co_unsigned56_t)u->i56;
827 for (size_t i = 0; i < 7; i++)
828 *begin++ = (u56 >> 8 * i) & 0xff;
829 }
830 return 7;
832 if (begin && (!end || end - begin >= 8))
833 stle_i64(begin, u->i64);
834 return 8;
836 if (begin && (!end || end - begin >= 3)) {
837 for (size_t i = 0; i < 3; i++)
838 *begin++ = (u->u24 >> 8 * i) & 0xff;
839 }
840 return 3;
842 if (begin && (!end || end - begin >= 5)) {
843 for (size_t i = 0; i < 5; i++)
844 *begin++ = (u->u40 >> 8 * i) & 0xff;
845 }
846 return 5;
848 if (begin && (!end || end - begin >= 6)) {
849 for (size_t i = 0; i < 6; i++)
850 *begin++ = (u->u48 >> 8 * i) & 0xff;
851 }
852 return 6;
854 if (begin && (!end || end - begin >= 7)) {
855 for (size_t i = 0; i < 7; i++)
856 *begin++ = (u->u56 >> 8 * i) & 0xff;
857 }
858 return 7;
860 if (begin && (!end || end - begin >= 8))
861 stle_u64(begin, u->u64);
862 return 8;
863 default: set_errnum(ERRNUM_INVAL); return 0;
864 }
865 }
866}
867
868size_t
869co_val_lex(co_unsigned16_t type, void *val, const char *begin, const char *end,
870 struct floc *at)
871{
872 assert(begin);
873 assert(!end || end >= begin);
874
875 // Prevent a previous range error from triggering a spurious warning.
876 if (get_errnum() == ERRNUM_RANGE)
877 set_errnum(0);
878
879 const char *cp = begin;
880 size_t chars = 0;
881
882 union co_val u;
883 switch (type) {
885 chars = lex_c99_u8(cp, end, NULL, &u.u8);
886 if (chars) {
887 cp += chars;
888 if (__unlikely(u.u8 > CO_BOOLEAN_MAX)) {
889 u.u8 = CO_BOOLEAN_MAX;
892 "boolean truth value overflow");
893 }
894 if (val)
895 *(co_boolean_t *)val = u.u8;
896 }
897 break;
899 chars = lex_c99_i8(cp, end, NULL, &u.i8);
900 if (chars) {
901 cp += chars;
902 // clang-format off
904 && u.i8 == INT8_MIN))
905 // clang-format on
907 "8-bit signed integer underflow");
908 // clang-format off
910 && u.i8 == INT8_MAX))
911 // clang-format on
913 "8-bit signed integer overflow");
914 if (val)
915 *(co_integer8_t *)val = u.i8;
916 }
917 break;
919 chars = lex_c99_i16(cp, end, NULL, &u.i16);
920 if (chars) {
921 cp += chars;
922 // clang-format off
924 && u.i16 == INT16_MIN))
925 // clang-format on
927 "16-bit signed integer underflow");
928 // clang-format off
930 && u.i16 == INT16_MAX))
931 // clang-format on
933 "16-bit signed integer overflow");
934 if (val)
935 *(co_integer16_t *)val = u.i16;
936 }
937 break;
939 chars = lex_c99_i32(cp, end, NULL, &u.i32);
940 if (chars) {
941 cp += chars;
942 // clang-format off
944 && u.i32 == INT32_MIN))
945 // clang-format on
947 "32-bit signed integer underflow");
948 // clang-format off
950 && u.i32 == INT32_MAX))
951 // clang-format on
953 "32-bit signed integer overflow");
954 if (val)
955 *(co_integer32_t *)val = u.i32;
956 }
957 break;
959 chars = lex_c99_u8(cp, end, NULL, &u.u8);
960 if (chars) {
961 cp += chars;
962 // clang-format off
964 && u.u8 == UINT8_MAX))
965 // clang-format on
967 "8-bit unsigned integer overflow");
968 if (val)
969 *(co_unsigned8_t *)val = u.u8;
970 }
971 break;
973 chars = lex_c99_u16(cp, end, NULL, &u.u16);
974 if (chars) {
975 cp += chars;
976 // clang-format off
978 && u.u16 == UINT16_MAX))
979 // clang-format on
981 "16-bit unsigned integer overflow");
982 if (val)
983 *(co_unsigned16_t *)val = u.u16;
984 }
985 break;
987 chars = lex_c99_u32(cp, end, NULL, &u.u32);
988 if (chars) {
989 cp += chars;
990 // clang-format off
992 && u.u32 == UINT32_MAX))
993 // clang-format on
995 "32-bit unsigned integer overflow");
996 if (val)
997 *(co_unsigned32_t *)val = u.u32;
998 }
999 break;
1000 case CO_DEFTYPE_REAL32:
1001 chars = lex_c99_u32(cp, end, NULL, &u.u32);
1002 if (chars) {
1003 cp += chars;
1004 // clang-format off
1006 && u.u32 == UINT32_MAX))
1007 // clang-format on
1009 "32-bit unsigned integer overflow");
1010 // clang-format off
1011 u.r32 = ((union {
1012 uint32_t u32;
1013 co_real32_t r32;
1014 }){ u.u32 }).r32;
1015 // clang-format on
1016 if (val)
1017 *(co_real32_t *)val = u.r32;
1018 }
1019 break;
1021 size_t n = 0;
1022 chars = lex_c99_str(cp, end, NULL, NULL, &n);
1023 if (val) {
1024 if (__unlikely(co_val_init_vs_n(val, 0, n) == -1)) {
1026 "unable to create value of type VISIBLE_STRING");
1027 return 0;
1028 }
1029 // Parse the characters.
1030 char *vs = *(void **)val;
1031 assert(vs);
1032 lex_c99_str(cp, end, NULL, vs, &n);
1033 }
1034 cp += chars;
1035 break;
1036 }
1038 // Count the number of hexadecimal digits.
1039 while ((!end || cp + chars < end)
1040 && isxdigit((unsigned char)cp[chars]))
1041 chars++;
1042 if (val) {
1043 // clang-format off
1044 if (__unlikely(co_val_init_os(val, NULL,
1045 (chars + 1) / 2) == -1)) {
1046 // clang-format on
1048 "unable to create value of type OCTET_STRING");
1049 return 0;
1050 }
1051 // Parse the octets.
1052 uint8_t *os = *(void **)val;
1053 assert(os);
1054 for (size_t i = 0; i < chars; i++) {
1055 if (i % 2) {
1056 *os <<= 4;
1057 *os++ |= ctox(cp[i]) & 0xf;
1058 } else {
1059 *os = ctox(cp[i]) & 0xf;
1060 }
1061 }
1062 }
1063 cp += chars;
1064 break;
1065 }
1067 size_t n = 0;
1068 chars = lex_base64(cp, end, NULL, NULL, &n);
1069 if (val) {
1070 // clang-format off
1071 if (__unlikely(co_val_init_us_n(val, NULL, n / 2)
1072 == -1)) {
1073 // clang-format on
1075 "unable to create value of type UNICODE_STRING");
1076 return 0;
1077 }
1078 // Parse the Unicode characters.
1079 char16_t *us = *(void **)val;
1080 assert(us);
1081 lex_base64(cp, end, NULL, us, &n);
1082 for (size_t i = 0; i + 1 < n; i += 2)
1083 us[i / 2] = letoh16(us[i / 2]);
1084 }
1085 cp += chars;
1086 break;
1087 }
1090 chars = lex_c99_u16(cp, end, NULL, &u.t.days);
1091 if (__unlikely(!chars))
1092 return 0;
1093 cp += chars;
1094 cp += lex_ctype(&isblank, cp, end, NULL);
1095 chars = lex_c99_u32(cp, end, NULL, &u.t.ms);
1096 if (__unlikely(!chars))
1097 return 0;
1098 cp += chars;
1099 if (val)
1100 *(co_time_of_day_t *)val = u.t;
1101 break;
1102 case CO_DEFTYPE_DOMAIN: {
1103 size_t n = 0;
1104 chars = lex_base64(cp, end, NULL, NULL, &n);
1105 if (val) {
1106 if (__unlikely(co_val_init_dom(val, NULL, n) == -1)) {
1108 "unable to create value of type DOMAIN");
1109 return 0;
1110 }
1111 void *dom = *(void **)val;
1112 assert(!n || dom);
1113 lex_base64(cp, end, NULL, dom, &n);
1114 }
1115 cp += chars;
1116 break;
1117 }
1119 chars = lex_c99_i32(cp, end, NULL, &u.i32);
1120 if (chars) {
1121 cp += chars;
1122 if (__unlikely(u.i32 < CO_INTEGER24_MIN)) {
1123 u.i32 = CO_INTEGER24_MIN;
1126 "24-bit signed integer underflow");
1127 } else if (__unlikely(u.i32 > CO_INTEGER24_MAX)) {
1128 u.i32 = CO_INTEGER24_MAX;
1131 "24-bit signed integer overflow");
1132 }
1133 if (val)
1134 *(co_integer24_t *)val = u.i32;
1135 }
1136 break;
1137 case CO_DEFTYPE_REAL64:
1138 chars = lex_c99_u64(cp, end, NULL, &u.u64);
1139 if (chars) {
1140 cp += chars;
1141 // clang-format off
1143 && u.u64 == UINT64_MAX))
1144 // clang-format on
1146 "64-bit unsigned integer overflow");
1147 // clang-format off
1148 u.r64 = ((union {
1149 uint64_t u64;
1150 co_real64_t r64;
1151 }){ u.u64 }).r64;
1152 // clang-format on
1153 if (val)
1154 *(co_real64_t *)val = u.r64;
1155 }
1156 break;
1158 chars = lex_c99_i64(cp, end, NULL, &u.i64);
1159 if (chars) {
1160 cp += chars;
1161 if (__unlikely(u.i64 < CO_INTEGER40_MIN)) {
1162 u.i64 = CO_INTEGER40_MIN;
1165 "40-bit signed integer underflow");
1166 } else if (__unlikely(u.i64 > CO_INTEGER40_MAX)) {
1167 u.i64 = CO_INTEGER40_MAX;
1170 "40-bit signed integer overflow");
1171 }
1172 if (val)
1173 *(co_integer40_t *)val = u.i64;
1174 }
1175 break;
1177 chars = lex_c99_i64(cp, end, NULL, &u.i64);
1178 if (chars) {
1179 cp += chars;
1180 if (__unlikely(u.i64 < CO_INTEGER48_MIN)) {
1181 u.i64 = CO_INTEGER48_MIN;
1184 "48-bit signed integer underflow");
1185 } else if (__unlikely(u.i64 > CO_INTEGER48_MAX)) {
1186 u.i64 = CO_INTEGER48_MAX;
1189 "48-bit signed integer overflow");
1190 }
1191 if (val)
1192 *(co_integer48_t *)val = u.i64;
1193 }
1194 break;
1196 chars = lex_c99_i64(cp, end, NULL, &u.i64);
1197 if (chars) {
1198 cp += chars;
1199 if (__unlikely(u.i64 < CO_INTEGER56_MIN)) {
1200 u.i64 = CO_INTEGER56_MIN;
1203 "56-bit signed integer underflow");
1204 } else if (__unlikely(u.i64 > CO_INTEGER56_MAX)) {
1205 u.i64 = CO_INTEGER56_MAX;
1208 "56-bit signed integer overflow");
1209 }
1210 if (val)
1211 *(co_integer56_t *)val = u.i64;
1212 }
1213 break;
1215 chars = lex_c99_i64(cp, end, NULL, &u.i64);
1216 if (chars) {
1217 cp += chars;
1218 // clang-format off
1220 && u.i64 == INT64_MIN))
1221 // clang-format on
1223 "64-bit signed integer underflow");
1224 // clang-format off
1225 else if (__unlikely(get_errnum() == ERRNUM_RANGE
1226 && u.i64 == INT64_MAX))
1227 // clang-format on
1229 "64-bit signed integer overflow");
1230 if (val)
1231 *(co_integer64_t *)val = u.i64;
1232 }
1233 break;
1235 chars = lex_c99_u32(cp, end, NULL, &u.u32);
1236 if (chars) {
1237 cp += chars;
1238 if (__unlikely(u.u32 > CO_UNSIGNED24_MAX)) {
1239 u.u32 = CO_UNSIGNED24_MAX;
1242 "24-bit unsigned integer overflow");
1243 }
1244 if (val)
1245 *(co_unsigned24_t *)val = u.u32;
1246 }
1247 break;
1249 chars = lex_c99_u64(cp, end, NULL, &u.u64);
1250 if (chars) {
1251 cp += chars;
1252 if (__unlikely(u.u64 > CO_UNSIGNED40_MAX)) {
1253 u.u64 = CO_UNSIGNED40_MAX;
1256 "40-bit unsigned integer overflow");
1257 }
1258 if (val)
1259 *(co_unsigned40_t *)val = u.u64;
1260 }
1261 break;
1263 chars = lex_c99_u64(cp, end, NULL, &u.u64);
1264 if (chars) {
1265 cp += chars;
1266 if (__unlikely(u.u64 > CO_UNSIGNED48_MAX)) {
1267 u.u64 = CO_UNSIGNED48_MAX;
1270 "48-bit unsigned integer overflow");
1271 }
1272 if (val)
1273 *(co_unsigned48_t *)val = u.u64;
1274 }
1275 break;
1277 chars = lex_c99_u64(cp, end, NULL, &u.u64);
1278 if (chars) {
1279 cp += chars;
1280 if (__unlikely(u.u64 > CO_UNSIGNED56_MAX)) {
1281 u.u64 = CO_UNSIGNED56_MAX;
1284 "56-bit unsigned integer overflow");
1285 }
1286 if (val)
1287 *(co_unsigned56_t *)val = u.u64;
1288 }
1289 break;
1291 chars = lex_c99_u64(cp, end, NULL, &u.u64);
1292 if (chars) {
1293 cp += chars;
1294 // clang-format off
1296 && u.u64 == UINT64_MAX))
1297 // clang-format on
1299 "64-bit unsigned integer overflow");
1300 if (val)
1301 *(co_unsigned64_t *)val = u.u64;
1302 }
1303 break;
1304 default:
1305 diag_if(DIAG_ERROR, 0, at, "cannot parse value of type 0x%04X",
1306 type);
1307 break;
1308 }
1309
1310 return floc_lex(at, begin, cp);
1311}
1312
1313size_t
1314co_val_print(co_unsigned16_t type, const void *val, char **pbegin, char *end)
1315{
1316 if (co_type_is_array(type)) {
1317 const void *ptr = co_val_addressof(type, val);
1318 size_t n = co_val_sizeof(type, val);
1319 if (!ptr || !n)
1320 return 0;
1321 switch (type) {
1323 return print_c99_str(pbegin, end, ptr, n);
1325 size_t chars = 0;
1326 for (const uint8_t *os = ptr; n; n--, os++) {
1327 chars += print_char(
1328 pbegin, end, xtoc(*os >> 4));
1329 chars += print_char(pbegin, end, xtoc(*os));
1330 }
1331 return chars;
1332 }
1334 char16_t *us = NULL;
1335 if (__unlikely(!co_val_copy(type, &us, val) && !us))
1336 return 0;
1337 assert(us);
1338 for (size_t i = 0; i + 1 < n; i += 2)
1339 us[i / 2] = htole16(us[i / 2]);
1340 size_t chars = print_base64(pbegin, end, us, n);
1341 co_array_free(&us);
1342 return chars;
1343 }
1344 case CO_DEFTYPE_DOMAIN:
1345 return print_base64(pbegin, end, ptr, n);
1346 default:
1347 // We can never get here.
1348 return 0;
1349 }
1350 } else {
1351 const union co_val *u = val;
1352 assert(u);
1353 switch (type) {
1354 case CO_DEFTYPE_BOOLEAN:
1355 return print_c99_u8(pbegin, end, !!u->b);
1357 return print_c99_i8(pbegin, end, u->i8);
1359 return print_c99_i16(pbegin, end, u->i16);
1361 return print_c99_i32(pbegin, end, u->i32);
1363 return print_fmt(pbegin, end, "0x%02" PRIx8, u->u8);
1365 return print_fmt(pbegin, end, "0x%04" PRIx16, u->u16);
1367 return print_fmt(pbegin, end, "0x%08" PRIx32, u->u32);
1368 case CO_DEFTYPE_REAL32:
1369 return print_c99_u32(pbegin, end, u->u32);
1371 case CO_DEFTYPE_TIME_DIFF: {
1372 size_t chars = 0;
1373 chars += print_c99_u16(pbegin, end, u->t.days);
1374 chars += print_char(pbegin, end, ' ');
1375 chars += print_c99_u32(pbegin, end, u->t.ms);
1376 return chars;
1377 }
1379 return print_c99_i32(pbegin, end, u->i24);
1380 case CO_DEFTYPE_REAL64:
1381 return print_fmt(pbegin, end, "0x%016" PRIx64, u->u64);
1383 return print_c99_i64(pbegin, end, u->i40);
1385 return print_c99_i64(pbegin, end, u->i48);
1387 return print_c99_i64(pbegin, end, u->i56);
1389 return print_c99_i64(pbegin, end, u->i64);
1391 return print_fmt(pbegin, end, "0x%06" PRIx32, u->u24);
1393 return print_fmt(pbegin, end, "0x%010" PRIx64, u->u40);
1395 return print_fmt(pbegin, end, "0x%012" PRIx64, u->u48);
1397 return print_fmt(pbegin, end, "0x%014" PRIx64, u->u56);
1399 return print_fmt(pbegin, end, "0x%016" PRIx64, u->u64);
1400 default: set_errnum(ERRNUM_INVAL); return 0;
1401 }
1402 }
1403}
1404
1405static int
1406co_array_alloc(void *val, size_t size)
1407{
1408 assert(val);
1409
1410 if (size) {
1411 char *ptr = calloc(1, CO_ARRAY_OFFSET + size);
1412 if (__unlikely(!ptr)) {
1413 set_errc(errno2c(errno));
1414 return -1;
1415 }
1416 *(char **)val = ptr + CO_ARRAY_OFFSET;
1417 } else {
1418 *(char **)val = NULL;
1419 }
1420
1421 return 0;
1422}
1423
1424static void
1425co_array_free(void *val)
1426{
1427 assert(val);
1428
1429 char *ptr = *(char **)val;
1430 if (ptr)
1431 free(ptr - CO_ARRAY_OFFSET);
1432}
1433
1434static void
1435co_array_init(void *val, size_t size)
1436{
1437 assert(val);
1438
1439 char *ptr = *(char **)val;
1440 assert(!size || ptr);
1441 if (ptr)
1442 *(size_t *)(ptr - CO_ARRAY_OFFSET) = size;
1443}
1444
1445static void
1446co_array_fini(void *val)
1447{
1448 assert(val);
1449
1450 *(char **)val = NULL;
1451}
1452
1453static size_t
1454co_array_sizeof(const void *val)
1455{
1456 assert(val);
1457
1458 const char *ptr = *(const char **)val;
1459 return ptr ? *(const size_t *)(ptr - CO_ARRAY_OFFSET) : 0;
1460}
1461
1462static size_t
1463str16len(const char16_t *s)
1464{
1465 const char16_t *cp = s;
1466 for (; *cp; cp++)
1467 ;
1468 return cp - s;
1469}
1470
1471static char16_t *
1472str16ncpy(char16_t *dst, const char16_t *src, size_t n)
1473{
1474 char16_t *cp = dst;
1475 for (; n && *src; n--)
1476 *cp++ = *src++;
1477 while (n--)
1478 *cp++ = 0;
1479
1480 return dst;
1481}
1482
1483static int
1484str16ncmp(const char16_t *s1, const char16_t *s2, size_t n)
1485{
1486 int result = 0;
1487 while (n-- && !(result = *s1 - *s2++) && *s1++)
1488 ;
1489 return result;
1490}
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:54
@ DIAG_WARNING
A warning.
Definition: diag.h:47
@ DIAG_ERROR
An error.
Definition: diag.h:49
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:190
This header file is part of the utilities library; it contains the byte order (endianness) function d...
uint_least16_t htole16(uint_least16_t x)
Converts a 16-bit unsigned integer from host to little-endian byte order.
Definition: endian.h:337
void stle_u16(void *ptr, uint_least16_t x)
Stores a 16-bit unsigned integer in little-endian byte order.
Definition: endian.h:480
void stle_i32(void *ptr, int_least32_t x)
Stores a 32-bit signed integer in little-endian byte order.
Definition: endian.h:522
int_least32_t ldle_i32(const void *ptr)
Loads a 32-bit signed integer in little-endian byte order.
Definition: endian.h:528
int_least16_t ldle_i16(const void *ptr)
Loads a 16-bit signed integer in little-endian byte order.
Definition: endian.h:474
int_least64_t ldle_i64(const void *ptr)
Loads a 64-bit signed integer in little-endian byte order.
Definition: endian.h:582
void stle_u64(void *ptr, uint_least64_t x)
Stores a 64-bit unsigned integer in little-endian byte order.
Definition: endian.h:588
void stle_u32(void *ptr, uint_least32_t x)
Stores a 32-bit unsigned integer in little-endian byte order.
Definition: endian.h:534
uint_least32_t ldle_u32(const void *ptr)
Loads a 32-bit unsigned integer in little-endian byte order.
Definition: endian.h:541
void stle_i64(void *ptr, int_least64_t x)
Stores a 64-bit signed integer in little-endian byte order.
Definition: endian.h:576
void stle_i16(void *ptr, int_least16_t x)
Stores a 16-bit signed integer in little-endian byte order.
Definition: endian.h:468
uint_least16_t letoh16(uint_least16_t x)
Converts a 16-bit unsigned integer from little-endian to host byte order.
Definition: endian.h:350
uint_least64_t ldle_u64(const void *ptr)
Loads a 64-bit unsigned integer in little-endian byte order.
Definition: endian.h:595
uint_least16_t ldle_u16(const void *ptr)
Loads a 16-bit unsigned integer in little-endian byte order.
Definition: endian.h:487
@ ERRNUM_RANGE
Result too large.
Definition: errnum.h:215
@ ERRNUM_NOMEM
Not enough space.
Definition: errnum.h:169
@ ERRNUM_INVAL
Invalid argument.
Definition: errnum.h:129
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:947
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:957
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
Definition: errnum.c:43
errnum_t get_errnum(void)
Returns the last (thread-specific) platform-independent error number set by a system call or library ...
Definition: errnum.h:369
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:375
#define __unlikely(x)
Indicates to the compiler that the expression is most-likely false.
Definition: features.h:286
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:449
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:51
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:544
size_t lex_base64(const char *begin, const char *end, struct floc *at, void *ptr, size_t *pn)
Lexwes and decodes the Base64 representation of binary data from a memory buffer.
Definition: lex.c:656
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:247
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:425
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:582
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:605
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:473
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:563
int ctox(int c)
Returns the hexadecimal digit corresponding to the character c.
Definition: lex.h:332
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:505
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:238
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:190
size_t print_char(char **pbegin, char *end, int c)
Prints a single character to a memory buffer.
Definition: print.h:284
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:246
int xtoc(int i)
Returns the character corresponding to the hexadecimal digit i.
Definition: print.h:263
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:240
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:248
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:258
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:239
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:244
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:247
size_t print_fmt(char **pbegin, char *end, const char *format,...)
Prints a formatted string to a memory buffer.
Definition: print.c:40
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....
A location in a text file.
Definition: diag.h:31
#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 0 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
A union of the CANopen static data types.
Definition: val.h:163
size_t co_val_write(co_unsigned16_t type, const void *val, uint8_t *begin, uint8_t *end)
Writes a value of the specified data type to a memory buffer.
Definition: val.c:718
int co_val_init(co_unsigned16_t type, void *val)
Initializes a value of the specified data type to zero.
Definition: val.c:120
size_t co_val_move(co_unsigned16_t type, void *dst, void *src)
Moves one value to another.
Definition: val.c:371
static size_t str16len(const char16_t *s)
Returns the number of (16-bit) Unicode characters, excluding the terminating null bytes,...
Definition: val.c:1463
static char16_t * str16ncpy(char16_t *dst, const char16_t *src, size_t n)
Copies at most n (16-bit) Unicode characters from the string at src to dst.
Definition: val.c:1472
int co_val_init_os(uint8_t **val, const uint8_t *os, size_t n)
Initializes an array of octets (CO_DEFTYPE_OCTET_STRING).
Definition: val.c:203
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:284
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:254
size_t co_val_read(co_unsigned16_t type, void *val, const uint8_t *begin, const uint8_t *end)
Reads a value of the specified data type from a memory buffer.
Definition: val.c:470
static int str16ncmp(const char16_t *s1, const char16_t *s2, size_t n)
Compares two (16-bit) Unicode strings.
Definition: val.c:1484
size_t co_val_copy(co_unsigned16_t type, void *dst, const void *src)
Copies one value to another.
Definition: val.c:333
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:293
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:235
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:184
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:222
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:386
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:698
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:137
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:1314
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:306
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
Definition: val.c:273
int co_val_init_vs(char **val, const char *vs)
Initializes an array of visible characters (CO_DEFTYPE_VISIBLE_STRING).
Definition: val.c:171
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:869
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:154
This header file is part of the CANopen library; it contains the CANopen value declarations.
#define CO_INTEGER24_MAX
The maximum value of a 24-bit signed integer (encoded as an int32_t).
Definition: val.h:100
#define CO_INTEGER48_MAX
The maximum value of a 48-bit signed integer (encoded as an int64_t).
Definition: val.h:118
#define CO_INTEGER24_MIN
The minimum value of a 24-bit signed integer (encoded as an int32_t).
Definition: val.h:97
#define CO_BOOLEAN_MAX
The maximum value of a boolean truth value (true).
Definition: val.h:34
#define CO_INTEGER40_MAX
The maximum value of a 40-bit signed integer (encoded as an int64_t).
Definition: val.h:112
#define CO_UNSIGNED40_MAX
The maximum value of a 40-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:142
#define CO_UNSIGNED56_MAX
The maximum value of a 56-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:154
#define CO_INTEGER48_MIN
The minimum value of a 48-bit signed integer (encoded as an int64_t).
Definition: val.h:115
#define CO_UNSIGNED48_MAX
The maximum value of a 48-bit unsigned integer (encoded as a uint64_t).
Definition: val.h:148
#define CO_INTEGER56_MAX
The maximum value of a 56-bit signed integer (encoded as an int64_t).
Definition: val.h:124
#define CO_INTEGER40_MIN
The minimum value of a 40-bit signed integer (encoded as an int64_t).
Definition: val.h:109
#define CO_UNSIGNED24_MAX
The maximum value of a 24-bit unsigned integer (encoded as a uint32_t).
Definition: val.h:136
#define CO_INTEGER56_MIN
The minimum value of a 56-bit signed integer (encoded as an int64_t).
Definition: val.h:121