libsigrok  0.3.0
sigrok hardware access and backend library
strutil.c
Go to the documentation of this file.
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 /** @} */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines