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)
794 s = g_string_sized_new(i);
795 for (i = 0; i < len; i++) {
797 g_string_append_c(s, ' ');
798 if (i && (i % 8) == 0)
799 g_string_append_c(s, ' ');
800 if (i && (i % 16) == 0)
801 g_string_append_c(s, ' ');
802 g_string_append_printf(s, "%02x", data[i]);
809 * Free a hex dump text that was created by sr_hexdump_new().
811 * @param[in] s Pointer to the GString to release.
815 SR_PRIV void sr_hexdump_free(GString *s)
818 g_string_free(s, TRUE);
822 * Convert a string representation of a numeric value to a sr_rational.
824 * The conversion is strict and will fail if the complete string does not
825 * represent a valid number. The function sets errno according to the details
826 * of the failure. This version ignores the locale.
828 * @param str The string representation to convert.
829 * @param ret Pointer to sr_rational where the result of the conversion will be stored.
831 * @retval SR_OK Conversion successful.
832 * @retval SR_ERR Failure.
836 SR_API int sr_parse_rational(const char *str, struct sr_rational *ret)
840 gboolean is_negative, empty_integral, empty_fractional, exp_negative;
844 uint32_t fractional_len;
848 * Implementor's note: This routine tries hard to avoid calling
849 * glib's or the platform's conversion routines with input that
850 * cannot get converted *at all* (see bug #1093). It also takes
851 * care to return with non-zero errno values for any failed
852 * conversion attempt. It's assumed that correctness and robustness
853 * are more important than performance, which is why code paths
854 * are not optimized at all. Maintainability took priority.
859 /* Skip leading whitespace. */
860 while (isspace(*readptr))
863 /* Determine the sign, default to non-negative. */
865 if (*readptr == '-') {
868 } else if (*readptr == '+') {
873 /* Get the (optional) integral part. */
874 empty_integral = TRUE;
876 endptr = (char *)readptr;
878 if (isdigit(*readptr)) {
879 empty_integral = FALSE;
880 integral = g_ascii_strtoll(readptr, &endptr, 10);
890 /* Get the optional fractional part. */
891 empty_fractional = TRUE;
894 if (*readptr == '.') {
898 if (isdigit(*readptr)) {
899 empty_fractional = FALSE;
900 fractional = g_ascii_strtoll(readptr, &endptr, 10);
903 if (endptr == readptr) {
907 fractional_len = endptr - readptr;
912 /* At least one of integral or fractional is required. */
913 if (empty_integral && empty_fractional) {
918 /* Get the (optional) exponent. */
920 if ((*readptr == 'E') || (*readptr == 'e')) {
923 exp_negative = FALSE;
924 if (*readptr == '+') {
925 exp_negative = FALSE;
928 } else if (*readptr == '-') {
933 if (!isdigit(*readptr)) {
938 exponent = g_ascii_strtoll(readptr, &endptr, 10);
941 if (endptr == readptr) {
947 exponent = -exponent;
950 /* Input must be exhausted. Unconverted remaining input is fatal. */
951 if (*endptr != '\0') {
957 * Apply the sign to the integral (and fractional) part(s).
958 * Adjust exponent (decimal position) such that the above integral
959 * and fractional parts both fit into the (new) integral part.
962 integral = -integral;
963 while (fractional_len-- > 0) {
968 integral += fractional;
970 integral -= fractional;
971 while (exponent > 0) {
977 * When significant digits remain after the decimal, scale up the
978 * denominator such that we end up with two integer p/q numbers.
981 while (exponent < 0) {
987 ret->q = denominator;
993 * Convert a numeric value value to its "natural" string representation
996 * E.g. a value of 3000000, with units set to "W", would be converted
997 * to "3 MW", 20000 to "20 kW", 31500 would become "31.5 kW".
999 * @param x The value to convert.
1000 * @param unit The unit to append to the string, or NULL if the string
1003 * @return A newly allocated string representation of the samplerate value,
1004 * or NULL upon errors. The caller is responsible to g_free() the
1009 SR_API char *sr_si_string_u64(uint64_t x, const char *unit)
1012 uint64_t quot, divisor[] = {
1013 SR_HZ(1), SR_KHZ(1), SR_MHZ(1), SR_GHZ(1),
1014 SR_GHZ(1000), SR_GHZ(1000 * 1000), SR_GHZ(1000 * 1000 * 1000),
1016 const char *p, prefix[] = "\0kMGTPE";
1017 char fmt[16], fract[20] = "", *f;
1022 for (i = 0; (quot = x / divisor[i]) >= 1000; i++);
1025 sprintf(fmt, ".%%0%d"PRIu64, i * 3);
1026 f = fract + sprintf(fract, fmt, x % divisor[i]) - 1;
1028 while (f >= fract && strchr("0.", *f))
1034 return g_strdup_printf("%" PRIu64 "%s %.1s%s", quot, fract, p, unit);
1038 * Convert a numeric samplerate value to its "natural" string representation.
1040 * E.g. a value of 3000000 would be converted to "3 MHz", 20000 to "20 kHz",
1041 * 31500 would become "31.5 kHz".
1043 * @param samplerate The samplerate in Hz.
1045 * @return A newly allocated string representation of the samplerate value,
1046 * or NULL upon errors. The caller is responsible to g_free() the
1051 SR_API char *sr_samplerate_string(uint64_t samplerate)
1053 return sr_si_string_u64(samplerate, "Hz");
1057 * Convert a numeric period value to the "natural" string representation
1058 * of its period value.
1060 * The period is specified as a rational number's numerator and denominator.
1062 * E.g. a pair of (1, 5) would be converted to "200 ms", (10, 100) to "100 ms".
1064 * @param v_p The period numerator.
1065 * @param v_q The period denominator.
1067 * @return A newly allocated string representation of the period value,
1068 * or NULL upon errors. The caller is responsible to g_free() the
1073 SR_API char *sr_period_string(uint64_t v_p, uint64_t v_q)
1078 freq = 1 / ((double)v_p / v_q);
1080 if (freq > SR_GHZ(1)) {
1081 v = (double)v_p / v_q * 1000000000000.0;
1082 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1083 return g_strdup_printf("%.*f ps", prec, v);
1084 } else if (freq > SR_MHZ(1)) {
1085 v = (double)v_p / v_q * 1000000000.0;
1086 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1087 return g_strdup_printf("%.*f ns", prec, v);
1088 } else if (freq > SR_KHZ(1)) {
1089 v = (double)v_p / v_q * 1000000.0;
1090 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1091 return g_strdup_printf("%.*f us", prec, v);
1092 } else if (freq > 1) {
1093 v = (double)v_p / v_q * 1000.0;
1094 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1095 return g_strdup_printf("%.*f ms", prec, v);
1097 v = (double)v_p / v_q;
1098 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1099 return g_strdup_printf("%.*f s", prec, v);
1104 * Convert a numeric voltage value to the "natural" string representation
1105 * of its voltage value. The voltage is specified as a rational number's
1106 * numerator and denominator.
1108 * E.g. a value of 300000 would be converted to "300mV", 2 to "2V".
1110 * @param v_p The voltage numerator.
1111 * @param v_q The voltage denominator.
1113 * @return A newly allocated string representation of the voltage value,
1114 * or NULL upon errors. The caller is responsible to g_free() the
1119 SR_API char *sr_voltage_string(uint64_t v_p, uint64_t v_q)
1122 return g_strdup_printf("%" PRIu64 " mV", v_p);
1124 return g_strdup_printf("%" PRIu64 " V", v_p);
1126 return g_strdup_printf("%g V", (float)v_p / (float)v_q);
1130 * Convert a "natural" string representation of a size value to uint64_t.
1132 * E.g. a value of "3k" or "3 K" would be converted to 3000, a value
1133 * of "15M" would be converted to 15000000.
1135 * Value representations other than decimal (such as hex or octal) are not
1136 * supported. Only 'k' (kilo), 'm' (mega), 'g' (giga) suffixes are supported.
1137 * Spaces (but not other whitespace) between value and suffix are allowed.
1139 * @param sizestring A string containing a (decimal) size value.
1140 * @param size Pointer to uint64_t which will contain the string's size value.
1142 * @return SR_OK upon success, SR_ERR upon errors.
1146 SR_API int sr_parse_sizestring(const char *sizestring, uint64_t *size)
1148 uint64_t multiplier;
1153 *size = strtoull(sizestring, &s, 10);
1157 while (s && *s && multiplier == 0 && !done) {
1162 frac_part = g_ascii_strtod(s, &s);
1166 multiplier = SR_KHZ(1);
1170 multiplier = SR_MHZ(1);
1174 multiplier = SR_GHZ(1);
1178 multiplier = SR_GHZ(1000);
1182 multiplier = SR_GHZ(1000 * 1000);
1186 multiplier = SR_GHZ(1000 * 1000 * 1000);
1194 if (multiplier > 0) {
1195 *size *= multiplier;
1196 *size += frac_part * multiplier;
1201 if (s && *s && g_ascii_strcasecmp(s, "Hz"))
1208 * Convert a "natural" string representation of a time value to an
1209 * uint64_t value in milliseconds.
1211 * E.g. a value of "3s" or "3 s" would be converted to 3000, a value
1212 * of "15ms" would be converted to 15.
1214 * Value representations other than decimal (such as hex or octal) are not
1215 * supported. Only lower-case "s" and "ms" time suffixes are supported.
1216 * Spaces (but not other whitespace) between value and suffix are allowed.
1218 * @param timestring A string containing a (decimal) time value.
1219 * @return The string's time value as uint64_t, in milliseconds.
1221 * @todo Add support for "m" (minutes) and others.
1222 * @todo Add support for picoseconds?
1223 * @todo Allow both lower-case and upper-case? If no, document it.
1227 SR_API uint64_t sr_parse_timestring(const char *timestring)
1232 /* TODO: Error handling, logging. */
1234 time_msec = strtoull(timestring, &s, 10);
1235 if (time_msec == 0 && s == timestring)
1241 if (!strcmp(s, "s"))
1243 else if (!strcmp(s, "ms"))
1253 SR_API gboolean sr_parse_boolstring(const char *boolstr)
1256 * Complete absence of an input spec is assumed to mean TRUE,
1257 * as in command line option strings like this:
1258 * ...:samplerate=100k:header:numchannels=4:...
1260 if (!boolstr || !*boolstr)
1263 if (!g_ascii_strncasecmp(boolstr, "true", 4) ||
1264 !g_ascii_strncasecmp(boolstr, "yes", 3) ||
1265 !g_ascii_strncasecmp(boolstr, "on", 2) ||
1266 !g_ascii_strncasecmp(boolstr, "1", 1))
1273 SR_API int sr_parse_period(const char *periodstr, uint64_t *p, uint64_t *q)
1277 *p = strtoull(periodstr, &s, 10);
1278 if (*p == 0 && s == periodstr)
1279 /* No digits found. */
1285 if (!strcmp(s, "fs"))
1286 *q = UINT64_C(1000000000000000);
1287 else if (!strcmp(s, "ps"))
1288 *q = UINT64_C(1000000000000);
1289 else if (!strcmp(s, "ns"))
1290 *q = UINT64_C(1000000000);
1291 else if (!strcmp(s, "us"))
1293 else if (!strcmp(s, "ms"))
1295 else if (!strcmp(s, "s"))
1298 /* Must have a time suffix. */
1306 SR_API int sr_parse_voltage(const char *voltstr, uint64_t *p, uint64_t *q)
1310 *p = strtoull(voltstr, &s, 10);
1311 if (*p == 0 && s == voltstr)
1312 /* No digits found. */
1318 if (!g_ascii_strcasecmp(s, "mv"))
1320 else if (!g_ascii_strcasecmp(s, "v"))
1323 /* Must have a base suffix. */
1331 * Append another text item to a NULL terminated string vector.
1333 * @param[in] table The previous string vector.
1334 * @param[in,out] sz The previous and the resulting vector size
1336 * @param[in] text The text string to append to the vector.
1339 * @returns The new vector, its location can differ from 'table'.
1340 * Or #NULL in case of failure.
1342 * This implementation happens to work for the first invocation when
1343 * 'table' is #NULL and 'sz' is 0, as well as subsequent append calls.
1344 * The 'text' can be #NULL or can be a non-empty string. When 'sz' is
1345 * not provided, then the 'table' must be a NULL terminated vector,
1346 * so that the routine can auto-determine the vector's current length.
1348 * This routine re-allocates the vector as needed. Callers must not
1349 * rely on the memory address to remain the same across calls.
1351 static char **append_probe_name(char **table, size_t *sz, const char *text)
1353 size_t curr_size, alloc_size;
1356 /* Get the table's previous size (item count). */
1360 curr_size = g_strv_length(table);
1364 /* Extend storage to hold one more item, and the termination. */
1365 alloc_size = curr_size + (text ? 1 : 0) + 1;
1366 alloc_size *= sizeof(table[0]);
1367 new_table = g_realloc(table, alloc_size);
1375 /* Append the item, NULL terminate. */
1377 new_table[curr_size] = g_strdup(text);
1378 if (!new_table[curr_size]) {
1379 g_strfreev(new_table);
1388 new_table[curr_size] = NULL;
1393 static char **append_probe_names(char **table, size_t *sz,
1400 table = append_probe_name(table, sz, names[0]);
1406 static const struct {
1408 const char **expands;
1409 } probe_name_aliases[] = {
1411 "ac97", (const char *[]){
1418 "i2c", (const char *[]){
1423 "jtag", (const char *[]){
1424 "tdi", "tdo", "tck", "tms", NULL,
1428 "jtag-opt", (const char *[]){
1429 "tdi", "tdo", "tck", "tms",
1430 "trst", "srst", "rtck", NULL,
1434 "ieee488", (const char *[]){
1435 "dio1", "dio2", "dio3", "dio4",
1436 "dio5", "dio6", "dio7", "dio8",
1437 "eoi", "dav", "nrfd", "ndac",
1438 "ifc", "srq", "atn", "ren", NULL,
1442 "lpc", (const char *[]){
1444 "lad0", "lad1", "lad2", "lad3",
1449 "lpc-opt", (const char *[]){
1451 "lad0", "lad1", "lad2", "lad3",
1452 "lreset", "ldrq", "serirq", "clkrun",
1453 "lpme", "lpcpd", "lsmi",
1458 "mcs48", (const char *[]){
1460 "d0", "d1", "d2", "d3",
1461 "d4", "d5", "d6", "d7",
1462 "a8", "a9", "a10", "a11",
1468 "microwire", (const char *[]){
1469 "cs", "sk", "si", "so", NULL,
1473 "sdcard_sd", (const char *[]){
1475 "dat0", "dat1", "dat2", "dat3",
1480 "seven_segment", (const char *[]){
1481 "a", "b", "c", "d", "e", "f", "g",
1486 "spi", (const char *[]){
1487 "clk", "miso", "mosi", "cs", NULL,
1491 "swd", (const char *[]){
1492 "swclk", "swdio", NULL,
1496 "uart", (const char *[]){
1501 "usb", (const char *[]){
1506 "z80", (const char *[]){
1507 "d0", "d1", "d2", "d3",
1508 "d4", "d5", "d6", "d7",
1511 "a0", "a1", "a2", "a3",
1512 "a4", "a5", "a6", "a7",
1513 "a8", "a9", "a10", "a11",
1514 "a12", "a13", "a14", "a15",
1520 /* Case insensitive lookup of an alias name. */
1521 static const char **lookup_probe_alias(const char *name)
1525 for (idx = 0; idx < ARRAY_SIZE(probe_name_aliases); idx++) {
1526 if (g_ascii_strcasecmp(probe_name_aliases[idx].name, name) != 0)
1528 return probe_name_aliases[idx].expands;
1534 * Parse a probe names specification, allocate a string vector.
1536 * @param[in] spec The input spec, list of probes or aliases.
1537 * @param[in] dflt_names The default probe names, a string array.
1538 * @param[in] dflt_count The default probe names count. Either must
1539 * match the unterminated array size, or can be 0 when the
1540 * default names are NULL terminated.
1541 * @param[in] max_count Optional resulting vector size limit.
1542 * @param[out] ret_count Optional result vector size (return value).
1544 * @returns A string vector with resulting probe names. Or #NULL
1545 * in case of failure.
1547 * The input spec is a comma separated list of probe names. Items can
1548 * be aliases which expand to a corresponding set of signal names.
1549 * The resulting names list optionally gets padded from the caller's
1550 * builtin probe names, an empty input spec yields the original names
1551 * as provided by the caller. Padding is omitted when the spec starts
1552 * with '-', which may result in a device with fewer channels being
1553 * created, enough to cover the user's spec, but none extra to maybe
1554 * enable and use later on. An optional maximum length spec will trim
1555 * the result set to that size. The resulting vector length optionally
1556 * is returned to the caller, so that it need not re-get the length.
1558 * Calling applications must release the allocated vector by means
1559 * of @ref sr_free_probe_names().
1563 SR_API char **sr_parse_probe_names(const char *spec,
1564 const char **dflt_names, size_t dflt_count,
1565 size_t max_count, size_t *ret_count)
1567 char **result_names;
1568 size_t result_count;
1569 gboolean pad_from_dflt;
1570 char **spec_names, *spec_name;
1572 const char **alias_names;
1574 if (!spec || !*spec)
1578 * Accept zero length spec for default input names. Determine
1579 * the name table's length here. Cannot re-use g_strv_length()
1580 * because of the 'const' decoration in application code.
1583 while (dflt_names && dflt_names[dflt_count])
1590 * Start with an empty resulting names table. Will grow
1591 * dynamically as more names get appended.
1593 result_names = NULL;
1595 pad_from_dflt = TRUE;
1598 * When an input spec exists, use its content. Lookup alias
1599 * names, and append their corresponding signals. Or append
1600 * the verbatim input name if it is not an alias. Recursion
1601 * is not supported in this implementation.
1603 * A leading '-' before the signal names list suppresses the
1604 * padding of the resulting list from the device's default
1608 if (spec && *spec == '-') {
1610 pad_from_dflt = FALSE;
1613 spec_names = g_strsplit(spec, ",", 0);
1614 for (spec_idx = 0; spec_names && spec_names[spec_idx]; spec_idx++) {
1615 spec_name = spec_names[spec_idx];
1618 alias_names = lookup_probe_alias(spec_name);
1620 result_names = append_probe_names(result_names,
1621 &result_count, alias_names);
1623 result_names = append_probe_name(result_names,
1624 &result_count, spec_name);
1627 g_strfreev(spec_names);
1630 * By default pad the resulting names from the caller's
1631 * probe names. Don't pad if the input spec started with
1632 * '-', when the spec's exact length was requested.
1634 if (pad_from_dflt) do {
1635 if (max_count && result_count >= max_count)
1637 if (result_count >= dflt_count)
1639 result_names = append_probe_name(result_names, &result_count,
1640 dflt_names[result_count]);
1643 /* Optionally trim the result to the caller's length limit. */
1645 while (result_count > max_count) {
1647 g_free(result_names[result_count]);
1648 result_names[result_count] = NULL;
1653 *ret_count = result_count;
1655 return result_names;
1659 * Release previously allocated probe names (string vector).
1661 * @param[in] names The previously allocated string vector.
1665 SR_API void sr_free_probe_names(char **names)