2 * This file is part of the libsigrok project.
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 /* Needed for POSIX.1-2008 locale functions */
22 #define _XOPEN_SOURCE 700
27 #if defined(__FreeBSD__) || defined(__APPLE__)
30 #if defined(__FreeBSD__)
31 #include <sys/param.h>
38 #include <libsigrok/libsigrok.h>
39 #include "libsigrok-internal.h"
42 #define LOG_PREFIX "strutil"
48 * Helper functions for handling or converting libsigrok-related strings.
52 * @defgroup grp_strutil String utilities
54 * Helper functions for handling or converting libsigrok-related strings.
60 * Convert a string representation of a numeric value (base 10) to a long integer. The
61 * conversion is strict and will fail if the complete string does not represent
62 * a valid long integer. The function sets errno according to the details of the
65 * @param str The string representation to convert.
66 * @param ret Pointer to long where the result of the conversion will be stored.
68 * @retval SR_OK Conversion successful.
69 * @retval SR_ERR Failure.
73 SR_PRIV int sr_atol(const char *str, long *ret)
79 tmp = strtol(str, &endptr, 10);
81 while (endptr && isspace(*endptr))
84 if (!endptr || *endptr || errno) {
95 * Convert a text to a number including support for non-decimal bases.
96 * Also optionally returns the position after the number, where callers
97 * can either error out, or support application specific suffixes.
99 * @param[in] str The input text to convert.
100 * @param[out] ret The conversion result.
101 * @param[out] end The position after the number.
102 * @param[in] base The number format's base, can be 0.
104 * @retval SR_OK Conversion successful.
105 * @retval SR_ERR Conversion failed.
109 * This routine is more general than @ref sr_atol(), which strictly
110 * expects the input text to contain just a decimal number, and nothing
111 * else in addition. The @ref sr_atol_base() routine accepts trailing
112 * text after the number, and supports non-decimal numbers (bin, hex),
113 * including automatic detection from prefix text.
115 SR_PRIV int sr_atol_base(const char *str, long *ret, char **end, int base)
120 /* Add "0b" prefix support which strtol(3) may be missing. */
121 while (str && isspace(*str))
123 if (!base && strncmp(str, "0b", strlen("0b")) == 0) {
128 /* Run the number conversion. Quick bail out if that fails. */
131 num = strtol(str, &endptr, base);
132 if (!endptr || errno) {
139 /* Advance to optional non-space trailing suffix. */
140 while (endptr && isspace(*endptr))
149 * Convert a text to a number including support for non-decimal bases.
150 * Also optionally returns the position after the number, where callers
151 * can either error out, or support application specific suffixes.
153 * @param[in] str The input text to convert.
154 * @param[out] ret The conversion result.
155 * @param[out] end The position after the number.
156 * @param[in] base The number format's base, can be 0.
158 * @retval SR_OK Conversion successful.
159 * @retval SR_ERR Conversion failed.
163 * This routine is more general than @ref sr_atol(), which strictly
164 * expects the input text to contain just a decimal number, and nothing
165 * else in addition. The @ref sr_atoul_base() routine accepts trailing
166 * text after the number, and supports non-decimal numbers (bin, hex),
167 * including automatic detection from prefix text.
169 SR_PRIV int sr_atoul_base(const char *str, unsigned long *ret, char **end, int base)
174 /* Add "0b" prefix support which strtol(3) may be missing. */
175 while (str && isspace(*str))
177 if (!base && strncmp(str, "0b", strlen("0b")) == 0) {
182 /* Run the number conversion. Quick bail out if that fails. */
185 num = strtoul(str, &endptr, base);
186 if (!endptr || errno) {
193 /* Advance to optional non-space trailing suffix. */
194 while (endptr && isspace(*endptr))
203 * Convert a string representation of a numeric value (base 10) to an integer. The
204 * conversion is strict and will fail if the complete string does not represent
205 * a valid integer. The function sets errno according to the details of the
208 * @param str The string representation to convert.
209 * @param ret Pointer to int where the result of the conversion will be stored.
211 * @retval SR_OK Conversion successful.
212 * @retval SR_ERR Failure.
216 SR_PRIV int sr_atoi(const char *str, int *ret)
220 if (sr_atol(str, &tmp) != SR_OK)
223 if ((int) tmp != tmp) {
233 * Convert a string representation of a numeric value to a double. The
234 * conversion is strict and will fail if the complete string does not represent
235 * a valid double. The function sets errno according to the details of the
238 * @param str The string representation to convert.
239 * @param ret Pointer to double where the result of the conversion will be stored.
241 * @retval SR_OK Conversion successful.
242 * @retval SR_ERR Failure.
246 SR_PRIV int sr_atod(const char *str, double *ret)
252 tmp = strtof(str, &endptr);
254 while (endptr && isspace(*endptr))
257 if (!endptr || *endptr || errno) {
268 * Convert a string representation of a numeric value to a float. The
269 * conversion is strict and will fail if the complete string does not represent
270 * a valid float. The function sets errno according to the details of the
273 * @param str The string representation to convert.
274 * @param ret Pointer to float where the result of the conversion will be stored.
276 * @retval SR_OK Conversion successful.
277 * @retval SR_ERR Failure.
281 SR_PRIV int sr_atof(const char *str, float *ret)
285 if (sr_atod(str, &tmp) != SR_OK)
288 if ((float) tmp != tmp) {
298 * Convert a string representation of a numeric value to a double. The
299 * conversion is strict and will fail if the complete string does not represent
300 * a valid double. The function sets errno according to the details of the
301 * failure. This version ignores the locale.
303 * @param str The string representation to convert.
304 * @param ret Pointer to double where the result of the conversion will be stored.
306 * @retval SR_OK Conversion successful.
307 * @retval SR_ERR Failure.
311 SR_PRIV int sr_atod_ascii(const char *str, double *ret)
317 tmp = g_ascii_strtod(str, &endptr);
319 if (!endptr || *endptr || errno) {
330 * Convert text to a floating point value, and get its precision.
332 * @param[in] str The input text to convert.
333 * @param[out] ret The conversion result, a double precision float number.
334 * @param[out] digits The number of significant decimals.
336 * @returns SR_OK in case of successful text to number conversion.
337 * @returns SR_ERR when conversion fails.
341 SR_PRIV int sr_atod_ascii_digits(const char *str, double *ret, int *digits)
344 int *dig_ref, m_dig, exp;
349 * Convert floating point text to the number value, _and_ get
350 * the value's precision in the process. Steps taken to do it:
351 * - Skip leading whitespace.
352 * - Count the number of decimals after the mantissa's period.
353 * - Get the exponent's signed value.
355 * This implementation still uses common code for the actual
356 * conversion, but "violates API layers" by duplicating the
357 * text scan, to get the number of significant digits.
360 while (*p && isspace(*p))
362 if (*p == '-' || *p == '+')
369 if (toupper(c) == 'E') {
370 exp = strtol(p, NULL, 10);
383 /* Need not warn, conversion will fail. */
386 sr_spew("atod digits: txt \"%s\" -> m %d, e %d -> digits %d",
387 str, m_dig, exp, m_dig + -exp);
390 if (sr_atod_ascii(str, &f) != SR_OK)
401 * Convert a string representation of a numeric value to a float. The
402 * conversion is strict and will fail if the complete string does not represent
403 * a valid float. The function sets errno according to the details of the
404 * failure. This version ignores the locale.
406 * @param str The string representation to convert.
407 * @param ret Pointer to float where the result of the conversion will be stored.
409 * @retval SR_OK Conversion successful.
410 * @retval SR_ERR Failure.
414 SR_PRIV int sr_atof_ascii(const char *str, float *ret)
420 tmp = g_ascii_strtod(str, &endptr);
422 if (!endptr || *endptr || errno) {
428 /* FIXME This fails unexpectedly. Some other method to safel downcast
429 * needs to be found. Checking against FLT_MAX doesn't work as well. */
431 if ((float) tmp != tmp) {
433 sr_dbg("ERANGEEEE %e != %e", (float) tmp, tmp);
443 * Compose a string with a format string in the buffer pointed to by buf.
445 * It is up to the caller to ensure that the allocated buffer is large enough
446 * to hold the formatted result.
448 * A terminating NUL character is automatically appended after the content
451 * After the format parameter, the function expects at least as many additional
452 * arguments as needed for format.
454 * This version ignores the current locale and uses the locale "C" for Linux,
455 * FreeBSD, OSX and Android.
457 * @param buf Pointer to a buffer where the resulting C string is stored.
458 * @param format C string that contains a format string (see printf).
459 * @param ... A sequence of additional arguments, each containing a value to be
460 * used to replace a format specifier in the format string.
462 * @return On success, the number of characters that would have been written,
463 * not counting the terminating NUL character.
467 SR_API int sr_sprintf_ascii(char *buf, const char *format, ...)
472 va_start(args, format);
473 ret = sr_vsprintf_ascii(buf, format, args);
480 * Compose a string with a format string in the buffer pointed to by buf.
482 * It is up to the caller to ensure that the allocated buffer is large enough
483 * to hold the formatted result.
485 * Internally, the function retrieves arguments from the list identified by
486 * args as if va_arg was used on it, and thus the state of args is likely to
487 * be altered by the call.
489 * In any case, args should have been initialized by va_start at some point
490 * before the call, and it is expected to be released by va_end at some point
493 * This version ignores the current locale and uses the locale "C" for Linux,
494 * FreeBSD, OSX and Android.
496 * @param buf Pointer to a buffer where the resulting C string is stored.
497 * @param format C string that contains a format string (see printf).
498 * @param args A value identifying a variable arguments list initialized with
501 * @return On success, the number of characters that would have been written,
502 * not counting the terminating NUL character.
506 SR_API int sr_vsprintf_ascii(char *buf, const char *format, va_list args)
513 * TODO: This part compiles with mingw-w64 but doesn't run with Win7.
514 * Doesn't start because of "Procedure entry point _create_locale
515 * not found in msvcrt.dll".
516 * mingw-w64 should link to msvcr100.dll not msvcrt.dll!
517 * See: https://msdn.microsoft.com/en-us/en-en/library/1kt27hek.aspx
521 locale = _create_locale(LC_NUMERIC, "C");
522 ret = _vsprintf_l(buf, format, locale, args);
523 _free_locale(locale);
526 /* vsprintf() uses the current locale, may not work correctly for floats. */
527 ret = vsprintf(buf, format, args);
530 #elif defined(__APPLE__)
533 * https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/printf_l.3.html
534 * https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/xlocale.3.html
539 locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
540 ret = vsprintf_l(buf, locale, format, args);
544 #elif defined(__FreeBSD__) && __FreeBSD_version >= 901000
547 * https://www.freebsd.org/cgi/man.cgi?query=printf_l&apropos=0&sektion=3&manpath=FreeBSD+9.1-RELEASE
548 * https://www.freebsd.org/cgi/man.cgi?query=xlocale&apropos=0&sektion=3&manpath=FreeBSD+9.1-RELEASE
553 locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
554 ret = vsprintf_l(buf, locale, format, args);
558 #elif defined(__ANDROID__)
560 * The Bionic libc only has two locales ("C" aka "POSIX" and "C.UTF-8"
561 * aka "en_US.UTF-8"). The decimal point is hard coded as "."
562 * See: https://android.googlesource.com/platform/bionic/+/master/libc/bionic/locale.cpp
566 ret = vsprintf(buf, format, args);
569 #elif defined(__linux__)
571 locale_t old_locale, temp_locale;
573 /* Switch to C locale for proper float/double conversion. */
574 temp_locale = newlocale(LC_NUMERIC, "C", NULL);
575 old_locale = uselocale(temp_locale);
577 ret = vsprintf(buf, format, args);
579 /* Switch back to original locale. */
580 uselocale(old_locale);
581 freelocale(temp_locale);
584 #elif defined(__unix__) || defined(__unix)
586 * This is a fallback for all other BSDs, *nix and FreeBSD <= 9.0, by
587 * using the current locale for snprintf(). This may not work correctly
592 ret = vsprintf(buf, format, args);
596 /* No implementation for unknown systems! */
602 * Composes a string with a format string (like printf) in the buffer pointed
603 * by buf (taking buf_size as the maximum buffer capacity to fill).
604 * If the resulting string would be longer than n - 1 characters, the remaining
605 * characters are discarded and not stored, but counted for the value returned
607 * A terminating NUL character is automatically appended after the content
609 * After the format parameter, the function expects at least as many additional
610 * arguments as needed for format.
612 * This version ignores the current locale and uses the locale "C" for Linux,
613 * FreeBSD, OSX and Android.
615 * @param buf Pointer to a buffer where the resulting C string is stored.
616 * @param buf_size Maximum number of bytes to be used in the buffer. The
617 * generated string has a length of at most buf_size - 1, leaving space
618 * for the additional terminating NUL character.
619 * @param format C string that contains a format string (see printf).
620 * @param ... A sequence of additional arguments, each containing a value to be
621 * used to replace a format specifier in the format string.
623 * @return On success, the number of characters that would have been written if
624 * buf_size had been sufficiently large, not counting the terminating
625 * NUL character. On failure, a negative number is returned.
626 * Notice that only when this returned value is non-negative and less
627 * than buf_size, the string has been completely written.
631 SR_API int sr_snprintf_ascii(char *buf, size_t buf_size,
632 const char *format, ...)
637 va_start(args, format);
638 ret = sr_vsnprintf_ascii(buf, buf_size, format, args);
645 * Composes a string with a format string (like printf) in the buffer pointed
646 * by buf (taking buf_size as the maximum buffer capacity to fill).
647 * If the resulting string would be longer than n - 1 characters, the remaining
648 * characters are discarded and not stored, but counted for the value returned
650 * A terminating NUL character is automatically appended after the content
652 * Internally, the function retrieves arguments from the list identified by
653 * args as if va_arg was used on it, and thus the state of args is likely to
654 * be altered by the call.
655 * In any case, arg should have been initialized by va_start at some point
656 * before the call, and it is expected to be released by va_end at some point
659 * This version ignores the current locale and uses the locale "C" for Linux,
660 * FreeBSD, OSX and Android.
662 * @param buf Pointer to a buffer where the resulting C string is stored.
663 * @param buf_size Maximum number of bytes to be used in the buffer. The
664 * generated string has a length of at most buf_size - 1, leaving space
665 * for the additional terminating NUL character.
666 * @param format C string that contains a format string (see printf).
667 * @param args A value identifying a variable arguments list initialized with
670 * @return On success, the number of characters that would have been written if
671 * buf_size had been sufficiently large, not counting the terminating
672 * NUL character. On failure, a negative number is returned.
673 * Notice that only when this returned value is non-negative and less
674 * than buf_size, the string has been completely written.
678 SR_API int sr_vsnprintf_ascii(char *buf, size_t buf_size,
679 const char *format, va_list args)
686 * TODO: This part compiles with mingw-w64 but doesn't run with Win7.
687 * Doesn't start because of "Procedure entry point _create_locale
688 * not found in msvcrt.dll".
689 * mingw-w64 should link to msvcr100.dll not msvcrt.dll!.
690 * See: https://msdn.microsoft.com/en-us/en-en/library/1kt27hek.aspx
694 locale = _create_locale(LC_NUMERIC, "C");
695 ret = _vsnprintf_l(buf, buf_size, format, locale, args);
696 _free_locale(locale);
699 /* vsprintf uses the current locale, may cause issues for floats. */
700 ret = vsnprintf(buf, buf_size, format, args);
703 #elif defined(__APPLE__)
706 * https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/printf_l.3.html
707 * https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/xlocale.3.html
712 locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
713 ret = vsnprintf_l(buf, buf_size, locale, format, args);
717 #elif defined(__FreeBSD__) && __FreeBSD_version >= 901000
720 * https://www.freebsd.org/cgi/man.cgi?query=printf_l&apropos=0&sektion=3&manpath=FreeBSD+9.1-RELEASE
721 * https://www.freebsd.org/cgi/man.cgi?query=xlocale&apropos=0&sektion=3&manpath=FreeBSD+9.1-RELEASE
726 locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
727 ret = vsnprintf_l(buf, buf_size, locale, format, args);
731 #elif defined(__ANDROID__)
733 * The Bionic libc only has two locales ("C" aka "POSIX" and "C.UTF-8"
734 * aka "en_US.UTF-8"). The decimal point is hard coded as ".".
735 * See: https://android.googlesource.com/platform/bionic/+/master/libc/bionic/locale.cpp
739 ret = vsnprintf(buf, buf_size, format, args);
742 #elif defined(__linux__)
744 locale_t old_locale, temp_locale;
746 /* Switch to C locale for proper float/double conversion. */
747 temp_locale = newlocale(LC_NUMERIC, "C", NULL);
748 old_locale = uselocale(temp_locale);
750 ret = vsnprintf(buf, buf_size, format, args);
752 /* Switch back to original locale. */
753 uselocale(old_locale);
754 freelocale(temp_locale);
757 #elif defined(__unix__) || defined(__unix)
759 * This is a fallback for all other BSDs, *nix and FreeBSD <= 9.0, by
760 * using the current locale for snprintf(). This may not work correctly
765 ret = vsnprintf(buf, buf_size, format, args);
769 /* No implementation for unknown systems! */
775 * Convert a sequence of bytes to its textual representation ("hex dump").
777 * Callers should free the allocated GString. See sr_hexdump_free().
779 * @param[in] data Pointer to the byte sequence to print.
780 * @param[in] len Number of bytes to print.
782 * @return NULL upon error, newly allocated GString pointer otherwise.
786 SR_PRIV GString *sr_hexdump_new(const uint8_t *data, const size_t len)
791 s = g_string_sized_new(3 * len);
792 for (i = 0; i < len; i++) {
794 g_string_append_c(s, ' ');
795 g_string_append_printf(s, "%02x", data[i]);
802 * Free a hex dump text that was created by sr_hexdump_new().
804 * @param[in] s Pointer to the GString to release.
808 SR_PRIV void sr_hexdump_free(GString *s)
811 g_string_free(s, TRUE);
815 * Convert a string representation of a numeric value to a sr_rational.
817 * The conversion is strict and will fail if the complete string does not
818 * represent a valid number. The function sets errno according to the details
819 * of the failure. This version ignores the locale.
821 * @param str The string representation to convert.
822 * @param ret Pointer to sr_rational where the result of the conversion will be stored.
824 * @retval SR_OK Conversion successful.
825 * @retval SR_ERR Failure.
829 SR_API int sr_parse_rational(const char *str, struct sr_rational *ret)
833 gboolean is_negative, empty_integral, empty_fractional, exp_negative;
837 uint32_t fractional_len;
841 * Implementor's note: This routine tries hard to avoid calling
842 * glib's or the platform's conversion routines with input that
843 * cannot get converted *at all* (see bug #1093). It also takes
844 * care to return with non-zero errno values for any failed
845 * conversion attempt. It's assumed that correctness and robustness
846 * are more important than performance, which is why code paths
847 * are not optimized at all. Maintainability took priority.
852 /* Skip leading whitespace. */
853 while (isspace(*readptr))
856 /* Determine the sign, default to non-negative. */
858 if (*readptr == '-') {
861 } else if (*readptr == '+') {
866 /* Get the (optional) integral part. */
867 empty_integral = TRUE;
869 endptr = (char *)readptr;
871 if (isdigit(*readptr)) {
872 empty_integral = FALSE;
873 integral = g_ascii_strtoll(readptr, &endptr, 10);
883 /* Get the optional fractional part. */
884 empty_fractional = TRUE;
887 if (*readptr == '.') {
891 if (isdigit(*readptr)) {
892 empty_fractional = FALSE;
893 fractional = g_ascii_strtoll(readptr, &endptr, 10);
896 if (endptr == readptr) {
900 fractional_len = endptr - readptr;
905 /* At least one of integral or fractional is required. */
906 if (empty_integral && empty_fractional) {
911 /* Get the (optional) exponent. */
913 if ((*readptr == 'E') || (*readptr == 'e')) {
916 exp_negative = FALSE;
917 if (*readptr == '+') {
918 exp_negative = FALSE;
921 } else if (*readptr == '-') {
926 if (!isdigit(*readptr)) {
931 exponent = g_ascii_strtoll(readptr, &endptr, 10);
934 if (endptr == readptr) {
940 exponent = -exponent;
943 /* Input must be exhausted. Unconverted remaining input is fatal. */
944 if (*endptr != '\0') {
950 * Apply the sign to the integral (and fractional) part(s).
951 * Adjust exponent (decimal position) such that the above integral
952 * and fractional parts both fit into the (new) integral part.
955 integral = -integral;
956 while (fractional_len-- > 0) {
961 integral += fractional;
963 integral -= fractional;
964 while (exponent > 0) {
970 * When significant digits remain after the decimal, scale up the
971 * denominator such that we end up with two integer p/q numbers.
974 while (exponent < 0) {
980 ret->q = denominator;
986 * Convert a numeric value value to its "natural" string representation
989 * E.g. a value of 3000000, with units set to "W", would be converted
990 * to "3 MW", 20000 to "20 kW", 31500 would become "31.5 kW".
992 * @param x The value to convert.
993 * @param unit The unit to append to the string, or NULL if the string
996 * @return A newly allocated string representation of the samplerate value,
997 * or NULL upon errors. The caller is responsible to g_free() the
1002 SR_API char *sr_si_string_u64(uint64_t x, const char *unit)
1005 uint64_t quot, divisor[] = {
1006 SR_HZ(1), SR_KHZ(1), SR_MHZ(1), SR_GHZ(1),
1007 SR_GHZ(1000), SR_GHZ(1000 * 1000), SR_GHZ(1000 * 1000 * 1000),
1009 const char *p, prefix[] = "\0kMGTPE";
1010 char fmt[16], fract[20] = "", *f;
1015 for (i = 0; (quot = x / divisor[i]) >= 1000; i++);
1018 sprintf(fmt, ".%%0%d"PRIu64, i * 3);
1019 f = fract + sprintf(fract, fmt, x % divisor[i]) - 1;
1021 while (f >= fract && strchr("0.", *f))
1027 return g_strdup_printf("%" PRIu64 "%s %.1s%s", quot, fract, p, unit);
1031 * Convert a numeric samplerate value to its "natural" string representation.
1033 * E.g. a value of 3000000 would be converted to "3 MHz", 20000 to "20 kHz",
1034 * 31500 would become "31.5 kHz".
1036 * @param samplerate The samplerate in Hz.
1038 * @return A newly allocated string representation of the samplerate value,
1039 * or NULL upon errors. The caller is responsible to g_free() the
1044 SR_API char *sr_samplerate_string(uint64_t samplerate)
1046 return sr_si_string_u64(samplerate, "Hz");
1050 * Convert a numeric period value to the "natural" string representation
1051 * of its period value.
1053 * The period is specified as a rational number's numerator and denominator.
1055 * E.g. a pair of (1, 5) would be converted to "200 ms", (10, 100) to "100 ms".
1057 * @param v_p The period numerator.
1058 * @param v_q The period denominator.
1060 * @return A newly allocated string representation of the period value,
1061 * or NULL upon errors. The caller is responsible to g_free() the
1066 SR_API char *sr_period_string(uint64_t v_p, uint64_t v_q)
1071 freq = 1 / ((double)v_p / v_q);
1073 if (freq > SR_GHZ(1)) {
1074 v = (double)v_p / v_q * 1000000000000.0;
1075 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1076 return g_strdup_printf("%.*f ps", prec, v);
1077 } else if (freq > SR_MHZ(1)) {
1078 v = (double)v_p / v_q * 1000000000.0;
1079 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1080 return g_strdup_printf("%.*f ns", prec, v);
1081 } else if (freq > SR_KHZ(1)) {
1082 v = (double)v_p / v_q * 1000000.0;
1083 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1084 return g_strdup_printf("%.*f us", prec, v);
1085 } else if (freq > 1) {
1086 v = (double)v_p / v_q * 1000.0;
1087 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1088 return g_strdup_printf("%.*f ms", prec, v);
1090 v = (double)v_p / v_q;
1091 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1092 return g_strdup_printf("%.*f s", prec, v);
1097 * Convert a numeric voltage value to the "natural" string representation
1098 * of its voltage value. The voltage is specified as a rational number's
1099 * numerator and denominator.
1101 * E.g. a value of 300000 would be converted to "300mV", 2 to "2V".
1103 * @param v_p The voltage numerator.
1104 * @param v_q The voltage denominator.
1106 * @return A newly allocated string representation of the voltage value,
1107 * or NULL upon errors. The caller is responsible to g_free() the
1112 SR_API char *sr_voltage_string(uint64_t v_p, uint64_t v_q)
1115 return g_strdup_printf("%" PRIu64 " mV", v_p);
1117 return g_strdup_printf("%" PRIu64 " V", v_p);
1119 return g_strdup_printf("%g V", (float)v_p / (float)v_q);
1123 * Convert a "natural" string representation of a size value to uint64_t.
1125 * E.g. a value of "3k" or "3 K" would be converted to 3000, a value
1126 * of "15M" would be converted to 15000000.
1128 * Value representations other than decimal (such as hex or octal) are not
1129 * supported. Only 'k' (kilo), 'm' (mega), 'g' (giga) suffixes are supported.
1130 * Spaces (but not other whitespace) between value and suffix are allowed.
1132 * @param sizestring A string containing a (decimal) size value.
1133 * @param size Pointer to uint64_t which will contain the string's size value.
1135 * @return SR_OK upon success, SR_ERR upon errors.
1139 SR_API int sr_parse_sizestring(const char *sizestring, uint64_t *size)
1141 uint64_t multiplier;
1146 *size = strtoull(sizestring, &s, 10);
1150 while (s && *s && multiplier == 0 && !done) {
1155 frac_part = g_ascii_strtod(s, &s);
1159 multiplier = SR_KHZ(1);
1163 multiplier = SR_MHZ(1);
1167 multiplier = SR_GHZ(1);
1171 multiplier = SR_GHZ(1000);
1175 multiplier = SR_GHZ(1000 * 1000);
1179 multiplier = SR_GHZ(1000 * 1000 * 1000);
1187 if (multiplier > 0) {
1188 *size *= multiplier;
1189 *size += frac_part * multiplier;
1194 if (s && *s && g_ascii_strcasecmp(s, "Hz"))
1201 * Convert a "natural" string representation of a time value to an
1202 * uint64_t value in milliseconds.
1204 * E.g. a value of "3s" or "3 s" would be converted to 3000, a value
1205 * of "15ms" would be converted to 15.
1207 * Value representations other than decimal (such as hex or octal) are not
1208 * supported. Only lower-case "s" and "ms" time suffixes are supported.
1209 * Spaces (but not other whitespace) between value and suffix are allowed.
1211 * @param timestring A string containing a (decimal) time value.
1212 * @return The string's time value as uint64_t, in milliseconds.
1214 * @todo Add support for "m" (minutes) and others.
1215 * @todo Add support for picoseconds?
1216 * @todo Allow both lower-case and upper-case? If no, document it.
1220 SR_API uint64_t sr_parse_timestring(const char *timestring)
1225 /* TODO: Error handling, logging. */
1227 time_msec = strtoull(timestring, &s, 10);
1228 if (time_msec == 0 && s == timestring)
1234 if (!strcmp(s, "s"))
1236 else if (!strcmp(s, "ms"))
1246 SR_API gboolean sr_parse_boolstring(const char *boolstr)
1249 * Complete absence of an input spec is assumed to mean TRUE,
1250 * as in command line option strings like this:
1251 * ...:samplerate=100k:header:numchannels=4:...
1253 if (!boolstr || !*boolstr)
1256 if (!g_ascii_strncasecmp(boolstr, "true", 4) ||
1257 !g_ascii_strncasecmp(boolstr, "yes", 3) ||
1258 !g_ascii_strncasecmp(boolstr, "on", 2) ||
1259 !g_ascii_strncasecmp(boolstr, "1", 1))
1266 SR_API int sr_parse_period(const char *periodstr, uint64_t *p, uint64_t *q)
1270 *p = strtoull(periodstr, &s, 10);
1271 if (*p == 0 && s == periodstr)
1272 /* No digits found. */
1278 if (!strcmp(s, "fs"))
1279 *q = UINT64_C(1000000000000000);
1280 else if (!strcmp(s, "ps"))
1281 *q = UINT64_C(1000000000000);
1282 else if (!strcmp(s, "ns"))
1283 *q = UINT64_C(1000000000);
1284 else if (!strcmp(s, "us"))
1286 else if (!strcmp(s, "ms"))
1288 else if (!strcmp(s, "s"))
1291 /* Must have a time suffix. */
1299 SR_API int sr_parse_voltage(const char *voltstr, uint64_t *p, uint64_t *q)
1303 *p = strtoull(voltstr, &s, 10);
1304 if (*p == 0 && s == voltstr)
1305 /* No digits found. */
1311 if (!g_ascii_strcasecmp(s, "mv"))
1313 else if (!g_ascii_strcasecmp(s, "v"))
1316 /* Must have a base suffix. */
1324 * Append another text item to a NULL terminated string vector.
1326 * @param[in] table The previous string vector.
1327 * @param[in,out] sz The previous and the resulting vector size
1329 * @param[in] text The text string to append to the vector.
1332 * @returns The new vector, its location can differ from 'table'.
1333 * Or #NULL in case of failure.
1335 * This implementation happens to work for the first invocation when
1336 * 'table' is #NULL and 'sz' is 0, as well as subsequent append calls.
1337 * The 'text' can be #NULL or can be a non-empty string. When 'sz' is
1338 * not provided, then the 'table' must be a NULL terminated vector,
1339 * so that the routine can auto-determine the vector's current length.
1341 * This routine re-allocates the vector as needed. Callers must not
1342 * rely on the memory address to remain the same across calls.
1344 static char **append_probe_name(char **table, size_t *sz, const char *text)
1346 size_t curr_size, alloc_size;
1349 /* Get the table's previous size (item count). */
1353 curr_size = g_strv_length(table);
1357 /* Extend storage to hold one more item, and the termination. */
1358 alloc_size = curr_size + (text ? 1 : 0) + 1;
1359 alloc_size *= sizeof(table[0]);
1360 new_table = g_realloc(table, alloc_size);
1368 /* Append the item, NULL terminate. */
1370 new_table[curr_size] = g_strdup(text);
1371 if (!new_table[curr_size]) {
1372 g_strfreev(new_table);
1381 new_table[curr_size] = NULL;
1386 static char **append_probe_names(char **table, size_t *sz,
1393 table = append_probe_name(table, sz, names[0]);
1399 static const struct {
1401 const char **expands;
1402 } probe_name_aliases[] = {
1404 "ac97", (const char *[]){
1411 "i2c", (const char *[]){
1416 "jtag", (const char *[]){
1417 "tdi", "tdo", "tck", "tms", NULL,
1421 "jtag-opt", (const char *[]){
1422 "tdi", "tdo", "tck", "tms",
1423 "trst", "srst", "rtck", NULL,
1427 "ieee488", (const char *[]){
1428 "dio1", "dio2", "dio3", "dio4",
1429 "dio5", "dio6", "dio7", "dio8",
1430 "eoi", "dav", "nrfd", "ndac",
1431 "ifc", "srq", "atn", "ren", NULL,
1435 "lpc", (const char *[]){
1437 "lad0", "lad1", "lad2", "lad3",
1442 "lpc-opt", (const char *[]){
1444 "lad0", "lad1", "lad2", "lad3",
1445 "lreset", "ldrq", "serirq", "clkrun",
1446 "lpme", "lpcpd", "lsmi",
1451 "mcs48", (const char *[]){
1453 "d0", "d1", "d2", "d3",
1454 "d4", "d5", "d6", "d7",
1455 "a8", "a9", "a10", "a11",
1461 "microwire", (const char *[]){
1462 "cs", "sk", "si", "so", NULL,
1466 "sdcard_sd", (const char *[]){
1468 "dat0", "dat1", "dat2", "dat3",
1473 "seven_segment", (const char *[]){
1474 "a", "b", "c", "d", "e", "f", "g",
1479 "spi", (const char *[]){
1480 "clk", "miso", "mosi", "cs", NULL,
1484 "swd", (const char *[]){
1485 "swclk", "swdio", NULL,
1489 "uart", (const char *[]){
1494 "usb", (const char *[]){
1499 "z80", (const char *[]){
1500 "d0", "d1", "d2", "d3",
1501 "d4", "d5", "d6", "d7",
1504 "a0", "a1", "a2", "a3",
1505 "a4", "a5", "a6", "a7",
1506 "a8", "a9", "a10", "a11",
1507 "a12", "a13", "a14", "a15",
1513 /* Case insensitive lookup of an alias name. */
1514 static const char **lookup_probe_alias(const char *name)
1518 for (idx = 0; idx < ARRAY_SIZE(probe_name_aliases); idx++) {
1519 if (g_ascii_strcasecmp(probe_name_aliases[idx].name, name) != 0)
1521 return probe_name_aliases[idx].expands;
1527 * Parse a probe names specification, allocate a string vector.
1529 * @param[in] spec The input spec, list of probes or aliases.
1530 * @param[in] dflt_names The default probe names, a string array.
1531 * @param[in] dflt_count The default probe names count. Either must
1532 * match the unterminated array size, or can be 0 when the
1533 * default names are NULL terminated.
1534 * @param[in] max_count Optional resulting vector size limit.
1535 * @param[out] ret_count Optional result vector size (return value).
1537 * @returns A string vector with resulting probe names. Or #NULL
1538 * in case of failure.
1540 * The input spec is a comma separated list of probe names. Items can
1541 * be aliases which expand to a corresponding set of signal names.
1542 * The resulting names list optionally gets padded from the caller's
1543 * builtin probe names, an empty input spec yields the original names
1544 * as provided by the caller. Padding is omitted when the spec starts
1545 * with '-', which may result in a device with fewer channels being
1546 * created, enough to cover the user's spec, but none extra to maybe
1547 * enable and use later on. An optional maximum length spec will trim
1548 * the result set to that size. The resulting vector length optionally
1549 * is returned to the caller, so that it need not re-get the length.
1551 * Calling applications must release the allocated vector by means
1552 * of @ref sr_free_probe_names().
1556 SR_API char **sr_parse_probe_names(const char *spec,
1557 const char **dflt_names, size_t dflt_count,
1558 size_t max_count, size_t *ret_count)
1560 char **result_names;
1561 size_t result_count;
1562 gboolean pad_from_dflt;
1563 char **spec_names, *spec_name;
1565 const char **alias_names;
1567 if (!spec || !*spec)
1571 * Accept zero length spec for default input names. Determine
1572 * the name table's length here. Cannot re-use g_strv_length()
1573 * because of the 'const' decoration in application code.
1576 while (dflt_names && dflt_names[dflt_count])
1583 * Start with an empty resulting names table. Will grow
1584 * dynamically as more names get appended.
1586 result_names = NULL;
1588 pad_from_dflt = TRUE;
1591 * When an input spec exists, use its content. Lookup alias
1592 * names, and append their corresponding signals. Or append
1593 * the verbatim input name if it is not an alias. Recursion
1594 * is not supported in this implementation.
1596 * A leading '-' before the signal names list suppresses the
1597 * padding of the resulting list from the device's default
1601 if (spec && *spec == '-') {
1603 pad_from_dflt = FALSE;
1606 spec_names = g_strsplit(spec, ",", 0);
1607 for (spec_idx = 0; spec_names && spec_names[spec_idx]; spec_idx++) {
1608 spec_name = spec_names[spec_idx];
1611 alias_names = lookup_probe_alias(spec_name);
1613 result_names = append_probe_names(result_names,
1614 &result_count, alias_names);
1616 result_names = append_probe_name(result_names,
1617 &result_count, spec_name);
1620 g_strfreev(spec_names);
1623 * By default pad the resulting names from the caller's
1624 * probe names. Don't pad if the input spec started with
1625 * '-', when the spec's exact length was requested.
1627 if (pad_from_dflt) do {
1628 if (max_count && result_count >= max_count)
1630 if (result_count >= dflt_count)
1632 result_names = append_probe_name(result_names, &result_count,
1633 dflt_names[result_count]);
1636 /* Optionally trim the result to the caller's length limit. */
1638 while (result_count > max_count) {
1640 g_free(result_names[result_count]);
1641 result_names[result_count] = NULL;
1646 *ret_count = result_count;
1648 return result_names;
1652 * Release previously allocated probe names (string vector).
1654 * @param[in] names The previously allocated string vector.
1658 SR_API void sr_free_probe_names(char **names)