]> sigrok.org Git - libsigrok.git/blob - src/strutil.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / strutil.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 /* Needed for POSIX.1-2008 locale functions */
21 /** @cond PRIVATE */
22 #define _XOPEN_SOURCE 700
23 /** @endcond */
24 #include <config.h>
25 #include <ctype.h>
26 #include <locale.h>
27 #if defined(__FreeBSD__) || defined(__APPLE__)
28 #include <xlocale.h>
29 #endif
30 #if defined(__FreeBSD__)
31 #include <sys/param.h>
32 #endif
33 #include <stdint.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <strings.h>
37 #include <errno.h>
38 #include <libsigrok/libsigrok.h>
39 #include "libsigrok-internal.h"
40
41 /** @cond PRIVATE */
42 #define LOG_PREFIX "strutil"
43 /** @endcond */
44
45 /**
46  * @file
47  *
48  * Helper functions for handling or converting libsigrok-related strings.
49  */
50
51 /**
52  * @defgroup grp_strutil String utilities
53  *
54  * Helper functions for handling or converting libsigrok-related strings.
55  *
56  * @{
57  */
58
59 /**
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
63  * failure.
64  *
65  * @param str The string representation to convert.
66  * @param ret Pointer to long where the result of the conversion will be stored.
67  *
68  * @retval SR_OK Conversion successful.
69  * @retval SR_ERR Failure.
70  *
71  * @private
72  */
73 SR_PRIV int sr_atol(const char *str, long *ret)
74 {
75         long tmp;
76         char *endptr = NULL;
77
78         errno = 0;
79         tmp = strtol(str, &endptr, 10);
80
81         while (endptr && isspace(*endptr))
82                 endptr++;
83
84         if (!endptr || *endptr || errno) {
85                 if (!errno)
86                         errno = EINVAL;
87                 return SR_ERR;
88         }
89
90         *ret = tmp;
91         return SR_OK;
92 }
93
94 /**
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.
98  *
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.
103  *
104  * @retval SR_OK Conversion successful.
105  * @retval SR_ERR Conversion failed.
106  *
107  * @private
108  *
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.
114  */
115 SR_PRIV int sr_atol_base(const char *str, long *ret, char **end, int base)
116 {
117         long num;
118         char *endptr;
119
120         /* Add "0b" prefix support which strtol(3) may be missing. */
121         while (str && isspace(*str))
122                 str++;
123         if (!base && strncmp(str, "0b", strlen("0b")) == 0) {
124                 str += strlen("0b");
125                 base = 2;
126         }
127
128         /* Run the number conversion. Quick bail out if that fails. */
129         errno = 0;
130         endptr = NULL;
131         num = strtol(str, &endptr, base);
132         if (!endptr || errno) {
133                 if (!errno)
134                         errno = EINVAL;
135                 return SR_ERR;
136         }
137         *ret = num;
138
139         /* Advance to optional non-space trailing suffix. */
140         while (endptr && isspace(*endptr))
141                 endptr++;
142         if (end)
143                 *end = endptr;
144
145         return SR_OK;
146 }
147
148 /**
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.
152  *
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.
157  *
158  * @retval SR_OK Conversion successful.
159  * @retval SR_ERR Conversion failed.
160  *
161  * @private
162  *
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.
168  */
169 SR_PRIV int sr_atoul_base(const char *str, unsigned long *ret, char **end, int base)
170 {
171         unsigned long num;
172         char *endptr;
173
174         /* Add "0b" prefix support which strtol(3) may be missing. */
175         while (str && isspace(*str))
176                 str++;
177         if ((!base || base == 2) && strncmp(str, "0b", strlen("0b")) == 0) {
178                 str += strlen("0b");
179                 base = 2;
180         }
181
182         /* Run the number conversion. Quick bail out if that fails. */
183         errno = 0;
184         endptr = NULL;
185         num = strtoul(str, &endptr, base);
186         if (!endptr || errno) {
187                 if (!errno)
188                         errno = EINVAL;
189                 return SR_ERR;
190         }
191         *ret = num;
192
193         /* Advance to optional non-space trailing suffix. */
194         while (endptr && isspace(*endptr))
195                 endptr++;
196         if (end)
197                 *end = endptr;
198
199         return SR_OK;
200 }
201
202 /**
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
206  * failure.
207  *
208  * @param str The string representation to convert.
209  * @param ret Pointer to int where the result of the conversion will be stored.
210  *
211  * @retval SR_OK Conversion successful.
212  * @retval SR_ERR Failure.
213  *
214  * @private
215  */
216 SR_PRIV int sr_atoi(const char *str, int *ret)
217 {
218         long tmp;
219
220         if (sr_atol(str, &tmp) != SR_OK)
221                 return SR_ERR;
222
223         if ((int) tmp != tmp) {
224                 errno = ERANGE;
225                 return SR_ERR;
226         }
227
228         *ret = (int) tmp;
229         return SR_OK;
230 }
231
232 /**
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
236  * failure.
237  *
238  * @param str The string representation to convert.
239  * @param ret Pointer to double where the result of the conversion will be stored.
240  *
241  * @retval SR_OK Conversion successful.
242  * @retval SR_ERR Failure.
243  *
244  * @private
245  */
246 SR_PRIV int sr_atod(const char *str, double *ret)
247 {
248         double tmp;
249         char *endptr = NULL;
250
251         errno = 0;
252         tmp = strtof(str, &endptr);
253
254         while (endptr && isspace(*endptr))
255                 endptr++;
256
257         if (!endptr || *endptr || errno) {
258                 if (!errno)
259                         errno = EINVAL;
260                 return SR_ERR;
261         }
262
263         *ret = tmp;
264         return SR_OK;
265 }
266
267 /**
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
271  * failure.
272  *
273  * @param str The string representation to convert.
274  * @param ret Pointer to float where the result of the conversion will be stored.
275  *
276  * @retval SR_OK Conversion successful.
277  * @retval SR_ERR Failure.
278  *
279  * @private
280  */
281 SR_PRIV int sr_atof(const char *str, float *ret)
282 {
283         double tmp;
284
285         if (sr_atod(str, &tmp) != SR_OK)
286                 return SR_ERR;
287
288         if ((float) tmp != tmp) {
289                 errno = ERANGE;
290                 return SR_ERR;
291         }
292
293         *ret = (float) tmp;
294         return SR_OK;
295 }
296
297 /**
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.
302  *
303  * @param str The string representation to convert.
304  * @param ret Pointer to double where the result of the conversion will be stored.
305  *
306  * @retval SR_OK Conversion successful.
307  * @retval SR_ERR Failure.
308  *
309  * @private
310  */
311 SR_PRIV int sr_atod_ascii(const char *str, double *ret)
312 {
313         double tmp;
314         char *endptr = NULL;
315
316         errno = 0;
317         tmp = g_ascii_strtod(str, &endptr);
318
319         if (!endptr || *endptr || errno) {
320                 if (!errno)
321                         errno = EINVAL;
322                 return SR_ERR;
323         }
324
325         *ret = tmp;
326         return SR_OK;
327 }
328
329 /**
330  * Convert text to a floating point value, and get its precision.
331  *
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.
335  *
336  * @returns SR_OK in case of successful text to number conversion.
337  * @returns SR_ERR when conversion fails.
338  *
339  * @since 0.6.0
340  */
341 SR_PRIV int sr_atod_ascii_digits(const char *str, double *ret, int *digits)
342 {
343         const char *p;
344         int *dig_ref, m_dig, exp;
345         char c;
346         double f;
347
348         /*
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.
354          *
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.
358          */
359         p = str;
360         while (*p && isspace(*p))
361                 p++;
362         if (*p == '-' || *p == '+')
363                 p++;
364         m_dig = 0;
365         exp = 0;
366         dig_ref = NULL;
367         while (*p) {
368                 c = *p++;
369                 if (toupper(c) == 'E') {
370                         exp = strtol(p, NULL, 10);
371                         break;
372                 }
373                 if (c == '.') {
374                         m_dig = 0;
375                         dig_ref = &m_dig;
376                         continue;
377                 }
378                 if (isdigit(c)) {
379                         if (dig_ref)
380                                 (*dig_ref)++;
381                         continue;
382                 }
383                 /* Need not warn, conversion will fail. */
384                 break;
385         }
386         sr_spew("atod digits: txt \"%s\" -> m %d, e %d -> digits %d",
387                 str, m_dig, exp, m_dig + -exp);
388         m_dig += -exp;
389
390         if (sr_atod_ascii(str, &f) != SR_OK)
391                 return SR_ERR;
392         if (ret)
393                 *ret = f;
394         if (digits)
395                 *digits = m_dig;
396
397         return SR_OK;
398 }
399
400 /**
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.
405  *
406  * @param str The string representation to convert.
407  * @param ret Pointer to float where the result of the conversion will be stored.
408  *
409  * @retval SR_OK Conversion successful.
410  * @retval SR_ERR Failure.
411  *
412  * @private
413  */
414 SR_PRIV int sr_atof_ascii(const char *str, float *ret)
415 {
416         double tmp;
417         char *endptr = NULL;
418
419         errno = 0;
420         tmp = g_ascii_strtod(str, &endptr);
421
422         if (!endptr || *endptr || errno) {
423                 if (!errno)
424                         errno = EINVAL;
425                 return SR_ERR;
426         }
427
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. */
430         /*
431         if ((float) tmp != tmp) {
432                 errno = ERANGE;
433                 sr_dbg("ERANGEEEE %e != %e", (float) tmp, tmp);
434                 return SR_ERR;
435         }
436         */
437
438         *ret = (float) tmp;
439         return SR_OK;
440 }
441
442 /**
443  * Compose a string with a format string in the buffer pointed to by buf.
444  *
445  * It is up to the caller to ensure that the allocated buffer is large enough
446  * to hold the formatted result.
447  *
448  * A terminating NUL character is automatically appended after the content
449  * written.
450  *
451  * After the format parameter, the function expects at least as many additional
452  * arguments as needed for format.
453  *
454  * This version ignores the current locale and uses the locale "C" for Linux,
455  * FreeBSD, OSX and Android.
456  *
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.
461  *
462  * @return On success, the number of characters that would have been written,
463  *         not counting the terminating NUL character.
464  *
465  * @since 0.6.0
466  */
467 SR_API int sr_sprintf_ascii(char *buf, const char *format, ...)
468 {
469         int ret;
470         va_list args;
471
472         va_start(args, format);
473         ret = sr_vsprintf_ascii(buf, format, args);
474         va_end(args);
475
476         return ret;
477 }
478
479 /**
480  * Compose a string with a format string in the buffer pointed to by buf.
481  *
482  * It is up to the caller to ensure that the allocated buffer is large enough
483  * to hold the formatted result.
484  *
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.
488  *
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
491  * after the call.
492  *
493  * This version ignores the current locale and uses the locale "C" for Linux,
494  * FreeBSD, OSX and Android.
495  *
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
499  *        va_start.
500  *
501  * @return On success, the number of characters that would have been written,
502  *         not counting the terminating NUL character.
503  *
504  * @since 0.6.0
505  */
506 SR_API int sr_vsprintf_ascii(char *buf, const char *format, va_list args)
507 {
508 #if defined(_WIN32)
509         int ret;
510
511 #if 0
512         /*
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
518          */
519         _locale_t locale;
520
521         locale = _create_locale(LC_NUMERIC, "C");
522         ret = _vsprintf_l(buf, format, locale, args);
523         _free_locale(locale);
524 #endif
525
526         /* vsprintf() uses the current locale, may not work correctly for floats. */
527         ret = vsprintf(buf, format, args);
528
529         return ret;
530 #elif defined(__APPLE__)
531         /*
532          * See:
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
535          */
536         int ret;
537         locale_t locale;
538
539         locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
540         ret = vsprintf_l(buf, locale, format, args);
541         freelocale(locale);
542
543         return ret;
544 #elif defined(__FreeBSD__) && __FreeBSD_version >= 901000
545         /*
546          * See:
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
549          */
550         int ret;
551         locale_t locale;
552
553         locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
554         ret = vsprintf_l(buf, locale, format, args);
555         freelocale(locale);
556
557         return ret;
558 #elif defined(__ANDROID__)
559         /*
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
563          */
564         int ret;
565
566         ret = vsprintf(buf, format, args);
567
568         return ret;
569 #elif defined(__linux__)
570         int ret;
571         locale_t old_locale, temp_locale;
572
573         /* Switch to C locale for proper float/double conversion. */
574         temp_locale = newlocale(LC_NUMERIC, "C", NULL);
575         old_locale = uselocale(temp_locale);
576
577         ret = vsprintf(buf, format, args);
578
579         /* Switch back to original locale. */
580         uselocale(old_locale);
581         freelocale(temp_locale);
582
583         return ret;
584 #elif defined(__unix__) || defined(__unix)
585         /*
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
588          * for floats!
589          */
590         int ret;
591
592         ret = vsprintf(buf, format, args);
593
594         return ret;
595 #else
596         /* No implementation for unknown systems! */
597         return -1;
598 #endif
599 }
600
601 /**
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
606  * by the function.
607  * A terminating NUL character is automatically appended after the content
608  * written.
609  * After the format parameter, the function expects at least as many additional
610  * arguments as needed for format.
611  *
612  * This version ignores the current locale and uses the locale "C" for Linux,
613  * FreeBSD, OSX and Android.
614  *
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.
622  *
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.
628  *
629  * @since 0.6.0
630  */
631 SR_API int sr_snprintf_ascii(char *buf, size_t buf_size,
632         const char *format, ...)
633 {
634         int ret;
635         va_list args;
636
637         va_start(args, format);
638         ret = sr_vsnprintf_ascii(buf, buf_size, format, args);
639         va_end(args);
640
641         return ret;
642 }
643
644 /**
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
649  * by the function.
650  * A terminating NUL character is automatically appended after the content
651  * written.
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
657  * after the call.
658  *
659  * This version ignores the current locale and uses the locale "C" for Linux,
660  * FreeBSD, OSX and Android.
661  *
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
668  *        va_start.
669  *
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.
675  *
676  * @since 0.6.0
677  */
678 SR_API int sr_vsnprintf_ascii(char *buf, size_t buf_size,
679         const char *format, va_list args)
680 {
681 #if defined(_WIN32)
682         int ret;
683
684 #if 0
685         /*
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
691          */
692         _locale_t locale;
693
694         locale = _create_locale(LC_NUMERIC, "C");
695         ret = _vsnprintf_l(buf, buf_size, format, locale, args);
696         _free_locale(locale);
697 #endif
698
699         /* vsprintf uses the current locale, may cause issues for floats. */
700         ret = vsnprintf(buf, buf_size, format, args);
701
702         return ret;
703 #elif defined(__APPLE__)
704         /*
705          * See:
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
708          */
709         int ret;
710         locale_t locale;
711
712         locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
713         ret = vsnprintf_l(buf, buf_size, locale, format, args);
714         freelocale(locale);
715
716         return ret;
717 #elif defined(__FreeBSD__) && __FreeBSD_version >= 901000
718         /*
719          * See:
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
722          */
723         int ret;
724         locale_t locale;
725
726         locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
727         ret = vsnprintf_l(buf, buf_size, locale, format, args);
728         freelocale(locale);
729
730         return ret;
731 #elif defined(__ANDROID__)
732         /*
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
736          */
737         int ret;
738
739         ret = vsnprintf(buf, buf_size, format, args);
740
741         return ret;
742 #elif defined(__linux__)
743         int ret;
744         locale_t old_locale, temp_locale;
745
746         /* Switch to C locale for proper float/double conversion. */
747         temp_locale = newlocale(LC_NUMERIC, "C", NULL);
748         old_locale = uselocale(temp_locale);
749
750         ret = vsnprintf(buf, buf_size, format, args);
751
752         /* Switch back to original locale. */
753         uselocale(old_locale);
754         freelocale(temp_locale);
755
756         return ret;
757 #elif defined(__unix__) || defined(__unix)
758         /*
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
761          * for floats!
762          */
763         int ret;
764
765         ret = vsnprintf(buf, buf_size, format, args);
766
767         return ret;
768 #else
769         /* No implementation for unknown systems! */
770         return -1;
771 #endif
772 }
773
774 /**
775  * Convert a sequence of bytes to its textual representation ("hex dump").
776  *
777  * Callers should free the allocated GString. See sr_hexdump_free().
778  *
779  * @param[in] data Pointer to the byte sequence to print.
780  * @param[in] len Number of bytes to print.
781  *
782  * @return NULL upon error, newly allocated GString pointer otherwise.
783  *
784  * @private
785  */
786 SR_PRIV GString *sr_hexdump_new(const uint8_t *data, const size_t len)
787 {
788         GString *s;
789         size_t i;
790
791         i = 3 * len;
792         i += len / 8;
793         i += len / 16;
794         s = g_string_sized_new(i);
795         for (i = 0; i < len; i++) {
796                 if (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]);
803         }
804
805         return s;
806 }
807
808 /**
809  * Free a hex dump text that was created by sr_hexdump_new().
810  *
811  * @param[in] s Pointer to the GString to release.
812  *
813  * @private
814  */
815 SR_PRIV void sr_hexdump_free(GString *s)
816 {
817         if (s)
818                 g_string_free(s, TRUE);
819 }
820
821 /**
822  * Convert a string representation of a numeric value to a sr_rational.
823  *
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.
827  *
828  * @param str The string representation to convert.
829  * @param ret Pointer to sr_rational where the result of the conversion will be stored.
830  *
831  * @retval SR_OK Conversion successful.
832  * @retval SR_ERR Failure.
833  *
834  * @since 0.5.0
835  */
836 SR_API int sr_parse_rational(const char *str, struct sr_rational *ret)
837 {
838         const char *readptr;
839         char *endptr;
840         gboolean is_negative, empty_integral, empty_fractional, exp_negative;
841         int64_t integral;
842         int64_t fractional;
843         int64_t denominator;
844         uint32_t fractional_len;
845         int32_t exponent;
846
847         /*
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.
855          */
856
857         readptr = str;
858
859         /* Skip leading whitespace. */
860         while (isspace(*readptr))
861                 readptr++;
862
863         /* Determine the sign, default to non-negative. */
864         is_negative = FALSE;
865         if (*readptr == '-') {
866                 is_negative = TRUE;
867                 readptr++;
868         } else if (*readptr == '+') {
869                 is_negative = FALSE;
870                 readptr++;
871         }
872
873         /* Get the (optional) integral part. */
874         empty_integral = TRUE;
875         integral = 0;
876         endptr = (char *)readptr;
877         errno = 0;
878         if (isdigit(*readptr)) {
879                 empty_integral = FALSE;
880                 integral = g_ascii_strtoll(readptr, &endptr, 10);
881                 if (errno)
882                         return SR_ERR;
883                 if (endptr == str) {
884                         errno = -EINVAL;
885                         return SR_ERR;
886                 }
887                 readptr = endptr;
888         }
889
890         /* Get the optional fractional part. */
891         empty_fractional = TRUE;
892         fractional = 0;
893         fractional_len = 0;
894         if (*readptr == '.') {
895                 readptr++;
896                 endptr++;
897                 errno = 0;
898                 if (isdigit(*readptr)) {
899                         empty_fractional = FALSE;
900                         fractional = g_ascii_strtoll(readptr, &endptr, 10);
901                         if (errno)
902                                 return SR_ERR;
903                         if (endptr == readptr) {
904                                 errno = -EINVAL;
905                                 return SR_ERR;
906                         }
907                         fractional_len = endptr - readptr;
908                         readptr = endptr;
909                 }
910         }
911
912         /* At least one of integral or fractional is required. */
913         if (empty_integral && empty_fractional) {
914                 errno = -EINVAL;
915                 return SR_ERR;
916         }
917
918         /* Get the (optional) exponent. */
919         exponent = 0;
920         if ((*readptr == 'E') || (*readptr == 'e')) {
921                 readptr++;
922                 endptr++;
923                 exp_negative = FALSE;
924                 if (*readptr == '+') {
925                         exp_negative = FALSE;
926                         readptr++;
927                         endptr++;
928                 } else if (*readptr == '-') {
929                         exp_negative = TRUE;
930                         readptr++;
931                         endptr++;
932                 }
933                 if (!isdigit(*readptr)) {
934                         errno = -EINVAL;
935                         return SR_ERR;
936                 }
937                 errno = 0;
938                 exponent = g_ascii_strtoll(readptr, &endptr, 10);
939                 if (errno)
940                         return SR_ERR;
941                 if (endptr == readptr) {
942                         errno = -EINVAL;
943                         return SR_ERR;
944                 }
945                 readptr = endptr;
946                 if (exp_negative)
947                         exponent = -exponent;
948         }
949
950         /* Input must be exhausted. Unconverted remaining input is fatal. */
951         if (*endptr != '\0') {
952                 errno = -EINVAL;
953                 return SR_ERR;
954         }
955
956         /*
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.
960          */
961         if (is_negative)
962                 integral = -integral;
963         while (fractional_len-- > 0) {
964                 integral *= 10;
965                 exponent--;
966         }
967         if (!is_negative)
968                 integral += fractional;
969         else
970                 integral -= fractional;
971         while (exponent > 0) {
972                 integral *= 10;
973                 exponent--;
974         }
975
976         /*
977          * When significant digits remain after the decimal, scale up the
978          * denominator such that we end up with two integer p/q numbers.
979          */
980         denominator = 1;
981         while (exponent < 0) {
982                 denominator *= 10;
983                 exponent++;
984         }
985
986         ret->p = integral;
987         ret->q = denominator;
988
989         return SR_OK;
990 }
991
992 /**
993  * Convert a numeric value value to its "natural" string representation
994  * in SI units.
995  *
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".
998  *
999  * @param x The value to convert.
1000  * @param unit The unit to append to the string, or NULL if the string
1001  *             has no units.
1002  *
1003  * @return A newly allocated string representation of the samplerate value,
1004  *         or NULL upon errors. The caller is responsible to g_free() the
1005  *         memory.
1006  *
1007  * @since 0.2.0
1008  */
1009 SR_API char *sr_si_string_u64(uint64_t x, const char *unit)
1010 {
1011         uint8_t i;
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),
1015         };
1016         const char *p, prefix[] = "\0kMGTPE";
1017         char fmt[16], fract[20] = "", *f;
1018
1019         if (!unit)
1020                 unit = "";
1021
1022         for (i = 0; (quot = x / divisor[i]) >= 1000; i++);
1023
1024         if (i) {
1025                 sprintf(fmt, ".%%0%d"PRIu64, i * 3);
1026                 f = fract + sprintf(fract, fmt, x % divisor[i]) - 1;
1027
1028                 while (f >= fract && strchr("0.", *f))
1029                         *f-- = 0;
1030         }
1031
1032         p = prefix + i;
1033
1034         return g_strdup_printf("%" PRIu64 "%s %.1s%s", quot, fract, p, unit);
1035 }
1036
1037 /**
1038  * Convert a numeric samplerate value to its "natural" string representation.
1039  *
1040  * E.g. a value of 3000000 would be converted to "3 MHz", 20000 to "20 kHz",
1041  * 31500 would become "31.5 kHz".
1042  *
1043  * @param samplerate The samplerate in Hz.
1044  *
1045  * @return A newly allocated string representation of the samplerate value,
1046  *         or NULL upon errors. The caller is responsible to g_free() the
1047  *         memory.
1048  *
1049  * @since 0.1.0
1050  */
1051 SR_API char *sr_samplerate_string(uint64_t samplerate)
1052 {
1053         return sr_si_string_u64(samplerate, "Hz");
1054 }
1055
1056 /**
1057  * Convert a numeric period value to the "natural" string representation
1058  * of its period value.
1059  *
1060  * The period is specified as a rational number's numerator and denominator.
1061  *
1062  * E.g. a pair of (1, 5) would be converted to "200 ms", (10, 100) to "100 ms".
1063  *
1064  * @param v_p The period numerator.
1065  * @param v_q The period denominator.
1066  *
1067  * @return A newly allocated string representation of the period value,
1068  *         or NULL upon errors. The caller is responsible to g_free() the
1069  *         memory.
1070  *
1071  * @since 0.5.0
1072  */
1073 SR_API char *sr_period_string(uint64_t v_p, uint64_t v_q)
1074 {
1075         double freq, v;
1076         int prec;
1077
1078         freq = 1 / ((double)v_p / v_q);
1079
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);
1096         } else {
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);
1100         }
1101 }
1102
1103 /**
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.
1107  *
1108  * E.g. a value of 300000 would be converted to "300mV", 2 to "2V".
1109  *
1110  * @param v_p The voltage numerator.
1111  * @param v_q The voltage denominator.
1112  *
1113  * @return A newly allocated string representation of the voltage value,
1114  *         or NULL upon errors. The caller is responsible to g_free() the
1115  *         memory.
1116  *
1117  * @since 0.2.0
1118  */
1119 SR_API char *sr_voltage_string(uint64_t v_p, uint64_t v_q)
1120 {
1121         if (v_q == 1000)
1122                 return g_strdup_printf("%" PRIu64 " mV", v_p);
1123         else if (v_q == 1)
1124                 return g_strdup_printf("%" PRIu64 " V", v_p);
1125         else
1126                 return g_strdup_printf("%g V", (float)v_p / (float)v_q);
1127 }
1128
1129 /**
1130  * Convert a "natural" string representation of a size value to uint64_t.
1131  *
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.
1134  *
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.
1138  *
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.
1141  *
1142  * @return SR_OK upon success, SR_ERR upon errors.
1143  *
1144  * @since 0.1.0
1145  */
1146 SR_API int sr_parse_sizestring(const char *sizestring, uint64_t *size)
1147 {
1148         uint64_t multiplier;
1149         int done;
1150         double frac_part;
1151         char *s;
1152
1153         *size = strtoull(sizestring, &s, 10);
1154         multiplier = 0;
1155         frac_part = 0;
1156         done = FALSE;
1157         while (s && *s && multiplier == 0 && !done) {
1158                 switch (*s) {
1159                 case ' ':
1160                         break;
1161                 case '.':
1162                         frac_part = g_ascii_strtod(s, &s);
1163                         break;
1164                 case 'k':
1165                 case 'K':
1166                         multiplier = SR_KHZ(1);
1167                         break;
1168                 case 'm':
1169                 case 'M':
1170                         multiplier = SR_MHZ(1);
1171                         break;
1172                 case 'g':
1173                 case 'G':
1174                         multiplier = SR_GHZ(1);
1175                         break;
1176                 case 't':
1177                 case 'T':
1178                         multiplier = SR_GHZ(1000);
1179                         break;
1180                 case 'p':
1181                 case 'P':
1182                         multiplier = SR_GHZ(1000 * 1000);
1183                         break;
1184                 case 'e':
1185                 case 'E':
1186                         multiplier = SR_GHZ(1000 * 1000 * 1000);
1187                         break;
1188                 default:
1189                         done = TRUE;
1190                         s--;
1191                 }
1192                 s++;
1193         }
1194         if (multiplier > 0) {
1195                 *size *= multiplier;
1196                 *size += frac_part * multiplier;
1197         } else {
1198                 *size += frac_part;
1199         }
1200
1201         if (s && *s && g_ascii_strcasecmp(s, "Hz"))
1202                 return SR_ERR;
1203
1204         return SR_OK;
1205 }
1206
1207 /**
1208  * Convert a "natural" string representation of a time value to an
1209  * uint64_t value in milliseconds.
1210  *
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.
1213  *
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.
1217  *
1218  * @param timestring A string containing a (decimal) time value.
1219  * @return The string's time value as uint64_t, in milliseconds.
1220  *
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.
1224  *
1225  * @since 0.1.0
1226  */
1227 SR_API uint64_t sr_parse_timestring(const char *timestring)
1228 {
1229         uint64_t time_msec;
1230         char *s;
1231
1232         /* TODO: Error handling, logging. */
1233
1234         time_msec = strtoull(timestring, &s, 10);
1235         if (time_msec == 0 && s == timestring)
1236                 return 0;
1237
1238         if (s && *s) {
1239                 while (*s == ' ')
1240                         s++;
1241                 if (!strcmp(s, "s"))
1242                         time_msec *= 1000;
1243                 else if (!strcmp(s, "ms"))
1244                         ; /* redundant */
1245                 else
1246                         return 0;
1247         }
1248
1249         return time_msec;
1250 }
1251
1252 /** @since 0.1.0 */
1253 SR_API gboolean sr_parse_boolstring(const char *boolstr)
1254 {
1255         /*
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:...
1259          */
1260         if (!boolstr || !*boolstr)
1261                 return TRUE;
1262
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))
1267                 return TRUE;
1268
1269         return FALSE;
1270 }
1271
1272 /** @since 0.2.0 */
1273 SR_API int sr_parse_period(const char *periodstr, uint64_t *p, uint64_t *q)
1274 {
1275         char *s;
1276
1277         *p = strtoull(periodstr, &s, 10);
1278         if (*p == 0 && s == periodstr)
1279                 /* No digits found. */
1280                 return SR_ERR_ARG;
1281
1282         if (s && *s) {
1283                 while (*s == ' ')
1284                         s++;
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"))
1292                         *q = 1000000;
1293                 else if (!strcmp(s, "ms"))
1294                         *q = 1000;
1295                 else if (!strcmp(s, "s"))
1296                         *q = 1;
1297                 else
1298                         /* Must have a time suffix. */
1299                         return SR_ERR_ARG;
1300         }
1301
1302         return SR_OK;
1303 }
1304
1305 /** @since 0.2.0 */
1306 SR_API int sr_parse_voltage(const char *voltstr, uint64_t *p, uint64_t *q)
1307 {
1308         char *s;
1309
1310         *p = strtoull(voltstr, &s, 10);
1311         if (*p == 0 && s == voltstr)
1312                 /* No digits found. */
1313                 return SR_ERR_ARG;
1314
1315         if (s && *s) {
1316                 while (*s == ' ')
1317                         s++;
1318                 if (!g_ascii_strcasecmp(s, "mv"))
1319                         *q = 1000L;
1320                 else if (!g_ascii_strcasecmp(s, "v"))
1321                         *q = 1;
1322                 else
1323                         /* Must have a base suffix. */
1324                         return SR_ERR_ARG;
1325         }
1326
1327         return SR_OK;
1328 }
1329
1330 /**
1331  * Append another text item to a NULL terminated string vector.
1332  *
1333  * @param[in] table The previous string vector.
1334  * @param[in,out] sz The previous and the resulting vector size
1335  *       (item count).
1336  * @param[in] text The text string to append to the vector.
1337  *       Can be #NULL.
1338  *
1339  * @returns The new vector, its location can differ from 'table'.
1340  *       Or #NULL in case of failure.
1341  *
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.
1347  *
1348  * This routine re-allocates the vector as needed. Callers must not
1349  * rely on the memory address to remain the same across calls.
1350  */
1351 static char **append_probe_name(char **table, size_t *sz, const char *text)
1352 {
1353         size_t curr_size, alloc_size;
1354         char **new_table;
1355
1356         /* Get the table's previous size (item count). */
1357         if (sz)
1358                 curr_size = *sz;
1359         else if (table)
1360                 curr_size = g_strv_length(table);
1361         else
1362                 curr_size = 0;
1363
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);
1368         if (!new_table) {
1369                 g_strfreev(table);
1370                 if (sz)
1371                         *sz = 0;
1372                 return NULL;
1373         }
1374
1375         /* Append the item, NULL terminate. */
1376         if (text) {
1377                 new_table[curr_size] = g_strdup(text);
1378                 if (!new_table[curr_size]) {
1379                         g_strfreev(new_table);
1380                         if (sz)
1381                                 *sz = 0;
1382                         return NULL;
1383                 }
1384                 curr_size++;
1385         }
1386         if (sz)
1387                 *sz = curr_size;
1388         new_table[curr_size] = NULL;
1389
1390         return new_table;
1391 }
1392
1393 static char **append_probe_names(char **table, size_t *sz,
1394         const char **names)
1395 {
1396         if (!names)
1397                 return table;
1398
1399         while (names[0]) {
1400                 table = append_probe_name(table, sz, names[0]);
1401                 names++;
1402         }
1403         return table;
1404 }
1405
1406 static const struct {
1407         const char *name;
1408         const char **expands;
1409 } probe_name_aliases[] = {
1410         {
1411                 "ac97", (const char *[]){
1412                         "sync", "clk",
1413                         "out", "in", "rst",
1414                         NULL,
1415                 },
1416         },
1417         {
1418                 "i2c", (const char *[]){
1419                         "scl", "sda", NULL,
1420                 },
1421         },
1422         {
1423                 "jtag", (const char *[]){
1424                         "tdi", "tdo", "tck", "tms", NULL,
1425                 },
1426         },
1427         {
1428                 "jtag-opt", (const char *[]){
1429                         "tdi", "tdo", "tck", "tms",
1430                         "trst", "srst", "rtck", NULL,
1431                 },
1432         },
1433         {
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,
1439                 },
1440         },
1441         {
1442                 "lpc", (const char *[]){
1443                         "lframe", "lclk",
1444                         "lad0", "lad1", "lad2", "lad3",
1445                         NULL,
1446                 },
1447         },
1448         {
1449                 "lpc-opt", (const char *[]){
1450                         "lframe", "lclk",
1451                         "lad0", "lad1", "lad2", "lad3",
1452                         "lreset", "ldrq", "serirq", "clkrun",
1453                         "lpme", "lpcpd", "lsmi",
1454                         NULL,
1455                 },
1456         },
1457         {
1458                 "mcs48", (const char *[]){
1459                         "ale", "psen",
1460                         "d0", "d1", "d2", "d3",
1461                         "d4", "d5", "d6", "d7",
1462                         "a8", "a9", "a10", "a11",
1463                         "a12", "a13",
1464                         NULL,
1465                 },
1466         },
1467         {
1468                 "microwire", (const char *[]){
1469                         "cs", "sk", "si", "so", NULL,
1470                 },
1471         },
1472         {
1473                 "sdcard_sd", (const char *[]){
1474                         "cmd", "clk",
1475                         "dat0", "dat1", "dat2", "dat3",
1476                         NULL,
1477                 },
1478         },
1479         {
1480                 "seven_segment", (const char *[]){
1481                         "a", "b", "c", "d", "e", "f", "g",
1482                         "dp", NULL,
1483                 },
1484         },
1485         {
1486                 "spi", (const char *[]){
1487                         "clk", "miso", "mosi", "cs", NULL,
1488                 },
1489         },
1490         {
1491                 "swd", (const char *[]){
1492                         "swclk", "swdio", NULL,
1493                 },
1494         },
1495         {
1496                 "uart", (const char *[]){
1497                         "rx", "tx", NULL,
1498                 },
1499         },
1500         {
1501                 "usb", (const char *[]){
1502                         "dp", "dm", NULL,
1503                 },
1504         },
1505         {
1506                 "z80", (const char *[]){
1507                         "d0", "d1", "d2", "d3",
1508                         "d4", "d5", "d6", "d7",
1509                         "m1", "rd", "wr",
1510                         "mreq", "iorq",
1511                         "a0", "a1", "a2", "a3",
1512                         "a4", "a5", "a6", "a7",
1513                         "a8", "a9", "a10", "a11",
1514                         "a12", "a13", "a14", "a15",
1515                         NULL,
1516                 },
1517         },
1518 };
1519
1520 /* Case insensitive lookup of an alias name. */
1521 static const char **lookup_probe_alias(const char *name)
1522 {
1523         size_t idx;
1524
1525         for (idx = 0; idx < ARRAY_SIZE(probe_name_aliases); idx++) {
1526                 if (g_ascii_strcasecmp(probe_name_aliases[idx].name, name) != 0)
1527                         continue;
1528                 return probe_name_aliases[idx].expands;
1529         }
1530         return NULL;
1531 }
1532
1533 /**
1534  * Parse a probe names specification, allocate a string vector.
1535  *
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).
1543  *
1544  * @returns A string vector with resulting probe names. Or #NULL
1545  *        in case of failure.
1546  *
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.
1557  *
1558  * Calling applications must release the allocated vector by means
1559  * of @ref sr_free_probe_names().
1560  *
1561  * @since 0.6.0
1562  */
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)
1566 {
1567         char **result_names;
1568         size_t result_count;
1569         gboolean pad_from_dflt;
1570         char **spec_names, *spec_name;
1571         size_t spec_idx;
1572         const char **alias_names;
1573
1574         if (!spec || !*spec)
1575                 spec = NULL;
1576
1577         /*
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.
1581          */
1582         if (!dflt_count) {
1583                 while (dflt_names && dflt_names[dflt_count])
1584                         dflt_count++;
1585         }
1586         if (!dflt_count)
1587                 return NULL;
1588
1589         /*
1590          * Start with an empty resulting names table. Will grow
1591          * dynamically as more names get appended.
1592          */
1593         result_names = NULL;
1594         result_count = 0;
1595         pad_from_dflt = TRUE;
1596
1597         /*
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.
1602          *
1603          * A leading '-' before the signal names list suppresses the
1604          * padding of the resulting list from the device's default
1605          * probe names.
1606          */
1607         spec_names = NULL;
1608         if (spec && *spec == '-') {
1609                 spec++;
1610                 pad_from_dflt = FALSE;
1611         }
1612         if (spec && *spec)
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];
1616                 if (!*spec_name)
1617                         continue;
1618                 alias_names = lookup_probe_alias(spec_name);
1619                 if (alias_names) {
1620                         result_names = append_probe_names(result_names,
1621                                 &result_count, alias_names);
1622                 } else {
1623                         result_names = append_probe_name(result_names,
1624                                 &result_count, spec_name);
1625                 }
1626         }
1627         g_strfreev(spec_names);
1628
1629         /*
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.
1633          */
1634         if (pad_from_dflt) do {
1635                 if (max_count && result_count >= max_count)
1636                         break;
1637                 if (result_count >= dflt_count)
1638                         break;
1639                 result_names = append_probe_name(result_names, &result_count,
1640                         dflt_names[result_count]);
1641         } while (1);
1642
1643         /* Optionally trim the result to the caller's length limit. */
1644         if (max_count) {
1645                 while (result_count > max_count) {
1646                         --result_count;
1647                         g_free(result_names[result_count]);
1648                         result_names[result_count] = NULL;
1649                 }
1650         }
1651
1652         if (ret_count)
1653                 *ret_count = result_count;
1654
1655         return result_names;
1656 }
1657
1658 /**
1659  * Release previously allocated probe names (string vector).
1660  *
1661  * @param[in] names The previously allocated string vector.
1662  *
1663  * @since 0.6.0
1664  */
1665 SR_API void sr_free_probe_names(char **names)
1666 {
1667         g_strfreev(names);
1668 }
1669
1670 /**
1671  * Trim leading and trailing whitespace off text.
1672  *
1673  * @param[in] s The input text.
1674  *
1675  * @return Start of trimmed input text.
1676  *
1677  * Manipulates the caller's input text in place.
1678  *
1679  * @since 0.6.0
1680  */
1681 SR_API char *sr_text_trim_spaces(char *s)
1682 {
1683         char *p;
1684
1685         if (!s || !*s)
1686                 return s;
1687
1688         p = s + strlen(s);
1689         while (p > s && isspace((int)p[-1]))
1690                 *(--p) = '\0';
1691         while (isspace((int)*s))
1692                 s++;
1693
1694         return s;
1695 }
1696
1697 /**
1698  * Check for another complete text line, trim, return consumed char count.
1699  *
1700  * @param[in] s The input text, current read position.
1701  * @param[in] l The input text, remaining available characters.
1702  * @param[out] next Position after the current text line.
1703  * @param[out] taken Count of consumed chars in current text line.
1704  *
1705  * @return Start of trimmed and NUL terminated text line.
1706  *   Or #NULL when no text line was found.
1707  *
1708  * Checks for the availability of another text line of input data.
1709  * Manipulates the caller's input text in place.
1710  *
1711  * The end-of-line condition is the LF character ('\n'). Which covers
1712  * LF-only as well as CR/LF input data. CR-only and LF/CR are considered
1713  * unpopular and are not supported. LF/CR may appear to work at the
1714  * caller's when leading whitespace gets trimmed (line boundaries will
1715  * be incorrect, but content may get processed as expected). Support for
1716  * all of the above combinations breaks the detection of empty lines (or
1717  * becomes unmaintainably complex).
1718  *
1719  * The input buffer must be end-of-line terminated, lack of EOL results
1720  * in failure to detect the text line. This is motivated by accumulating
1721  * input in chunks, and the desire to not process incomplete lines before
1722  * their reception has completed. Callers should enforce EOL if their
1723  * source of input provides an EOF condition and is unreliable in terms
1724  * of text line termination.
1725  *
1726  * When another text line is available, it gets NUL terminated and
1727  * space gets trimmed of both ends. The start position of the trimmed
1728  * text line is returned. Optionally the number of consumed characters
1729  * is returned to the caller. Optionally 'next' points to after the
1730  * returned text line, or #NULL when no other text is available in the
1731  * input buffer.
1732  *
1733  * The 'taken' value is not preset by this routine, only gets updated.
1734  * This is convenient for callers which expect to find multiple text
1735  * lines in a received chunk, before finally discarding processed data
1736  * from the input buffer (which can involve expensive memory move
1737  * operations, and may be desirable to defer as much as possible).
1738  *
1739  * @since 0.6.0
1740  */
1741 SR_API char *sr_text_next_line(char *s, size_t l, char **next, size_t *taken)
1742 {
1743         char *p;
1744
1745         if (next)
1746                 *next = NULL;
1747         if (!l)
1748                 l = strlen(s);
1749
1750         /* Immediate reject incomplete input data. */
1751         if (!s || !*s || !l)
1752                 return NULL;
1753
1754         /* Search for the next line termination. NUL terminate. */
1755         p = g_strstr_len(s, l, "\n");
1756         if (!p)
1757                 return NULL;
1758         *p++ = '\0';
1759         if (taken)
1760                 *taken += p - s;
1761         l -= p - s;
1762         if (next)
1763                 *next = l ? p : NULL;
1764
1765         /* Trim NUL terminated text line at both ends. */
1766         s = sr_text_trim_spaces(s);
1767         return s;
1768 }
1769
1770 /**
1771  * Isolates another space separated word in a text line.
1772  *
1773  * @param[in] s The input text, current read position.
1774  * @param[out] next The position after the current word.
1775  *
1776  * @return The start of the current word. Or #NULL if there is none.
1777  *
1778  * Advances over leading whitespace. Isolates (NUL terminates) the next
1779  * whitespace separated word. Optionally returns the position after the
1780  * current word. Manipulates the caller's input text in place.
1781  *
1782  * @since 0.6.0
1783  */
1784 SR_API char *sr_text_next_word(char *s, char **next)
1785 {
1786         char *word, *p;
1787
1788         word = s;
1789         if (next)
1790                 *next = NULL;
1791
1792         /* Immediately reject incomplete input data. */
1793         if (!word || !*word)
1794                 return NULL;
1795
1796         /* Advance over optional leading whitespace. */
1797         while (isspace((int)*word))
1798                 word++;
1799         if (!*word)
1800                 return NULL;
1801
1802         /*
1803          * Advance until whitespace or end of text. Quick return when
1804          * end of input is seen. Otherwise advance over whitespace and
1805          * return the position of trailing text.
1806          */
1807         p = word;
1808         while (*p && !isspace((int)*p))
1809                 p++;
1810         if (!*p)
1811                 return word;
1812         *p++ = '\0';
1813         while (isspace((int)*p))
1814                 p++;
1815         if (!*p)
1816                 return word;
1817         if (next)
1818                 *next = p;
1819         return word;
1820 }
1821
1822 /**
1823  * Get the number of necessary bits to hold a given value. Also gets
1824  * the next power-of-two value at or above the caller provided value.
1825  *
1826  * @param[in] value The value that must get stored.
1827  * @param[out] bits The required number of bits.
1828  * @param[out] power The corresponding power-of-two.
1829  *
1830  * @return SR_OK upon success, SR_ERR* otherwise.
1831  *
1832  * TODO Move this routine to a more appropriate location, it is not
1833  * strictly string related.
1834  *
1835  * @since 0.6.0
1836  */
1837 SR_API int sr_next_power_of_two(size_t value, size_t *bits, size_t *power)
1838 {
1839         size_t need_bits;
1840         size_t check_mask;
1841
1842         if (bits)
1843                 *bits = 0;
1844         if (power)
1845                 *power = 0;
1846
1847         /*
1848          * Handle the special case of input value 0 (needs 1 bit
1849          * and results in "power of two" value 1) here. It is not
1850          * covered by the generic logic below.
1851          */
1852         if (!value) {
1853                 if (bits)
1854                         *bits = 1;
1855                 if (power)
1856                         *power = 1;
1857                 return SR_OK;
1858         }
1859
1860         need_bits = 0;
1861         check_mask = 0;
1862         do {
1863                 need_bits++;
1864                 check_mask <<= 1;
1865                 check_mask |= 1UL << 0;
1866         } while (value & ~check_mask);
1867
1868         if (bits)
1869                 *bits = need_bits;
1870         if (power)
1871                 *power = ++check_mask;
1872         return SR_OK;
1873 }
1874
1875 /** @} */