AMU Library 3.0
C/C++ library for communicating with AMU (Aerospace Measurement Unit) devices
Loading...
Searching...
No Matches
utils.c
Go to the documentation of this file.
1/*-
2 * Copyright (c) 2013 Jan Breuer
3 * Richard.hmm
4 * Copyright (c) 2012 Jan Breuer
5 *
6 * All Rights Reserved
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
38
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <ctype.h>
43#include <math.h>
44
45#include "utils_private.h"
46#include "utils.h"
47
48static size_t patternSeparatorShortPos(const char * pattern, size_t len);
49static size_t patternSeparatorPos(const char * pattern, size_t len);
50static size_t cmdSeparatorPos(const char * cmd, size_t len);
51
59char * strnpbrk(const char *str, size_t size, const char *set) {
60 const char *scanp;
61 long c, sc;
62 const char * strend = str + size;
63
64 while ((strend != str) && ((c = *str++) != 0)) {
65 for (scanp = set; (sc = *scanp++) != '\0';)
66 if (sc == c)
67 return ((char *) (str - 1));
68 }
69 return (NULL);
70}
71
81size_t UInt32ToStrBaseSign(uint32_t val, char * str, size_t len, int8_t base, scpi_bool_t sign) {
82 const char digits[] = "0123456789ABCDEF";
83
84#define ADD_CHAR(c) if (pos < len) str[pos++] = (c)
85 uint32_t x = 0;
86 int_fast8_t digit;
87 size_t pos = 0;
88 uint32_t uval = val;
89
90 if (uval == 0) {
91 ADD_CHAR('0');
92 } else {
93
94 switch (base) {
95 case 2:
96 x = 0x80000000L;
97 break;
98 case 8:
99 x = 0x40000000L;
100 break;
101 default:
102 case 10:
103 base = 10;
104 x = 1000000000L;
105 break;
106 case 16:
107 x = 0x10000000L;
108 break;
109 }
110
111 /* add sign for numbers in base 10 */
112 if (sign && ((int32_t) val < 0) && (base == 10)) {
113 uval = -val;
114 ADD_CHAR('-');
115 }
116
117 /* remove leading zeros */
118 while ((uval / x) == 0) {
119 x /= base;
120 }
121
122 do {
123 digit = (uint8_t) (uval / x);
124 ADD_CHAR(digits[digit]);
125 uval -= digit * x;
126 x /= base;
127 } while (x && (pos < len));
128 }
129
130 if (pos < len) str[pos] = 0;
131 return pos;
132#undef ADD_CHAR
133}
134
142size_t SCPI_Int32ToStr(int32_t val, char * str, size_t len) {
143 return UInt32ToStrBaseSign((uint32_t) val, str, len, 10, TRUE);
144}
145
154size_t SCPI_UInt32ToStrBase(uint32_t val, char * str, size_t len, int8_t base) {
155 return UInt32ToStrBaseSign(val, str, len, base, FALSE);
156}
157
167size_t UInt64ToStrBaseSign(uint64_t val, char * str, size_t len, int8_t base, scpi_bool_t sign) {
168 const char digits[] = "0123456789ABCDEF";
169
170#define ADD_CHAR(c) if (pos < len) str[pos++] = (c)
171 uint64_t x = 0;
172 int_fast8_t digit;
173 size_t pos = 0;
174 uint64_t uval = val;
175
176 if (uval == 0) {
177 ADD_CHAR('0');
178 } else {
179
180 switch (base) {
181 case 2:
182 x = 0x8000000000000000ULL;
183 break;
184 case 8:
185 x = 0x8000000000000000ULL;
186 break;
187 default:
188 case 10:
189 x = 10000000000000000000ULL;
190 base = 10;
191 break;
192 case 16:
193 x = 0x1000000000000000ULL;
194 break;
195 }
196
197 /* add sign for numbers in base 10 */
198 if (sign && ((int64_t) val < 0) && (base == 10)) {
199 uval = -val;
200 ADD_CHAR('-');
201 }
202
203 /* remove leading zeros */
204 while ((uval / x) == 0) {
205 x /= base;
206 }
207
208 do {
209 digit = (uint8_t) (uval / x);
210 ADD_CHAR(digits[digit]);
211 uval -= digit * x;
212 x /= base;
213 } while (x && (pos < len));
214 }
215
216 if (pos < len) str[pos] = 0;
217 return pos;
218#undef ADD_CHAR
219}
220
228size_t SCPI_Int64ToStr(int64_t val, char * str, size_t len) {
229 return UInt64ToStrBaseSign((uint64_t) val, str, len, 10, TRUE);
230}
231
240size_t SCPI_UInt64ToStrBase(uint64_t val, char * str, size_t len, int8_t base) {
241 return UInt64ToStrBaseSign(val, str, len, base, FALSE);
242}
243
251size_t SCPI_FloatToStr(float val, char * str, size_t len) {
252 SCPIDEFINE_floatToStr(val, str, len);
253 return strlen(str);
254}
255
263size_t SCPI_DoubleToStr(double val, char * str, size_t len) {
264 SCPIDEFINE_doubleToStr(val, str, len);
265 return strlen(str);
266}
267
274size_t strBaseToInt32(const char * str, int32_t * val, int8_t base) {
275 char * endptr;
276 *val = strtol(str, &endptr, base);
277 return endptr - str;
278}
279
286size_t strBaseToUInt32(const char * str, uint32_t * val, int8_t base) {
287 char * endptr;
288 *val = strtoul(str, &endptr, base);
289 return endptr - str;
290}
291
298size_t strBaseToInt64(const char * str, int64_t * val, int8_t base) {
299 char * endptr;
300 *val = SCPIDEFINE_strtoll(str, &endptr, base);
301 return endptr - str;
302}
303
310size_t strBaseToUInt64(const char * str, uint64_t * val, int8_t base) {
311 char * endptr;
312 *val = SCPIDEFINE_strtoull(str, &endptr, base);
313 return endptr - str;
314}
315
322size_t strToFloat(const char * str, float * val) {
323 char * endptr;
324 *val = SCPIDEFINE_strtof(str, &endptr);
325 return endptr - str;
326}
327
334size_t strToDouble(const char * str, double * val) {
335 char * endptr;
336 *val = strtod(str, &endptr);
337 return endptr - str;
338}
339
348scpi_bool_t compareStr(const char * str1, size_t len1, const char * str2, size_t len2) {
349 if (len1 != len2) {
350 return FALSE;
351 }
352
353 if (SCPIDEFINE_strncasecmp(str1, str2, len2) == 0) {
354 return TRUE;
355 }
356
357 return FALSE;
358}
359
368scpi_bool_t compareStrAndNum(const char * str1, size_t len1, const char * str2, size_t len2, int32_t * num) {
369 scpi_bool_t result = FALSE;
370 size_t i;
371
372 if (len2 < len1) {
373 return FALSE;
374 }
375
376 if (SCPIDEFINE_strncasecmp(str1, str2, len1) == 0) {
377 result = TRUE;
378
379 if (num) {
380 if (len1 == len2) {
381 /* *num = 1; */
382 } else {
383 int32_t tmpNum;
384 i = len1 + strBaseToInt32(str2 + len1, &tmpNum, 10);
385 if (i != len2) {
386 result = FALSE;
387 } else {
388 *num = tmpNum;
389 }
390 }
391 } else {
392 for (i = len1; i < len2; i++) {
393 if (!isdigit((int) str2[i])) {
394 result = FALSE;
395 break;
396 }
397 }
398 }
399 }
400
401 return result;
402}
403
410size_t skipWhitespace(const char * cmd, size_t len) {
411 size_t i;
412 for (i = 0; i < len; i++) {
413 if (!isspace((unsigned char) cmd[i])) {
414 return i;
415 }
416 }
417 return len;
418}
419
427static size_t patternSeparatorShortPos(const char * pattern, size_t len) {
428 size_t i;
429 for (i = 0; (i < len) && pattern[i]; i++) {
430 if (islower((unsigned char) pattern[i])) {
431 return i;
432 }
433 }
434 return i;
435}
436
443static size_t patternSeparatorPos(const char * pattern, size_t len) {
444
445 char * separator = strnpbrk(pattern, len, "?:[]");
446 if (separator == NULL) {
447 return len;
448 } else {
449 return separator - pattern;
450 }
451}
452
459static size_t cmdSeparatorPos(const char * cmd, size_t len) {
460 char * separator = strnpbrk(cmd, len, ":?");
461 size_t result;
462 if (separator == NULL) {
463 result = len;
464 } else {
465 result = separator - cmd;
466 }
467
468 return result;
469}
470
479scpi_bool_t matchPattern(const char * pattern, size_t pattern_len, const char * str, size_t str_len, int32_t * num) {
480 int pattern_sep_pos_short;
481
482 if ((pattern_len > 0) && pattern[pattern_len - 1] == '#') {
483 size_t new_pattern_len = pattern_len - 1;
484
485 pattern_sep_pos_short = patternSeparatorShortPos(pattern, new_pattern_len);
486
487 return compareStrAndNum(pattern, new_pattern_len, str, str_len, num) ||
488 compareStrAndNum(pattern, pattern_sep_pos_short, str, str_len, num);
489 } else {
490
491 pattern_sep_pos_short = patternSeparatorShortPos(pattern, pattern_len);
492
493 return compareStr(pattern, pattern_len, str, str_len) ||
494 compareStr(pattern, pattern_sep_pos_short, str, str_len);
495 }
496}
497
505scpi_bool_t matchCommand(const char * pattern, const char * cmd, size_t len, int32_t *numbers, size_t numbers_len, int32_t default_value, bool *query) {
506#define SKIP_PATTERN(n) do {pattern_ptr += (n); pattern_len -= (n);} while(0)
507#define SKIP_CMD(n) do {cmd_ptr += (n); cmd_len -= (n);} while(0)
508
509 scpi_bool_t result = FALSE;
510 int brackets = 0;
511 int cmd_sep_pos = 0;
512
513 size_t numbers_idx = 0;
514 int32_t *number_ptr = NULL;
515
516 const char * pattern_ptr = pattern;
517 int pattern_len = strlen(pattern);
518
519 const char * cmd_ptr = cmd;
520 size_t cmd_len = SCPIDEFINE_strnlen(cmd, len);
521
522 /* both commands are query commands? */
523 if (pattern_ptr[pattern_len - 1] == '?') {
524 if (cmd_ptr[cmd_len - 1] == '?') {
525 cmd_len -= 1;
526 pattern_len -= 1;
527 *query = true;
528 }
529 else
530 return FALSE;
531 }
532
533 /* now support optional keywords in pattern style, e.g. [:MEASure]:VOLTage:DC? */
534 if (pattern_ptr[0] == '[') { /* skip first '[' */
535 SKIP_PATTERN(1);
536 brackets++;
537 }
538 if (pattern_ptr[0] == ':') { /* skip first ':' */
539 SKIP_PATTERN(1);
540 }
541
542 if (cmd_ptr[0] == ':') {
543 /* handle errornouse ":*IDN?" */
544 if (cmd_len >= 2) {
545 if (cmd_ptr[1] != '*') {
546 SKIP_CMD(1);
547 } else {
548 return FALSE;
549 }
550 }
551 }
552
553 while (1) {
554 int pattern_sep_pos = patternSeparatorPos(pattern_ptr, pattern_len);
555
556 cmd_sep_pos = cmdSeparatorPos(cmd_ptr, cmd_len);
557
558 if ((pattern_sep_pos > 0) && pattern_ptr[pattern_sep_pos - 1] == '#') {
559 if (numbers && (numbers_idx < numbers_len)) {
560 number_ptr = numbers + numbers_idx;
561 *number_ptr = default_value; /* default value */
562 } else {
563 number_ptr = NULL;
564 }
565 numbers_idx++;
566 } else {
567 number_ptr = NULL;
568 }
569
570 if (matchPattern(pattern_ptr, pattern_sep_pos, cmd_ptr, cmd_sep_pos, number_ptr)) {
571 SKIP_PATTERN(pattern_sep_pos);
572 SKIP_CMD(cmd_sep_pos);
573 result = TRUE;
574
575 /* command is complete */
576 if ((pattern_len == 0) && (cmd_len == 0)) {
577 break;
578 }
579
580 /* pattern complete, but command not */
581 if ((pattern_len == 0) && (cmd_len > 0)) {
582 result = FALSE;
583 break;
584 }
585
586 /* command complete, but pattern not */
587 if (cmd_len == 0) {
588 /* verify all subsequent pattern parts are also optional */
589 while (pattern_len) {
590 pattern_sep_pos = patternSeparatorPos(pattern_ptr, pattern_len);
591 switch (pattern_ptr[pattern_sep_pos]) {
592 case '[':
593 brackets++;
594 break;
595 case ']':
596 brackets--;
597 break;
598 default:
599 break;
600 }
601 SKIP_PATTERN(pattern_sep_pos + 1);
602 if (brackets == 0) {
603 if ((pattern_len > 0) && (pattern_ptr[0] == '[')) {
604 continue;
605 } else {
606 break;
607 }
608 }
609 }
610 if (pattern_len != 0) {
611 result = FALSE;
612 }
613 break; /* exist optional keyword, command is complete */
614 }
615
616 /* both command and patter contains command separator at this position */
617 if ((pattern_len > 0)
618 && ((pattern_ptr[0] == cmd_ptr[0])
619 && (pattern_ptr[0] == ':'))) {
620 SKIP_PATTERN(1);
621 SKIP_CMD(1);
622 } else if ((pattern_len > 1)
623 && (pattern_ptr[1] == cmd_ptr[0])
624 && (pattern_ptr[0] == '[')
625 && (pattern_ptr[1] == ':')) {
626 SKIP_PATTERN(2); /* for skip '[' in "[:" */
627 SKIP_CMD(1);
628 brackets++;
629 } else if ((pattern_len > 1)
630 && (pattern_ptr[1] == cmd_ptr[0])
631 && (pattern_ptr[0] == ']')
632 && (pattern_ptr[1] == ':')) {
633 SKIP_PATTERN(2); /* for skip ']' in "]:" */
634 SKIP_CMD(1);
635 brackets--;
636 } else if ((pattern_len > 2)
637 && (pattern_ptr[2] == cmd_ptr[0])
638 && (pattern_ptr[0] == ']')
639 && (pattern_ptr[1] == '[')
640 && (pattern_ptr[2] == ':')) {
641 SKIP_PATTERN(3); /* for skip '][' in "][:" */
642 SKIP_CMD(1);
643 /* brackets++; */
644 /* brackets--; */
645 } else if ((pattern_len > 2)
646 && (pattern_ptr[1] == cmd_ptr[0])
647 && (pattern_ptr[0] == '[')
648 && (pattern_ptr[1] == '?')
649 && (pattern_ptr[2] == ']')) {
650 *query = true;
651 SKIP_PATTERN(3);
652 SKIP_CMD(1);
653 } else {
654 result = FALSE;
655 break;
656 }
657 } else {
658 SKIP_PATTERN(pattern_sep_pos);
659 if ((pattern_ptr[0] == ']') && (pattern_ptr[1] == ':')) {
660 SKIP_PATTERN(2); /* for skip ']' in "]:" , pattern_ptr continue, while cmd_ptr remain unchanged */
661 brackets--;
662 } else if ((pattern_len > 2) && (pattern_ptr[0] == ']')
663 && (pattern_ptr[1] == '[')
664 && (pattern_ptr[2] == ':')) {
665 SKIP_PATTERN(3); /* for skip ']' in "][:" , pattern_ptr continue, while cmd_ptr remain unchanged */
666 /* brackets++; */
667 /* brackets--; */
668 } else {
669 result = FALSE;
670 break;
671 }
672 }
673 }
674
675 return result;
676#undef SKIP_PATTERN
677#undef SKIP_CMD
678}
679
688scpi_bool_t composeCompoundCommand(const scpi_token_t * prev, scpi_token_t * current) {
689 size_t i;
690
691 /* Invalid input */
692 if (current == NULL || current->ptr == NULL || current->len == 0)
693 return FALSE;
694
695 /* no previous command - nothing to do*/
696 if (prev->ptr == NULL || prev->len == 0)
697 return TRUE;
698
699 /* Common command or command root - nothing to do */
700 if (current->ptr[0] == '*' || current->ptr[0] == ':')
701 return TRUE;
702
703 /* Previous command was common command - nothing to do */
704 if (prev->ptr[0] == '*')
705 return TRUE;
706
707 /* Find last occurrence of ':' */
708 for (i = prev->len; i > 0; i--) {
709 if (prev->ptr[i - 1] == ':') {
710 break;
711 }
712 }
713
714 /* Previous command was simple command - nothing to do*/
715 if (i == 0)
716 return TRUE;
717
718 current->ptr -= i;
719 current->len += i;
720 memmove(current->ptr, prev->ptr, i);
721 return TRUE;
722}
723
724
725
726#if !HAVE_STRNLEN
727/* use FreeBSD strnlen */
728
729/*-
730 * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
731 * All rights reserved.
732 */
733size_t
734BSD_strnlen(const char *s, size_t maxlen) {
735 size_t len;
736
737 for (len = 0; len < maxlen; len++, s++) {
738 if (!*s)
739 break;
740 }
741 return (len);
742}
743#endif
744
745#if !HAVE_STRNCASECMP && !HAVE_STRNICMP
746
747int OUR_strncasecmp(const char *s1, const char *s2, size_t n) {
748 unsigned char c1, c2;
749
750 for (; n != 0; n--) {
751 c1 = tolower((unsigned char) *s1++);
752 c2 = tolower((unsigned char) *s2++);
753 if (c1 != c2) {
754 return c1 - c2;
755 }
756 if (c1 == '\0') {
757 return 0;
758 }
759 }
760 return 0;
761}
762#endif
763
764#if USE_MEMORY_ALLOCATION_FREE && !HAVE_STRNDUP
765char *OUR_strndup(const char *s, size_t n) {
766 size_t len = SCPIDEFINE_strnlen(s, n);
767 char * result = malloc(len + 1);
768 if (!result) {
769 return NULL;
770 }
771 memcpy(result, s, len);
772 result[len] = '\0';
773 return result;
774}
775#endif
776
777#if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE
778
785void scpiheap_init(scpi_error_info_heap_t * heap, char * error_info_heap, size_t error_info_heap_length)
786{
787 heap->data = error_info_heap;
788 heap->wr = 0;
789 heap->size = error_info_heap_length;
790 heap->count = heap->size;
791 memset(heap->data, 0, heap->size);
792}
793
802char * scpiheap_strndup(scpi_error_info_heap_t * heap, const char *s, size_t n) {
803 if (!s || !heap || !heap->size) {
804 return NULL;
805 }
806
807 if (heap->data[heap->wr] != '\0') {
808 return NULL;
809 }
810
811 if (*s == '\0') {
812 return NULL;
813 }
814
815 size_t len = SCPIDEFINE_strnlen(s, n) + 1; /* additional '\0' at end */
816 if (len > heap->count) {
817 return NULL;
818 }
819 const char * ptrs = s;
820 char * head = &heap->data[heap->wr];
821 size_t rem = heap->size - (&heap->data[heap->wr] - heap->data);
822
823 if (len >= rem) {
824 memcpy(&heap->data[heap->wr], s, rem);
825 len = len - rem;
826 ptrs += rem;
827 heap->wr = 0;
828 heap->count -= rem;
829 }
830
831 memcpy(&heap->data[heap->wr], ptrs, len);
832 heap->wr += len;
833 heap->count -= len;
834
835 /* ensure '\0' a the end */
836 if (heap->wr > 0) {
837 heap->data[heap->wr - 1] = '\0';
838 } else {
839 heap->data[heap->size - 1] = '\0';
840 }
841 return head;
842}
843
853scpi_bool_t scpiheap_get_parts(scpi_error_info_heap_t * heap, const char * s, size_t * len1, const char ** s2, size_t * len2) {
854 if (!heap || !s || !len1 || !s2 || !len2) {
855 return FALSE;
856 }
857
858 if (*s == '\0') {
859 return FALSE;
860 }
861
862 *len1 = 0;
863 size_t rem = heap->size - (s - heap->data);
864 *len1 = strnlen(s, rem);
865
866 if (&s[*len1 - 1] == &heap->data[heap->size - 1]) {
867 *s2 = heap->data;
868 *len2 = strnlen(*s2, heap->size);
869 } else {
870 *s2 = NULL;
871 *len2 = 0;
872 }
873 return TRUE;
874}
875
883void scpiheap_free(scpi_error_info_heap_t * heap, char * s, scpi_bool_t rollback) {
884
885 if (!s) return;
886
887 char * data_add;
888 size_t len[2];
889
890 if (!scpiheap_get_parts(heap, s, &len[0], (const char **)&data_add, &len[1])) return;
891
892 if (data_add) {
893 len[1]++;
894 memset(data_add, 0, len[1]);
895 heap->count += len[1];
896 } else {
897 len[0]++;
898 }
899 memset(s, 0, len[0]);
900 heap->count += len[0];
901 if (heap->count == heap->size) {
902 heap->wr = 0;
903 return;
904 }
905 if (rollback) {
906 size_t rb = len[0] + len[1];
907 if (rb > heap->wr) {
908 heap->wr += heap->size;
909 }
910 heap->wr -= rb;
911 }
912}
913
914#endif
915
916/*
917 * Floating point to string conversion routines
918 *
919 * Copyright (C) 2002 Michael Ringgaard. All rights reserved.
920 *
921 * Redistribution and use in source and binary forms, with or without
922 * modification, are permitted provided that the following conditions
923 * are met:
924 *
925 * 1. Redistributions of source code must retain the above copyright
926 * notice, this list of conditions and the following disclaimer.
927 * 2. Redistributions in binary form must reproduce the above copyright
928 * notice, this list of conditions and the following disclaimer in the
929 * documentation and/or other materials provided with the distribution.
930 * 3. Neither the name of the project nor the names of its contributors
931 * may be used to endorse or promote products derived from this software
932 * without specific prior written permission.
933 *
934 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
935 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
936 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
937 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
938 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
939 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
940 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
941 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
942 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
943 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
944 * SUCH DAMAGE.
945 */
946
947static char *scpi_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf, size_t bufsize) {
948 int r1, r2;
949 double fi, fj;
950 int w1, w2;
951
952 if (ndigits < 0) ndigits = 0;
953 if (ndigits >= (int) (bufsize - 1)) ndigits = bufsize - 2;
954
955 r2 = 0;
956 *sign = 0;
957 w1 = 0;
958 if (arg < 0) {
959 *sign = 1;
960 arg = -arg;
961 }
962 frexp(arg, &r1);
963 arg = modf(arg, &fi);
964
965 if (fi != 0) {
966 r1 = r1 * 308 / 1024 - ndigits;
967 w2 = bufsize;
968 while (r1 > 0) {
969 fj = modf(fi / 10, &fi);
970 r2++;
971 r1--;
972 }
973 while (fi != 0) {
974 fj = modf(fi / 10, &fi);
975 buf[--w2] = (int) ((fj + .03) * 10) + '0';
976 r2++;
977 }
978 while (w2 < (int) bufsize) buf[w1++] = buf[w2++];
979 } else if (arg > 0) {
980 while ((fj = arg * 10) < 1) {
981 arg = fj;
982 r2--;
983 }
984 }
985 w2 = ndigits;
986 *decpt = r2;
987 if (w2 < 0) {
988 buf[0] = '\0';
989 return buf;
990 }
991 while (w1 <= w2 && w1 < (int) bufsize) {
992 arg *= 10;
993 arg = modf(arg, &fj);
994 buf[w1++] = (int) fj + '0';
995 }
996 if (w2 >= (int) bufsize) {
997 buf[bufsize - 1] = '\0';
998 return buf;
999 }
1000 w1 = w2;
1001 buf[w2] += 5;
1002 while (buf[w2] > '9') {
1003 buf[w2] = '0';
1004 if (w2 > 0) {
1005 ++buf[--w2];
1006 } else {
1007 buf[w2] = '1';
1008 (*decpt)++;
1009 }
1010 }
1011 buf[w1] = '\0';
1012 return buf;
1013}
1014
1015#define SCPI_DTOSTRE_BUFFER_SIZE 32
1016
1017char * SCPI_dtostre(double __val, char * __s, size_t __ssize, unsigned char __prec, unsigned char __flags) {
1018 char buffer[SCPI_DTOSTRE_BUFFER_SIZE];
1019
1020 int sign = SCPIDEFINE_signbit(__val);
1021 char * s = buffer;
1022 int decpt;
1023 if (sign) {
1024 __val = -__val;
1025 s[0] = '-';
1026 s++;
1027 } else if (!SCPIDEFINE_isnan(__val)) {
1028 if (SCPI_DTOSTRE_PLUS_SIGN & __flags) {
1029 s[0] = '+';
1030 s++;
1031 } else if (SCPI_DTOSTRE_ALWAYS_SIGN & __flags) {
1032 s[0] = ' ';
1033 s++;
1034 }
1035 }
1036
1037 if (!SCPIDEFINE_isfinite(__val)) {
1038 if (SCPIDEFINE_isnan(__val)) {
1039 strcpy(s, (__flags & SCPI_DTOSTRE_UPPERCASE) ? "NAN" : "nan");
1040 } else {
1041 strcpy(s, (__flags & SCPI_DTOSTRE_UPPERCASE) ? "INF" : "inf");
1042 }
1043 strncpy(__s, buffer, __ssize);
1044 __s[__ssize - 1] = '\0';
1045 return __s;
1046 }
1047
1048 scpi_ecvt(__val, __prec, &decpt, &sign, s, SCPI_DTOSTRE_BUFFER_SIZE - 1);
1049 if (decpt > 1 && decpt <= __prec) {
1050 memmove(s + decpt + 1, s + decpt, __prec + 1 - decpt);
1051 s[decpt] = '.';
1052 decpt = 0;
1053 } else if (decpt > -4 && decpt <= 0) {
1054 decpt = -decpt + 1;
1055 memmove(s + decpt + 1, s, __prec + 1);
1056 memset(s, '0', decpt + 1);
1057 s[1] = '.';
1058 decpt = 0;
1059 } else {
1060 memmove(s + 2, s + 1, __prec + 1);
1061 s[1] = '.';
1062 decpt--;
1063 }
1064
1065 s = &s[__prec];
1066 while (s[0] == '0') {
1067 s[0] = 0;
1068 s--;
1069 }
1070 if (s[0] == '.') {
1071 s[0] = 0;
1072 s--;
1073 }
1074
1075 if (decpt != 0) {
1076 s++;
1077 s[0] = 'e';
1078 s++;
1079 if (decpt != 0) {
1080 if (decpt > 0) {
1081 s[0] = '+';
1082 }
1083 if (decpt < 0) {
1084 s[0] = '-';
1085 decpt = -decpt;
1086 }
1087 s++;
1088 }
1089 UInt32ToStrBaseSign(decpt, s, 5, 10, 0);
1090 if (s[1] == 0) {
1091 s[2] = s[1];
1092 s[1] = s[0];
1093 s[0] = '0';
1094 }
1095 }
1096
1097 strncpy(__s, buffer, __ssize);
1098 __s[__ssize - 1] = '\0';
1099 return __s;
1100}
1101
1107
1108 union {
1109 uint32_t i;
1110 char c[4];
1111 } bint = {0x01020304};
1112
1113 return bint.c[0] == 1 ? SCPI_FORMAT_BIGENDIAN : SCPI_FORMAT_LITTLEENDIAN;
1114}
1115
1121uint16_t SCPI_Swap16(uint16_t val) {
1122 return ((val & 0x00FF) << 8) |
1123 ((val & 0xFF00) >> 8);
1124}
1125
1131uint32_t SCPI_Swap32(uint32_t val) {
1132 return ((val & 0x000000FFul) << 24) |
1133 ((val & 0x0000FF00ul) << 8) |
1134 ((val & 0x00FF0000ul) >> 8) |
1135 ((val & 0xFF000000ul) >> 24);
1136}
1137
1143uint64_t SCPI_Swap64(uint64_t val) {
1144 return ((val & 0x00000000000000FFull) << 56) |
1145 ((val & 0x000000000000FF00ull) << 40) |
1146 ((val & 0x0000000000FF0000ull) << 24) |
1147 ((val & 0x00000000FF000000ull) << 8) |
1148 ((val & 0x000000FF00000000ull) >> 8) |
1149 ((val & 0x0000FF0000000000ull) >> 24) |
1150 ((val & 0x00FF000000000000ull) >> 40) |
1151 ((val & 0xFF00000000000000ull) >> 56);
1152}
#define SCPIDEFINE_isfinite(n)
Definition config.h:241
#define SCPIDEFINE_strtof(n, p)
Definition config.h:247
#define SCPIDEFINE_strtoull(n, p, b)
Definition config.h:255
#define SCPIDEFINE_floatToStr(v, s, l)
Definition config.h:193
#define SCPIDEFINE_strnlen(s, l)
Definition config.h:174
#define SCPIDEFINE_signbit(n)
Definition config.h:233
#define SCPIDEFINE_strncasecmp(s1, s2, l)
Definition config.h:183
#define SCPIDEFINE_doubleToStr(v, s, l)
Definition config.h:203
#define SCPIDEFINE_isnan(n)
Definition config.h:265
#define SCPIDEFINE_strtoll(n, p, b)
Definition config.h:254
enum _scpi_array_format_t scpi_array_format_t
Definition types.h:407
bool scpi_bool_t
Definition types.h:67
#define TRUE
Definition types.h:63
#define FALSE
Definition types.h:60
@ SCPI_FORMAT_BIGENDIAN
Definition types.h:404
@ SCPI_FORMAT_LITTLEENDIAN
Definition types.h:405
uint64_t SCPI_Swap64(uint64_t val)
Definition utils.c:1143
char * SCPI_dtostre(double __val, char *__s, size_t __ssize, unsigned char __prec, unsigned char __flags)
Definition utils.c:1017
char * strnpbrk(const char *str, size_t size, const char *set)
Definition utils.c:59
size_t SCPI_Int64ToStr(int64_t val, char *str, size_t len)
Definition utils.c:228
size_t skipWhitespace(const char *cmd, size_t len)
Definition utils.c:410
size_t SCPI_FloatToStr(float val, char *str, size_t len)
Definition utils.c:251
scpi_bool_t compareStrAndNum(const char *str1, size_t len1, const char *str2, size_t len2, int32_t *num)
Definition utils.c:368
size_t SCPI_UInt32ToStrBase(uint32_t val, char *str, size_t len, int8_t base)
Definition utils.c:154
size_t SCPI_UInt64ToStrBase(uint64_t val, char *str, size_t len, int8_t base)
Definition utils.c:240
scpi_bool_t matchPattern(const char *pattern, size_t pattern_len, const char *str, size_t str_len, int32_t *num)
Definition utils.c:479
size_t UInt64ToStrBaseSign(uint64_t val, char *str, size_t len, int8_t base, scpi_bool_t sign)
Definition utils.c:167
size_t SCPI_Int32ToStr(int32_t val, char *str, size_t len)
Definition utils.c:142
uint32_t SCPI_Swap32(uint32_t val)
Definition utils.c:1131
size_t strToDouble(const char *str, double *val)
Definition utils.c:334
size_t strBaseToUInt64(const char *str, uint64_t *val, int8_t base)
Definition utils.c:310
#define SCPI_DTOSTRE_BUFFER_SIZE
Definition utils.c:1015
static size_t patternSeparatorPos(const char *pattern, size_t len)
Definition utils.c:443
static char * scpi_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf, size_t bufsize)
Definition utils.c:947
static size_t cmdSeparatorPos(const char *cmd, size_t len)
Definition utils.c:459
scpi_bool_t matchCommand(const char *pattern, const char *cmd, size_t len, int32_t *numbers, size_t numbers_len, int32_t default_value, bool *query)
Definition utils.c:505
size_t strBaseToUInt32(const char *str, uint32_t *val, int8_t base)
Definition utils.c:286
scpi_bool_t composeCompoundCommand(const scpi_token_t *prev, scpi_token_t *current)
Definition utils.c:688
scpi_array_format_t SCPI_GetNativeFormat(void)
Definition utils.c:1106
#define SKIP_CMD(n)
size_t SCPI_DoubleToStr(double val, char *str, size_t len)
Definition utils.c:263
#define SKIP_PATTERN(n)
size_t strBaseToInt64(const char *str, int64_t *val, int8_t base)
Definition utils.c:298
scpi_bool_t compareStr(const char *str1, size_t len1, const char *str2, size_t len2)
Definition utils.c:348
size_t strBaseToInt32(const char *str, int32_t *val, int8_t base)
Definition utils.c:274
size_t BSD_strnlen(const char *s, size_t maxlen)
Definition utils.c:734
int OUR_strncasecmp(const char *s1, const char *s2, size_t n)
Definition utils.c:747
size_t strToFloat(const char *str, float *val)
Definition utils.c:322
#define ADD_CHAR(c)
static size_t patternSeparatorShortPos(const char *pattern, size_t len)
Definition utils.c:427
uint16_t SCPI_Swap16(uint16_t val)
Definition utils.c:1121
size_t UInt32ToStrBaseSign(uint32_t val, char *str, size_t len, int8_t base, scpi_bool_t sign)
Definition utils.c:81
Conversion routines and string manipulation routines.
#define SCPI_DTOSTRE_PLUS_SIGN
#define SCPI_DTOSTRE_UPPERCASE
#define SCPI_DTOSTRE_ALWAYS_SIGN
char * OUR_strndup(const char *s, size_t n)