libsigrok  0.3.0
sigrok hardware access and backend library
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
strutil.c
Go to the documentation of this file.
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, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include "libsigrok.h"
26 #include "libsigrok-internal.h"
27 
28 /** @cond PRIVATE */
29 #define LOG_PREFIX "strutil"
30 /** @endcond */
31 
32 /**
33  * @file
34  *
35  * Helper functions for handling or converting libsigrok-related strings.
36  */
37 
38 /**
39  * @defgroup grp_strutil String utilities
40  *
41  * Helper functions for handling or converting libsigrok-related strings.
42  *
43  * @{
44  */
45 
46 /**
47  * @private
48  *
49  * Convert a string representation of a numeric value to a long integer. The
50  * conversion is strict and will fail if the complete string does not represent
51  * a valid long integer. The function sets errno according to the details of the
52  * failure.
53  *
54  * @param str The string representation to convert.
55  * @param ret Pointer to long where the result of the conversion will be stored.
56  *
57  * @return SR_OK if conversion is successful, otherwise SR_ERR.
58  *
59  * @since 0.3.0
60  */
61 SR_PRIV int sr_atol(const char *str, long *ret)
62 {
63  long tmp;
64  char *endptr = NULL;
65 
66  errno = 0;
67  tmp = strtol(str, &endptr, 0);
68 
69  if (!endptr || *endptr || errno) {
70  if (!errno)
71  errno = EINVAL;
72  return SR_ERR;
73  }
74 
75  *ret = tmp;
76  return SR_OK;
77 }
78 
79 /**
80  * @private
81  *
82  * Convert a string representation of a numeric value to an integer. The
83  * conversion is strict and will fail if the complete string does not represent
84  * a valid integer. The function sets errno according to the details of the
85  * failure.
86  *
87  * @param str The string representation to convert.
88  * @param ret Pointer to int where the result of the conversion will be stored.
89  *
90  * @return SR_OK if conversion is successful, otherwise SR_ERR.
91  *
92  * @since 0.3.0
93  */
94 SR_PRIV int sr_atoi(const char *str, int *ret)
95 {
96  long tmp;
97 
98  if (sr_atol(str, &tmp) != SR_OK)
99  return SR_ERR;
100 
101  if ((int) tmp != tmp) {
102  errno = ERANGE;
103  return SR_ERR;
104  }
105 
106  *ret = (int) tmp;
107  return SR_OK;
108 }
109 
110 /**
111  * @private
112  *
113  * Convert a string representation of a numeric value to a double. The
114  * conversion is strict and will fail if the complete string does not represent
115  * a valid double. The function sets errno according to the details of the
116  * failure.
117  *
118  * @param str The string representation to convert.
119  * @param ret Pointer to double where the result of the conversion will be stored.
120  *
121  * @return SR_OK if conversion is successful, otherwise SR_ERR.
122  *
123  * @since 0.3.0
124  */
125 SR_PRIV int sr_atod(const char *str, double *ret)
126 {
127  double tmp;
128  char *endptr = NULL;
129 
130  errno = 0;
131  tmp = strtof(str, &endptr);
132 
133  if (!endptr || *endptr || errno) {
134  if (!errno)
135  errno = EINVAL;
136  return SR_ERR;
137  }
138 
139  *ret = tmp;
140  return SR_OK;
141 }
142 
143 /**
144  * @private
145  *
146  * Convert a string representation of a numeric value to a float. The
147  * conversion is strict and will fail if the complete string does not represent
148  * a valid float. The function sets errno according to the details of the
149  * failure.
150  *
151  * @param str The string representation to convert.
152  * @param ret Pointer to float where the result of the conversion will be stored.
153  *
154  * @return SR_OK if conversion is successful, otherwise SR_ERR.
155  *
156  * @since 0.3.0
157  */
158 SR_PRIV int sr_atof(const char *str, float *ret)
159 {
160  double tmp;
161 
162  if (sr_atod(str, &tmp) != SR_OK)
163  return SR_ERR;
164 
165  if ((float) tmp != tmp) {
166  errno = ERANGE;
167  return SR_ERR;
168  }
169 
170  *ret = (float) tmp;
171  return SR_OK;
172 }
173 
174 /**
175  * @private
176  *
177  * Convert a string representation of a numeric value to a float. The
178  * conversion is strict and will fail if the complete string does not represent
179  * a valid float. The function sets errno according to the details of the
180  * failure. This version ignores the locale.
181  *
182  * @param str The string representation to convert.
183  * @param ret Pointer to float where the result of the conversion will be stored.
184  *
185  * @return SR_OK if conversion is successful, otherwise SR_ERR.
186  *
187  * @since 0.3.0
188  */
189 SR_PRIV int sr_atof_ascii(const char *str, float *ret)
190 {
191  double tmp;
192  char *endptr = NULL;
193 
194  errno = 0;
195  tmp = g_ascii_strtod(str, &endptr);
196 
197  if (!endptr || *endptr || errno) {
198  if (!errno)
199  errno = EINVAL;
200  return SR_ERR;
201  }
202 
203  /* FIXME This fails unexpectedly. Some other method to safel downcast
204  * needs to be found. Checking against FLT_MAX doesn't work as well. */
205  /*
206  if ((float) tmp != tmp) {
207  errno = ERANGE;
208  sr_dbg("ERANGEEEE %e != %e", (float) tmp, tmp);
209  return SR_ERR;
210  }
211  */
212 
213  *ret = (float) tmp;
214  return SR_OK;
215 }
216 
217 /**
218  * Convert a numeric value value to its "natural" string representation
219  * in SI units.
220  *
221  * E.g. a value of 3000000, with units set to "W", would be converted
222  * to "3 MW", 20000 to "20 kW", 31500 would become "31.5 kW".
223  *
224  * @param x The value to convert.
225  * @param unit The unit to append to the string, or NULL if the string
226  * has no units.
227  *
228  * @return A g_try_malloc()ed string representation of the samplerate value,
229  * or NULL upon errors. The caller is responsible to g_free() the
230  * memory.
231  *
232  * @since 0.2.0
233  */
234 SR_API char *sr_si_string_u64(uint64_t x, const char *unit)
235 {
236  uint8_t i;
237  uint64_t quot, divisor[] = {
238  SR_HZ(1), SR_KHZ(1), SR_MHZ(1), SR_GHZ(1),
239  SR_GHZ(1000), SR_GHZ(1000 * 1000), SR_GHZ(1000 * 1000 * 1000),
240  };
241  const char *p, prefix[] = "\0kMGTPE";
242  char fmt[16], fract[20] = "", *f;
243 
244  if (unit == NULL)
245  unit = "";
246 
247  for (i = 0; (quot = x / divisor[i]) >= 1000; i++);
248 
249  if (i) {
250  sprintf(fmt, ".%%0%d"PRIu64, i * 3);
251  f = fract + sprintf(fract, fmt, x % divisor[i]) - 1;
252 
253  while (f >= fract && strchr("0.", *f))
254  *f-- = 0;
255  }
256 
257  p = prefix + i;
258 
259  return g_strdup_printf("%" PRIu64 "%s %.1s%s", quot, fract, p, unit);
260 }
261 
262 /**
263  * Convert a numeric samplerate value to its "natural" string representation.
264  *
265  * E.g. a value of 3000000 would be converted to "3 MHz", 20000 to "20 kHz",
266  * 31500 would become "31.5 kHz".
267  *
268  * @param samplerate The samplerate in Hz.
269  *
270  * @return A g_try_malloc()ed string representation of the samplerate value,
271  * or NULL upon errors. The caller is responsible to g_free() the
272  * memory.
273  *
274  * @since 0.1.0
275  */
276 SR_API char *sr_samplerate_string(uint64_t samplerate)
277 {
278  return sr_si_string_u64(samplerate, "Hz");
279 }
280 
281 /**
282  * Convert a numeric frequency value to the "natural" string representation
283  * of its period.
284  *
285  * E.g. a value of 3000000 would be converted to "3 us", 20000 to "50 ms".
286  *
287  * @param frequency The frequency in Hz.
288  *
289  * @return A g_try_malloc()ed string representation of the frequency value,
290  * or NULL upon errors. The caller is responsible to g_free() the
291  * memory.
292  *
293  * @since 0.1.0
294  */
295 SR_API char *sr_period_string(uint64_t frequency)
296 {
297  char *o;
298  int r;
299 
300  /* Allocate enough for a uint64_t as string + " ms". */
301  if (!(o = g_try_malloc0(30 + 1))) {
302  sr_err("%s: o malloc failed", __func__);
303  return NULL;
304  }
305 
306  if (frequency >= SR_GHZ(1))
307  r = snprintf(o, 30, "%" PRIu64 " ns", frequency / 1000000000);
308  else if (frequency >= SR_MHZ(1))
309  r = snprintf(o, 30, "%" PRIu64 " us", frequency / 1000000);
310  else if (frequency >= SR_KHZ(1))
311  r = snprintf(o, 30, "%" PRIu64 " ms", frequency / 1000);
312  else
313  r = snprintf(o, 30, "%" PRIu64 " s", frequency);
314 
315  if (r < 0) {
316  /* Something went wrong... */
317  g_free(o);
318  return NULL;
319  }
320 
321  return o;
322 }
323 
324 /**
325  * Convert a numeric voltage value to the "natural" string representation
326  * of its voltage value. The voltage is specified as a rational number's
327  * numerator and denominator.
328  *
329  * E.g. a value of 300000 would be converted to "300mV", 2 to "2V".
330  *
331  * @param v_p The voltage numerator.
332  * @param v_q The voltage denominator.
333  *
334  * @return A g_try_malloc()ed string representation of the voltage value,
335  * or NULL upon errors. The caller is responsible to g_free() the
336  * memory.
337  *
338  * @since 0.2.0
339  */
340 SR_API char *sr_voltage_string(uint64_t v_p, uint64_t v_q)
341 {
342  int r;
343  char *o;
344 
345  if (!(o = g_try_malloc0(30 + 1))) {
346  sr_err("%s: o malloc failed", __func__);
347  return NULL;
348  }
349 
350  if (v_q == 1000)
351  r = snprintf(o, 30, "%" PRIu64 "mV", v_p);
352  else if (v_q == 1)
353  r = snprintf(o, 30, "%" PRIu64 "V", v_p);
354  else
355  r = snprintf(o, 30, "%gV", (float)v_p / (float)v_q);
356 
357  if (r < 0) {
358  /* Something went wrong... */
359  g_free(o);
360  return NULL;
361  }
362 
363  return o;
364 }
365 
366 /**
367  * Parse a trigger specification string.
368  *
369  * @param sdi The device instance for which the trigger specification is
370  * intended. Must not be NULL. Also, sdi->driver and
371  * sdi->driver->info_get must not be NULL.
372  * @param triggerstring The string containing the trigger specification for
373  * one or more channels of this device. Entries for multiple channels are
374  * comma-separated. Triggers are specified in the form key=value,
375  * where the key is a channel number (or channel name) and the value is
376  * the requested trigger type. Valid trigger types currently
377  * include 'r' (rising edge), 'f' (falling edge), 'c' (any pin value
378  * change), '0' (low value), or '1' (high value).
379  * Example: "1=r,sck=f,miso=0,7=c"
380  *
381  * @return Pointer to a list of trigger types (strings), or NULL upon errors.
382  * The pointer list (if non-NULL) has as many entries as the
383  * respective device has channels (all physically available channels,
384  * not just enabled ones). Entries of the list which don't have
385  * a trigger value set in 'triggerstring' are NULL, the other entries
386  * contain the respective trigger type which is requested for the
387  * respective channel (e.g. "r", "c", and so on).
388  *
389  * @since 0.2.0
390  */
391 SR_API char **sr_parse_triggerstring(const struct sr_dev_inst *sdi,
392  const char *triggerstring)
393 {
394  GSList *l;
395  GVariant *gvar;
396  struct sr_channel *ch;
397  int max_channels, channelnum, i;
398  char **tokens, **triggerlist, *trigger, *tc;
399  const char *trigger_types;
400  gboolean error;
401 
402  max_channels = g_slist_length(sdi->channels);
403  error = FALSE;
404 
405  if (!(triggerlist = g_try_malloc0(max_channels * sizeof(char *)))) {
406  sr_err("%s: triggerlist malloc failed", __func__);
407  return NULL;
408  }
409 
411  &gvar, sdi, NULL) != SR_OK) {
412  sr_err("%s: Device doesn't support any triggers.", __func__);
413  return NULL;
414  }
415  trigger_types = g_variant_get_string(gvar, NULL);
416 
417  tokens = g_strsplit(triggerstring, ",", max_channels);
418  for (i = 0; tokens[i]; i++) {
419  channelnum = -1;
420  for (l = sdi->channels; l; l = l->next) {
421  ch = (struct sr_channel *)l->data;
422  if (ch->enabled
423  && !strncmp(ch->name, tokens[i],
424  strlen(ch->name))) {
425  channelnum = ch->index;
426  break;
427  }
428  }
429 
430  if (channelnum < 0 || channelnum >= max_channels) {
431  sr_err("Invalid channel.");
432  error = TRUE;
433  break;
434  }
435 
436  if ((trigger = strchr(tokens[i], '='))) {
437  for (tc = ++trigger; *tc; tc++) {
438  if (strchr(trigger_types, *tc) == NULL) {
439  sr_err("Unsupported trigger "
440  "type '%c'.", *tc);
441  error = TRUE;
442  break;
443  }
444  }
445  if (!error)
446  triggerlist[channelnum] = g_strdup(trigger);
447  }
448  }
449  g_strfreev(tokens);
450  g_variant_unref(gvar);
451 
452  if (error) {
453  for (i = 0; i < max_channels; i++)
454  g_free(triggerlist[i]);
455  g_free(triggerlist);
456  triggerlist = NULL;
457  }
458 
459  return triggerlist;
460 }
461 
462 /**
463  * Convert a "natural" string representation of a size value to uint64_t.
464  *
465  * E.g. a value of "3k" or "3 K" would be converted to 3000, a value
466  * of "15M" would be converted to 15000000.
467  *
468  * Value representations other than decimal (such as hex or octal) are not
469  * supported. Only 'k' (kilo), 'm' (mega), 'g' (giga) suffixes are supported.
470  * Spaces (but not other whitespace) between value and suffix are allowed.
471  *
472  * @param sizestring A string containing a (decimal) size value.
473  * @param size Pointer to uint64_t which will contain the string's size value.
474  *
475  * @return SR_OK upon success, SR_ERR upon errors.
476  *
477  * @since 0.1.0
478  */
479 SR_API int sr_parse_sizestring(const char *sizestring, uint64_t *size)
480 {
481  int multiplier, done;
482  double frac_part;
483  char *s;
484 
485  *size = strtoull(sizestring, &s, 10);
486  multiplier = 0;
487  frac_part = 0;
488  done = FALSE;
489  while (s && *s && multiplier == 0 && !done) {
490  switch (*s) {
491  case ' ':
492  break;
493  case '.':
494  frac_part = g_ascii_strtod(s, &s);
495  break;
496  case 'k':
497  case 'K':
498  multiplier = SR_KHZ(1);
499  break;
500  case 'm':
501  case 'M':
502  multiplier = SR_MHZ(1);
503  break;
504  case 'g':
505  case 'G':
506  multiplier = SR_GHZ(1);
507  break;
508  default:
509  done = TRUE;
510  s--;
511  }
512  s++;
513  }
514  if (multiplier > 0) {
515  *size *= multiplier;
516  *size += frac_part * multiplier;
517  } else
518  *size += frac_part;
519 
520  if (*s && strcasecmp(s, "Hz"))
521  return SR_ERR;
522 
523  return SR_OK;
524 }
525 
526 /**
527  * Convert a "natural" string representation of a time value to an
528  * uint64_t value in milliseconds.
529  *
530  * E.g. a value of "3s" or "3 s" would be converted to 3000, a value
531  * of "15ms" would be converted to 15.
532  *
533  * Value representations other than decimal (such as hex or octal) are not
534  * supported. Only lower-case "s" and "ms" time suffixes are supported.
535  * Spaces (but not other whitespace) between value and suffix are allowed.
536  *
537  * @param timestring A string containing a (decimal) time value.
538  * @return The string's time value as uint64_t, in milliseconds.
539  *
540  * @todo Add support for "m" (minutes) and others.
541  * @todo Add support for picoseconds?
542  * @todo Allow both lower-case and upper-case? If no, document it.
543  *
544  * @since 0.1.0
545  */
546 SR_API uint64_t sr_parse_timestring(const char *timestring)
547 {
548  uint64_t time_msec;
549  char *s;
550 
551  /* TODO: Error handling, logging. */
552 
553  time_msec = strtoull(timestring, &s, 10);
554  if (time_msec == 0 && s == timestring)
555  return 0;
556 
557  if (s && *s) {
558  while (*s == ' ')
559  s++;
560  if (!strcmp(s, "s"))
561  time_msec *= 1000;
562  else if (!strcmp(s, "ms"))
563  ; /* redundant */
564  else
565  return 0;
566  }
567 
568  return time_msec;
569 }
570 
571 /** @since 0.1.0 */
572 SR_API gboolean sr_parse_boolstring(const char *boolstr)
573 {
574  if (!boolstr)
575  return FALSE;
576 
577  if (!g_ascii_strncasecmp(boolstr, "true", 4) ||
578  !g_ascii_strncasecmp(boolstr, "yes", 3) ||
579  !g_ascii_strncasecmp(boolstr, "on", 2) ||
580  !g_ascii_strncasecmp(boolstr, "1", 1))
581  return TRUE;
582 
583  return FALSE;
584 }
585 
586 /** @since 0.2.0 */
587 SR_API int sr_parse_period(const char *periodstr, uint64_t *p, uint64_t *q)
588 {
589  char *s;
590 
591  *p = strtoull(periodstr, &s, 10);
592  if (*p == 0 && s == periodstr)
593  /* No digits found. */
594  return SR_ERR_ARG;
595 
596  if (s && *s) {
597  while (*s == ' ')
598  s++;
599  if (!strcmp(s, "fs"))
600  *q = 1000000000000000ULL;
601  else if (!strcmp(s, "ps"))
602  *q = 1000000000000ULL;
603  else if (!strcmp(s, "ns"))
604  *q = 1000000000ULL;
605  else if (!strcmp(s, "us"))
606  *q = 1000000;
607  else if (!strcmp(s, "ms"))
608  *q = 1000;
609  else if (!strcmp(s, "s"))
610  *q = 1;
611  else
612  /* Must have a time suffix. */
613  return SR_ERR_ARG;
614  }
615 
616  return SR_OK;
617 }
618 
619 /** @since 0.2.0 */
620 SR_API int sr_parse_voltage(const char *voltstr, uint64_t *p, uint64_t *q)
621 {
622  char *s;
623 
624  *p = strtoull(voltstr, &s, 10);
625  if (*p == 0 && s == voltstr)
626  /* No digits found. */
627  return SR_ERR_ARG;
628 
629  if (s && *s) {
630  while (*s == ' ')
631  s++;
632  if (!strcasecmp(s, "mv"))
633  *q = 1000L;
634  else if (!strcasecmp(s, "v"))
635  *q = 1;
636  else
637  /* Must have a base suffix. */
638  return SR_ERR_ARG;
639  }
640 
641  return SR_OK;
642 }
643 
644 /** @} */
Generic/unspecified error.
Definition: libsigrok.h:68
Information on single channel.
Definition: libsigrok.h:537
No error.
Definition: libsigrok.h:67
gboolean enabled
Is this channel enabled?
Definition: libsigrok.h:543
char ** sr_parse_triggerstring(const struct sr_dev_inst *sdi, const char *triggerstring)
Parse a trigger specification string.
Definition: strutil.c:391
gboolean sr_parse_boolstring(const char *boolstr)
Definition: strutil.c:572
The public libsigrok header file to be used by frontends.
#define SR_GHZ(n)
Definition: libsigrok.h:90
char * sr_period_string(uint64_t frequency)
Convert a numeric frequency value to the "natural" string representation of its period.
Definition: strutil.c:295
char * trigger
Trigger string, format like used by sigrok-cli.
Definition: libsigrok.h:547
GSList * channels
List of channels.
Definition: libsigrok.h:857
char * sr_voltage_string(uint64_t v_p, uint64_t v_q)
Convert a numeric voltage value to the "natural" string representation of its voltage value...
Definition: strutil.c:340
Device instance data.
Definition: libsigrok.h:841
Trigger types.
Definition: libsigrok.h:690
char * sr_si_string_u64(uint64_t x, const char *unit)
Convert a numeric value value to its "natural" string representation in SI units. ...
Definition: strutil.c:234
int sr_parse_period(const char *periodstr, uint64_t *p, uint64_t *q)
Definition: strutil.c:587
#define SR_PRIV
Definition: libsigrok.h:129
#define SR_HZ(n)
Definition: libsigrok.h:87
uint64_t sr_parse_timestring(const char *timestring)
Convert a "natural" string representation of a time value to an uint64_t value in milliseconds...
Definition: strutil.c:546
int sr_parse_voltage(const char *voltstr, uint64_t *p, uint64_t *q)
Definition: strutil.c:620
Function argument error.
Definition: libsigrok.h:70
char * name
Name of channel.
Definition: libsigrok.h:545
int(* config_list)(int info_id, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
List all possible values for a configuration key in a device instance.
Definition: libsigrok.h:939
#define SR_KHZ(n)
Definition: libsigrok.h:88
struct sr_dev_driver * driver
Device driver.
Definition: libsigrok.h:843
int sr_parse_sizestring(const char *sizestring, uint64_t *size)
Convert a "natural" string representation of a size value to uint64_t.
Definition: strutil.c:479
char * sr_samplerate_string(uint64_t samplerate)
Convert a numeric samplerate value to its "natural" string representation.
Definition: strutil.c:276
#define SR_MHZ(n)
Definition: libsigrok.h:89
int index
Number of channels, starting at 0.
Definition: libsigrok.h:539
#define SR_API
Definition: libsigrok.h:122