![]() |
libsigrok
0.3.0
sigrok hardware access and backend library
|
00001 /* 00002 * This file is part of the libsigrok project. 00003 * 00004 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 #include <stdint.h> 00022 #include <stdlib.h> 00023 #include <string.h> 00024 #include <errno.h> 00025 #include "libsigrok.h" 00026 #include "libsigrok-internal.h" 00027 00028 /** @cond PRIVATE */ 00029 #define LOG_PREFIX "strutil" 00030 /** @endcond */ 00031 00032 /** 00033 * @file 00034 * 00035 * Helper functions for handling or converting libsigrok-related strings. 00036 */ 00037 00038 /** 00039 * @defgroup grp_strutil String utilities 00040 * 00041 * Helper functions for handling or converting libsigrok-related strings. 00042 * 00043 * @{ 00044 */ 00045 00046 /** 00047 * @private 00048 * 00049 * Convert a string representation of a numeric value to a long integer. The 00050 * conversion is strict and will fail if the complete string does not represent 00051 * a valid long integer. The function sets errno according to the details of the 00052 * failure. 00053 * 00054 * @param str The string representation to convert. 00055 * @param ret Pointer to long where the result of the conversion will be stored. 00056 * 00057 * @return SR_OK if conversion is successful, otherwise SR_ERR. 00058 * 00059 * @since 0.3.0 00060 */ 00061 SR_PRIV int sr_atol(const char *str, long *ret) 00062 { 00063 long tmp; 00064 char *endptr = NULL; 00065 00066 errno = 0; 00067 tmp = strtol(str, &endptr, 0); 00068 00069 if (!endptr || *endptr || errno) { 00070 if (!errno) 00071 errno = EINVAL; 00072 return SR_ERR; 00073 } 00074 00075 *ret = tmp; 00076 return SR_OK; 00077 } 00078 00079 /** 00080 * @private 00081 * 00082 * Convert a string representation of a numeric value to an integer. The 00083 * conversion is strict and will fail if the complete string does not represent 00084 * a valid integer. The function sets errno according to the details of the 00085 * failure. 00086 * 00087 * @param str The string representation to convert. 00088 * @param ret Pointer to int where the result of the conversion will be stored. 00089 * 00090 * @return SR_OK if conversion is successful, otherwise SR_ERR. 00091 * 00092 * @since 0.3.0 00093 */ 00094 SR_PRIV int sr_atoi(const char *str, int *ret) 00095 { 00096 long tmp; 00097 00098 if (sr_atol(str, &tmp) != SR_OK) 00099 return SR_ERR; 00100 00101 if ((int) tmp != tmp) { 00102 errno = ERANGE; 00103 return SR_ERR; 00104 } 00105 00106 *ret = (int) tmp; 00107 return SR_OK; 00108 } 00109 00110 /** 00111 * @private 00112 * 00113 * Convert a string representation of a numeric value to a double. The 00114 * conversion is strict and will fail if the complete string does not represent 00115 * a valid double. The function sets errno according to the details of the 00116 * failure. 00117 * 00118 * @param str The string representation to convert. 00119 * @param ret Pointer to double where the result of the conversion will be stored. 00120 * 00121 * @return SR_OK if conversion is successful, otherwise SR_ERR. 00122 * 00123 * @since 0.3.0 00124 */ 00125 SR_PRIV int sr_atod(const char *str, double *ret) 00126 { 00127 double tmp; 00128 char *endptr = NULL; 00129 00130 errno = 0; 00131 tmp = strtof(str, &endptr); 00132 00133 if (!endptr || *endptr || errno) { 00134 if (!errno) 00135 errno = EINVAL; 00136 return SR_ERR; 00137 } 00138 00139 *ret = tmp; 00140 return SR_OK; 00141 } 00142 00143 /** 00144 * @private 00145 * 00146 * Convert a string representation of a numeric value to a float. The 00147 * conversion is strict and will fail if the complete string does not represent 00148 * a valid float. The function sets errno according to the details of the 00149 * failure. 00150 * 00151 * @param str The string representation to convert. 00152 * @param ret Pointer to float where the result of the conversion will be stored. 00153 * 00154 * @return SR_OK if conversion is successful, otherwise SR_ERR. 00155 * 00156 * @since 0.3.0 00157 */ 00158 SR_PRIV int sr_atof(const char *str, float *ret) 00159 { 00160 double tmp; 00161 00162 if (sr_atod(str, &tmp) != SR_OK) 00163 return SR_ERR; 00164 00165 if ((float) tmp != tmp) { 00166 errno = ERANGE; 00167 return SR_ERR; 00168 } 00169 00170 *ret = (float) tmp; 00171 return SR_OK; 00172 } 00173 00174 /** 00175 * @private 00176 * 00177 * Convert a string representation of a numeric value to a float. The 00178 * conversion is strict and will fail if the complete string does not represent 00179 * a valid float. The function sets errno according to the details of the 00180 * failure. This version ignores the locale. 00181 * 00182 * @param str The string representation to convert. 00183 * @param ret Pointer to float where the result of the conversion will be stored. 00184 * 00185 * @return SR_OK if conversion is successful, otherwise SR_ERR. 00186 * 00187 * @since 0.3.0 00188 */ 00189 SR_PRIV int sr_atof_ascii(const char *str, float *ret) 00190 { 00191 double tmp; 00192 char *endptr = NULL; 00193 00194 errno = 0; 00195 tmp = g_ascii_strtod(str, &endptr); 00196 00197 if (!endptr || *endptr || errno) { 00198 if (!errno) 00199 errno = EINVAL; 00200 return SR_ERR; 00201 } 00202 00203 /* FIXME This fails unexpectedly. Some other method to safel downcast 00204 * needs to be found. Checking against FLT_MAX doesn't work as well. */ 00205 /* 00206 if ((float) tmp != tmp) { 00207 errno = ERANGE; 00208 sr_dbg("ERANGEEEE %e != %e", (float) tmp, tmp); 00209 return SR_ERR; 00210 } 00211 */ 00212 00213 *ret = (float) tmp; 00214 return SR_OK; 00215 } 00216 00217 /** 00218 * Convert a numeric value value to its "natural" string representation 00219 * in SI units. 00220 * 00221 * E.g. a value of 3000000, with units set to "W", would be converted 00222 * to "3 MW", 20000 to "20 kW", 31500 would become "31.5 kW". 00223 * 00224 * @param x The value to convert. 00225 * @param unit The unit to append to the string, or NULL if the string 00226 * has no units. 00227 * 00228 * @return A g_try_malloc()ed string representation of the samplerate value, 00229 * or NULL upon errors. The caller is responsible to g_free() the 00230 * memory. 00231 * 00232 * @since 0.2.0 00233 */ 00234 SR_API char *sr_si_string_u64(uint64_t x, const char *unit) 00235 { 00236 uint8_t i; 00237 uint64_t quot, divisor[] = { 00238 SR_HZ(1), SR_KHZ(1), SR_MHZ(1), SR_GHZ(1), 00239 SR_GHZ(1000), SR_GHZ(1000 * 1000), SR_GHZ(1000 * 1000 * 1000), 00240 }; 00241 const char *p, prefix[] = "\0kMGTPE"; 00242 char fmt[16], fract[20] = "", *f; 00243 00244 if (unit == NULL) 00245 unit = ""; 00246 00247 for (i = 0; (quot = x / divisor[i]) >= 1000; i++); 00248 00249 if (i) { 00250 sprintf(fmt, ".%%0%d"PRIu64, i * 3); 00251 f = fract + sprintf(fract, fmt, x % divisor[i]) - 1; 00252 00253 while (f >= fract && strchr("0.", *f)) 00254 *f-- = 0; 00255 } 00256 00257 p = prefix + i; 00258 00259 return g_strdup_printf("%" PRIu64 "%s %.1s%s", quot, fract, p, unit); 00260 } 00261 00262 /** 00263 * Convert a numeric samplerate value to its "natural" string representation. 00264 * 00265 * E.g. a value of 3000000 would be converted to "3 MHz", 20000 to "20 kHz", 00266 * 31500 would become "31.5 kHz". 00267 * 00268 * @param samplerate The samplerate in Hz. 00269 * 00270 * @return A g_try_malloc()ed string representation of the samplerate value, 00271 * or NULL upon errors. The caller is responsible to g_free() the 00272 * memory. 00273 * 00274 * @since 0.1.0 00275 */ 00276 SR_API char *sr_samplerate_string(uint64_t samplerate) 00277 { 00278 return sr_si_string_u64(samplerate, "Hz"); 00279 } 00280 00281 /** 00282 * Convert a numeric frequency value to the "natural" string representation 00283 * of its period. 00284 * 00285 * E.g. a value of 3000000 would be converted to "3 us", 20000 to "50 ms". 00286 * 00287 * @param frequency The frequency in Hz. 00288 * 00289 * @return A g_try_malloc()ed string representation of the frequency value, 00290 * or NULL upon errors. The caller is responsible to g_free() the 00291 * memory. 00292 * 00293 * @since 0.1.0 00294 */ 00295 SR_API char *sr_period_string(uint64_t frequency) 00296 { 00297 char *o; 00298 int r; 00299 00300 /* Allocate enough for a uint64_t as string + " ms". */ 00301 if (!(o = g_try_malloc0(30 + 1))) { 00302 sr_err("%s: o malloc failed", __func__); 00303 return NULL; 00304 } 00305 00306 if (frequency >= SR_GHZ(1)) 00307 r = snprintf(o, 30, "%" PRIu64 " ns", frequency / 1000000000); 00308 else if (frequency >= SR_MHZ(1)) 00309 r = snprintf(o, 30, "%" PRIu64 " us", frequency / 1000000); 00310 else if (frequency >= SR_KHZ(1)) 00311 r = snprintf(o, 30, "%" PRIu64 " ms", frequency / 1000); 00312 else 00313 r = snprintf(o, 30, "%" PRIu64 " s", frequency); 00314 00315 if (r < 0) { 00316 /* Something went wrong... */ 00317 g_free(o); 00318 return NULL; 00319 } 00320 00321 return o; 00322 } 00323 00324 /** 00325 * Convert a numeric voltage value to the "natural" string representation 00326 * of its voltage value. The voltage is specified as a rational number's 00327 * numerator and denominator. 00328 * 00329 * E.g. a value of 300000 would be converted to "300mV", 2 to "2V". 00330 * 00331 * @param v_p The voltage numerator. 00332 * @param v_q The voltage denominator. 00333 * 00334 * @return A g_try_malloc()ed string representation of the voltage value, 00335 * or NULL upon errors. The caller is responsible to g_free() the 00336 * memory. 00337 * 00338 * @since 0.2.0 00339 */ 00340 SR_API char *sr_voltage_string(uint64_t v_p, uint64_t v_q) 00341 { 00342 int r; 00343 char *o; 00344 00345 if (!(o = g_try_malloc0(30 + 1))) { 00346 sr_err("%s: o malloc failed", __func__); 00347 return NULL; 00348 } 00349 00350 if (v_q == 1000) 00351 r = snprintf(o, 30, "%" PRIu64 "mV", v_p); 00352 else if (v_q == 1) 00353 r = snprintf(o, 30, "%" PRIu64 "V", v_p); 00354 else 00355 r = snprintf(o, 30, "%gV", (float)v_p / (float)v_q); 00356 00357 if (r < 0) { 00358 /* Something went wrong... */ 00359 g_free(o); 00360 return NULL; 00361 } 00362 00363 return o; 00364 } 00365 00366 /** 00367 * Parse a trigger specification string. 00368 * 00369 * @param sdi The device instance for which the trigger specification is 00370 * intended. Must not be NULL. Also, sdi->driver and 00371 * sdi->driver->info_get must not be NULL. 00372 * @param triggerstring The string containing the trigger specification for 00373 * one or more channels of this device. Entries for multiple channels are 00374 * comma-separated. Triggers are specified in the form key=value, 00375 * where the key is a channel number (or channel name) and the value is 00376 * the requested trigger type. Valid trigger types currently 00377 * include 'r' (rising edge), 'f' (falling edge), 'c' (any pin value 00378 * change), '0' (low value), or '1' (high value). 00379 * Example: "1=r,sck=f,miso=0,7=c" 00380 * 00381 * @return Pointer to a list of trigger types (strings), or NULL upon errors. 00382 * The pointer list (if non-NULL) has as many entries as the 00383 * respective device has channels (all physically available channels, 00384 * not just enabled ones). Entries of the list which don't have 00385 * a trigger value set in 'triggerstring' are NULL, the other entries 00386 * contain the respective trigger type which is requested for the 00387 * respective channel (e.g. "r", "c", and so on). 00388 * 00389 * @since 0.2.0 00390 */ 00391 SR_API char **sr_parse_triggerstring(const struct sr_dev_inst *sdi, 00392 const char *triggerstring) 00393 { 00394 GSList *l; 00395 GVariant *gvar; 00396 struct sr_channel *ch; 00397 int max_channels, channelnum, i; 00398 char **tokens, **triggerlist, *trigger, *tc; 00399 const char *trigger_types; 00400 gboolean error; 00401 00402 max_channels = g_slist_length(sdi->channels); 00403 error = FALSE; 00404 00405 if (!(triggerlist = g_try_malloc0(max_channels * sizeof(char *)))) { 00406 sr_err("%s: triggerlist malloc failed", __func__); 00407 return NULL; 00408 } 00409 00410 if (sdi->driver->config_list(SR_CONF_TRIGGER_TYPE, 00411 &gvar, sdi, NULL) != SR_OK) { 00412 sr_err("%s: Device doesn't support any triggers.", __func__); 00413 return NULL; 00414 } 00415 trigger_types = g_variant_get_string(gvar, NULL); 00416 00417 tokens = g_strsplit(triggerstring, ",", max_channels); 00418 for (i = 0; tokens[i]; i++) { 00419 channelnum = -1; 00420 for (l = sdi->channels; l; l = l->next) { 00421 ch = (struct sr_channel *)l->data; 00422 if (ch->enabled 00423 && !strncmp(ch->name, tokens[i], 00424 strlen(ch->name))) { 00425 channelnum = ch->index; 00426 break; 00427 } 00428 } 00429 00430 if (channelnum < 0 || channelnum >= max_channels) { 00431 sr_err("Invalid channel."); 00432 error = TRUE; 00433 break; 00434 } 00435 00436 if ((trigger = strchr(tokens[i], '='))) { 00437 for (tc = ++trigger; *tc; tc++) { 00438 if (strchr(trigger_types, *tc) == NULL) { 00439 sr_err("Unsupported trigger " 00440 "type '%c'.", *tc); 00441 error = TRUE; 00442 break; 00443 } 00444 } 00445 if (!error) 00446 triggerlist[channelnum] = g_strdup(trigger); 00447 } 00448 } 00449 g_strfreev(tokens); 00450 g_variant_unref(gvar); 00451 00452 if (error) { 00453 for (i = 0; i < max_channels; i++) 00454 g_free(triggerlist[i]); 00455 g_free(triggerlist); 00456 triggerlist = NULL; 00457 } 00458 00459 return triggerlist; 00460 } 00461 00462 /** 00463 * Convert a "natural" string representation of a size value to uint64_t. 00464 * 00465 * E.g. a value of "3k" or "3 K" would be converted to 3000, a value 00466 * of "15M" would be converted to 15000000. 00467 * 00468 * Value representations other than decimal (such as hex or octal) are not 00469 * supported. Only 'k' (kilo), 'm' (mega), 'g' (giga) suffixes are supported. 00470 * Spaces (but not other whitespace) between value and suffix are allowed. 00471 * 00472 * @param sizestring A string containing a (decimal) size value. 00473 * @param size Pointer to uint64_t which will contain the string's size value. 00474 * 00475 * @return SR_OK upon success, SR_ERR upon errors. 00476 * 00477 * @since 0.1.0 00478 */ 00479 SR_API int sr_parse_sizestring(const char *sizestring, uint64_t *size) 00480 { 00481 int multiplier, done; 00482 double frac_part; 00483 char *s; 00484 00485 *size = strtoull(sizestring, &s, 10); 00486 multiplier = 0; 00487 frac_part = 0; 00488 done = FALSE; 00489 while (s && *s && multiplier == 0 && !done) { 00490 switch (*s) { 00491 case ' ': 00492 break; 00493 case '.': 00494 frac_part = g_ascii_strtod(s, &s); 00495 break; 00496 case 'k': 00497 case 'K': 00498 multiplier = SR_KHZ(1); 00499 break; 00500 case 'm': 00501 case 'M': 00502 multiplier = SR_MHZ(1); 00503 break; 00504 case 'g': 00505 case 'G': 00506 multiplier = SR_GHZ(1); 00507 break; 00508 default: 00509 done = TRUE; 00510 s--; 00511 } 00512 s++; 00513 } 00514 if (multiplier > 0) { 00515 *size *= multiplier; 00516 *size += frac_part * multiplier; 00517 } else 00518 *size += frac_part; 00519 00520 if (*s && strcasecmp(s, "Hz")) 00521 return SR_ERR; 00522 00523 return SR_OK; 00524 } 00525 00526 /** 00527 * Convert a "natural" string representation of a time value to an 00528 * uint64_t value in milliseconds. 00529 * 00530 * E.g. a value of "3s" or "3 s" would be converted to 3000, a value 00531 * of "15ms" would be converted to 15. 00532 * 00533 * Value representations other than decimal (such as hex or octal) are not 00534 * supported. Only lower-case "s" and "ms" time suffixes are supported. 00535 * Spaces (but not other whitespace) between value and suffix are allowed. 00536 * 00537 * @param timestring A string containing a (decimal) time value. 00538 * @return The string's time value as uint64_t, in milliseconds. 00539 * 00540 * @todo Add support for "m" (minutes) and others. 00541 * @todo Add support for picoseconds? 00542 * @todo Allow both lower-case and upper-case? If no, document it. 00543 * 00544 * @since 0.1.0 00545 */ 00546 SR_API uint64_t sr_parse_timestring(const char *timestring) 00547 { 00548 uint64_t time_msec; 00549 char *s; 00550 00551 /* TODO: Error handling, logging. */ 00552 00553 time_msec = strtoull(timestring, &s, 10); 00554 if (time_msec == 0 && s == timestring) 00555 return 0; 00556 00557 if (s && *s) { 00558 while (*s == ' ') 00559 s++; 00560 if (!strcmp(s, "s")) 00561 time_msec *= 1000; 00562 else if (!strcmp(s, "ms")) 00563 ; /* redundant */ 00564 else 00565 return 0; 00566 } 00567 00568 return time_msec; 00569 } 00570 00571 /** @since 0.1.0 */ 00572 SR_API gboolean sr_parse_boolstring(const char *boolstr) 00573 { 00574 if (!boolstr) 00575 return FALSE; 00576 00577 if (!g_ascii_strncasecmp(boolstr, "true", 4) || 00578 !g_ascii_strncasecmp(boolstr, "yes", 3) || 00579 !g_ascii_strncasecmp(boolstr, "on", 2) || 00580 !g_ascii_strncasecmp(boolstr, "1", 1)) 00581 return TRUE; 00582 00583 return FALSE; 00584 } 00585 00586 /** @since 0.2.0 */ 00587 SR_API int sr_parse_period(const char *periodstr, uint64_t *p, uint64_t *q) 00588 { 00589 char *s; 00590 00591 *p = strtoull(periodstr, &s, 10); 00592 if (*p == 0 && s == periodstr) 00593 /* No digits found. */ 00594 return SR_ERR_ARG; 00595 00596 if (s && *s) { 00597 while (*s == ' ') 00598 s++; 00599 if (!strcmp(s, "fs")) 00600 *q = 1000000000000000ULL; 00601 else if (!strcmp(s, "ps")) 00602 *q = 1000000000000ULL; 00603 else if (!strcmp(s, "ns")) 00604 *q = 1000000000ULL; 00605 else if (!strcmp(s, "us")) 00606 *q = 1000000; 00607 else if (!strcmp(s, "ms")) 00608 *q = 1000; 00609 else if (!strcmp(s, "s")) 00610 *q = 1; 00611 else 00612 /* Must have a time suffix. */ 00613 return SR_ERR_ARG; 00614 } 00615 00616 return SR_OK; 00617 } 00618 00619 /** @since 0.2.0 */ 00620 SR_API int sr_parse_voltage(const char *voltstr, uint64_t *p, uint64_t *q) 00621 { 00622 char *s; 00623 00624 *p = strtoull(voltstr, &s, 10); 00625 if (*p == 0 && s == voltstr) 00626 /* No digits found. */ 00627 return SR_ERR_ARG; 00628 00629 if (s && *s) { 00630 while (*s == ' ') 00631 s++; 00632 if (!strcasecmp(s, "mv")) 00633 *q = 1000L; 00634 else if (!strcasecmp(s, "v")) 00635 *q = 1; 00636 else 00637 /* Must have a base suffix. */ 00638 return SR_ERR_ARG; 00639 } 00640 00641 return SR_OK; 00642 } 00643 00644 /** @} */
1.7.6.1