22 #define _XOPEN_SOURCE 700 27 #if defined(__FreeBSD__) || defined(__APPLE__) 30 #if defined(__FreeBSD__) 31 #include <sys/param.h> 39 #include "libsigrok-internal.h" 42 #define LOG_PREFIX "strutil" 73 SR_PRIV int sr_atol(
const char *str,
long *ret)
79 tmp = strtol(str, &endptr, 10);
81 while (endptr && isspace(*endptr))
84 if (!endptr || *endptr || errno) {
115 SR_PRIV int sr_atol_base(
const char *str,
long *ret,
char **end,
int base)
121 while (str && isspace(*str))
123 if (!base && strncmp(str,
"0b", strlen(
"0b")) == 0) {
131 num = strtol(str, &endptr, base);
132 if (!endptr || errno) {
140 while (endptr && isspace(*endptr))
169 SR_PRIV int sr_atoul_base(
const char *str,
unsigned long *ret,
char **end,
int base)
175 while (str && isspace(*str))
177 if ((!base || base == 2) && strncmp(str,
"0b", strlen(
"0b")) == 0) {
185 num = strtoul(str, &endptr, base);
186 if (!endptr || errno) {
194 while (endptr && isspace(*endptr))
216 SR_PRIV int sr_atoi(
const char *str,
int *ret)
220 if (sr_atol(str, &tmp) !=
SR_OK)
223 if ((
int) tmp != tmp) {
246 SR_PRIV int sr_atod(
const char *str,
double *ret)
252 tmp = strtof(str, &endptr);
254 while (endptr && isspace(*endptr))
257 if (!endptr || *endptr || errno) {
281 SR_PRIV int sr_atof(
const char *str,
float *ret)
285 if (sr_atod(str, &tmp) !=
SR_OK)
288 if ((
float) tmp != tmp) {
311 SR_PRIV int sr_atod_ascii(
const char *str,
double *ret)
317 tmp = g_ascii_strtod(str, &endptr);
319 if (!endptr || *endptr || errno) {
344 int *dig_ref, m_dig, exp;
360 while (*p && isspace(*p))
362 if (*p ==
'-' || *p ==
'+')
369 if (toupper(c) ==
'E') {
370 exp = strtol(p, NULL, 10);
386 sr_spew(
"atod digits: txt \"%s\" -> m %d, e %d -> digits %d",
387 str, m_dig, exp, m_dig + -exp);
390 if (sr_atod_ascii(str, &f) !=
SR_OK)
414 SR_PRIV int sr_atof_ascii(
const char *str,
float *ret)
420 tmp = g_ascii_strtod(str, &endptr);
422 if (!endptr || *endptr || errno) {
472 va_start(args, format);
521 locale = _create_locale(LC_NUMERIC,
"C");
522 ret = _vsprintf_l(buf, format, locale, args);
523 _free_locale(locale);
527 ret = vsprintf(buf, format, args);
530 #elif defined(__APPLE__) 539 locale = newlocale(LC_NUMERIC_MASK,
"C", NULL);
540 ret = vsprintf_l(buf, locale, format, args);
544 #elif defined(__FreeBSD__) && __FreeBSD_version >= 901000 553 locale = newlocale(LC_NUMERIC_MASK,
"C", NULL);
554 ret = vsprintf_l(buf, locale, format, args);
558 #elif defined(__ANDROID__) 566 ret = vsprintf(buf, format, args);
569 #elif defined(__linux__) 571 locale_t old_locale, temp_locale;
574 temp_locale = newlocale(LC_NUMERIC,
"C", NULL);
575 old_locale = uselocale(temp_locale);
577 ret = vsprintf(buf, format, args);
580 uselocale(old_locale);
581 freelocale(temp_locale);
584 #elif defined(__unix__) || defined(__unix) 592 ret = vsprintf(buf, format, args);
632 const char *format, ...)
637 va_start(args, format);
679 const char *format, va_list args)
694 locale = _create_locale(LC_NUMERIC,
"C");
695 ret = _vsnprintf_l(buf, buf_size, format, locale, args);
696 _free_locale(locale);
700 ret = vsnprintf(buf, buf_size, format, args);
703 #elif defined(__APPLE__) 712 locale = newlocale(LC_NUMERIC_MASK,
"C", NULL);
713 ret = vsnprintf_l(buf, buf_size, locale, format, args);
717 #elif defined(__FreeBSD__) && __FreeBSD_version >= 901000 726 locale = newlocale(LC_NUMERIC_MASK,
"C", NULL);
727 ret = vsnprintf_l(buf, buf_size, locale, format, args);
731 #elif defined(__ANDROID__) 739 ret = vsnprintf(buf, buf_size, format, args);
742 #elif defined(__linux__) 744 locale_t old_locale, temp_locale;
747 temp_locale = newlocale(LC_NUMERIC,
"C", NULL);
748 old_locale = uselocale(temp_locale);
750 ret = vsnprintf(buf, buf_size, format, args);
753 uselocale(old_locale);
754 freelocale(temp_locale);
757 #elif defined(__unix__) || defined(__unix) 765 ret = vsnprintf(buf, buf_size, format, args);
786 SR_PRIV GString *sr_hexdump_new(
const uint8_t *data,
const size_t len)
794 s = g_string_sized_new(i);
795 for (i = 0; i < len; i++) {
797 g_string_append_c(s,
' ');
798 if (i && (i % 8) == 0)
799 g_string_append_c(s,
' ');
800 if (i && (i % 16) == 0)
801 g_string_append_c(s,
' ');
802 g_string_append_printf(s,
"%02x", data[i]);
815 SR_PRIV void sr_hexdump_free(GString *s)
818 g_string_free(s, TRUE);
840 gboolean is_negative, empty_integral, empty_fractional, exp_negative;
844 uint32_t fractional_len;
860 while (isspace(*readptr))
865 if (*readptr ==
'-') {
868 }
else if (*readptr ==
'+') {
874 empty_integral = TRUE;
876 endptr = (
char *)readptr;
878 if (isdigit(*readptr)) {
879 empty_integral = FALSE;
880 integral = g_ascii_strtoll(readptr, &endptr, 10);
891 empty_fractional = TRUE;
894 if (*readptr ==
'.') {
898 if (isdigit(*readptr)) {
899 empty_fractional = FALSE;
900 fractional = g_ascii_strtoll(readptr, &endptr, 10);
903 if (endptr == readptr) {
907 fractional_len = endptr - readptr;
913 if (empty_integral && empty_fractional) {
920 if ((*readptr ==
'E') || (*readptr ==
'e')) {
923 exp_negative = FALSE;
924 if (*readptr ==
'+') {
925 exp_negative = FALSE;
928 }
else if (*readptr ==
'-') {
933 if (!isdigit(*readptr)) {
938 exponent = g_ascii_strtoll(readptr, &endptr, 10);
941 if (endptr == readptr) {
947 exponent = -exponent;
951 if (*endptr !=
'\0') {
962 integral = -integral;
963 while (fractional_len-- > 0) {
968 integral += fractional;
970 integral -= fractional;
971 while (exponent > 0) {
981 while (exponent < 0) {
987 ret->
q = denominator;
1012 uint64_t quot, divisor[] = {
1016 const char *p, prefix[] =
"\0kMGTPE";
1017 char fmt[16], fract[20] =
"", *f;
1022 for (i = 0; (quot = x / divisor[i]) >= 1000; i++);
1025 sprintf(fmt,
".%%0%d"PRIu64, i * 3);
1026 f = fract + sprintf(fract, fmt, x % divisor[i]) - 1;
1028 while (f >= fract && strchr(
"0.", *f))
1034 return g_strdup_printf(
"%" PRIu64
"%s %.1s%s", quot, fract, p, unit);
1078 freq = 1 / ((double)v_p / v_q);
1081 v = (double)v_p / v_q * 1000000000000.0;
1082 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1083 return g_strdup_printf(
"%.*f ps", prec, v);
1084 }
else if (freq >
SR_MHZ(1)) {
1085 v = (double)v_p / v_q * 1000000000.0;
1086 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1087 return g_strdup_printf(
"%.*f ns", prec, v);
1088 }
else if (freq >
SR_KHZ(1)) {
1089 v = (double)v_p / v_q * 1000000.0;
1090 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1091 return g_strdup_printf(
"%.*f us", prec, v);
1092 }
else if (freq > 1) {
1093 v = (double)v_p / v_q * 1000.0;
1094 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1095 return g_strdup_printf(
"%.*f ms", prec, v);
1097 v = (double)v_p / v_q;
1098 prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3;
1099 return g_strdup_printf(
"%.*f s", prec, v);
1122 return g_strdup_printf(
"%" PRIu64
" mV", v_p);
1124 return g_strdup_printf(
"%" PRIu64
" V", v_p);
1126 return g_strdup_printf(
"%g V", (
float)v_p / (
float)v_q);
1148 uint64_t multiplier;
1153 *size = strtoull(sizestring, &s, 10);
1157 while (s && *s && multiplier == 0 && !done) {
1162 frac_part = g_ascii_strtod(s, &s);
1178 multiplier =
SR_GHZ(1000);
1182 multiplier =
SR_GHZ(1000 * 1000);
1186 multiplier =
SR_GHZ(1000 * 1000 * 1000);
1194 if (multiplier > 0) {
1195 *size *= multiplier;
1196 *size += frac_part * multiplier;
1201 if (s && *s && g_ascii_strcasecmp(s,
"Hz"))
1234 time_msec = strtoull(timestring, &s, 10);
1235 if (time_msec == 0 && s == timestring)
1241 if (!strcmp(s,
"s"))
1243 else if (!strcmp(s,
"ms"))
1260 if (!boolstr || !*boolstr)
1263 if (!g_ascii_strncasecmp(boolstr,
"true", 4) ||
1264 !g_ascii_strncasecmp(boolstr,
"yes", 3) ||
1265 !g_ascii_strncasecmp(boolstr,
"on", 2) ||
1266 !g_ascii_strncasecmp(boolstr,
"1", 1))
1277 *p = strtoull(periodstr, &s, 10);
1278 if (*p == 0 && s == periodstr)
1285 if (!strcmp(s,
"fs"))
1286 *q = UINT64_C(1000000000000000);
1287 else if (!strcmp(s,
"ps"))
1288 *q = UINT64_C(1000000000000);
1289 else if (!strcmp(s,
"ns"))
1290 *q = UINT64_C(1000000000);
1291 else if (!strcmp(s,
"us"))
1293 else if (!strcmp(s,
"ms"))
1295 else if (!strcmp(s,
"s"))
1310 *p = strtoull(voltstr, &s, 10);
1311 if (*p == 0 && s == voltstr)
1318 if (!g_ascii_strcasecmp(s,
"mv"))
1320 else if (!g_ascii_strcasecmp(s,
"v"))
1351 static char **append_probe_name(
char **table,
size_t *sz,
const char *text)
1353 size_t curr_size, alloc_size;
1360 curr_size = g_strv_length(table);
1365 alloc_size = curr_size + (text ? 1 : 0) + 1;
1366 alloc_size *=
sizeof(table[0]);
1367 new_table = g_realloc(table, alloc_size);
1377 new_table[curr_size] = g_strdup(text);
1378 if (!new_table[curr_size]) {
1379 g_strfreev(new_table);
1388 new_table[curr_size] = NULL;
1393 static char **append_probe_names(
char **table,
size_t *sz,
1400 table = append_probe_name(table, sz, names[0]);
1406 static const struct {
1409 } probe_name_aliases[] = {
1411 "ac97", (
const char *[]){
1418 "i2c", (
const char *[]){
1423 "jtag", (
const char *[]){
1424 "tdi",
"tdo",
"tck",
"tms", NULL,
1428 "jtag-opt", (
const char *[]){
1429 "tdi",
"tdo",
"tck",
"tms",
1430 "trst",
"srst",
"rtck", NULL,
1434 "ieee488", (
const char *[]){
1435 "dio1",
"dio2",
"dio3",
"dio4",
1436 "dio5",
"dio6",
"dio7",
"dio8",
1437 "eoi",
"dav",
"nrfd",
"ndac",
1438 "ifc",
"srq",
"atn",
"ren", NULL,
1442 "lpc", (
const char *[]){
1444 "lad0",
"lad1",
"lad2",
"lad3",
1449 "lpc-opt", (
const char *[]){
1451 "lad0",
"lad1",
"lad2",
"lad3",
1452 "lreset",
"ldrq",
"serirq",
"clkrun",
1453 "lpme",
"lpcpd",
"lsmi",
1458 "mcs48", (
const char *[]){
1460 "d0",
"d1",
"d2",
"d3",
1461 "d4",
"d5",
"d6",
"d7",
1462 "a8",
"a9",
"a10",
"a11",
1468 "microwire", (
const char *[]){
1469 "cs",
"sk",
"si",
"so", NULL,
1473 "sdcard_sd", (
const char *[]){
1475 "dat0",
"dat1",
"dat2",
"dat3",
1480 "seven_segment", (
const char *[]){
1481 "a",
"b",
"c",
"d",
"e",
"f",
"g",
1486 "spi", (
const char *[]){
1487 "clk",
"miso",
"mosi",
"cs", NULL,
1491 "swd", (
const char *[]){
1492 "swclk",
"swdio", NULL,
1496 "uart", (
const char *[]){
1501 "usb", (
const char *[]){
1506 "z80", (
const char *[]){
1507 "d0",
"d1",
"d2",
"d3",
1508 "d4",
"d5",
"d6",
"d7",
1511 "a0",
"a1",
"a2",
"a3",
1512 "a4",
"a5",
"a6",
"a7",
1513 "a8",
"a9",
"a10",
"a11",
1514 "a12",
"a13",
"a14",
"a15",
1521 static const char **lookup_probe_alias(
const char *
name)
1525 for (idx = 0; idx < ARRAY_SIZE(probe_name_aliases); idx++) {
1526 if (g_ascii_strcasecmp(probe_name_aliases[idx].name, name) != 0)
1528 return probe_name_aliases[idx].expands;
1564 const char **dflt_names,
size_t dflt_count,
1565 size_t max_count,
size_t *ret_count)
1567 char **result_names;
1568 size_t result_count;
1569 gboolean pad_from_dflt;
1570 char **spec_names, *spec_name;
1572 const char **alias_names;
1574 if (!spec || !*spec)
1583 while (dflt_names && dflt_names[dflt_count])
1593 result_names = NULL;
1595 pad_from_dflt = TRUE;
1608 if (spec && *spec ==
'-') {
1610 pad_from_dflt = FALSE;
1613 spec_names = g_strsplit(spec,
",", 0);
1614 for (spec_idx = 0; spec_names && spec_names[spec_idx]; spec_idx++) {
1615 spec_name = spec_names[spec_idx];
1618 alias_names = lookup_probe_alias(spec_name);
1620 result_names = append_probe_names(result_names,
1621 &result_count, alias_names);
1623 result_names = append_probe_name(result_names,
1624 &result_count, spec_name);
1627 g_strfreev(spec_names);
1634 if (pad_from_dflt)
do {
1635 if (max_count && result_count >= max_count)
1637 if (result_count >= dflt_count)
1639 result_names = append_probe_name(result_names, &result_count,
1640 dflt_names[result_count]);
1645 while (result_count > max_count) {
1647 g_free(result_names[result_count]);
1648 result_names[result_count] = NULL;
1653 *ret_count = result_count;
1655 return result_names;
1689 while (p > s && isspace((
int)p[-1]))
1691 while (isspace((
int)*s))
1751 if (!s || !*s || !l)
1755 p = g_strstr_len(s, l,
"\n");
1763 *next = l ? p : NULL;
1793 if (!word || !*word)
1797 while (isspace((
int)*word))
1808 while (*p && !isspace((
int)*p))
1813 while (isspace((
int)*p))
1865 check_mask |= 1UL << 0;
1866 }
while (value & ~check_mask);
1871 *power = ++check_mask;
int sr_sprintf_ascii(char *buf, const char *format,...)
Compose a string with a format string in the buffer pointed to by buf.
char * sr_text_next_line(char *s, size_t l, char **next, size_t *taken)
Check for another complete text line, trim, return consumed char count.
gboolean sr_parse_boolstring(const char *boolstr)
int sr_vsprintf_ascii(char *buf, const char *format, va_list args)
Compose a string with a format string in the buffer pointed to by buf.
int sr_parse_rational(const char *str, struct sr_rational *ret)
Convert a string representation of a numeric value to a sr_rational.
char * sr_si_string_u64(uint64_t x, const char *unit)
Convert a numeric value value to its "natural" string representation in SI units. ...
int sr_snprintf_ascii(char *buf, size_t buf_size, const char *format,...)
Composes a string with a format string (like printf) in the buffer pointed by buf (taking buf_size as...
char * sr_text_trim_spaces(char *s)
Trim leading and trailing whitespace off text.
int64_t p
Numerator of the rational number.
uint64_t sr_parse_timestring(const char *timestring)
Convert a "natural" string representation of a time value to an uint64_t value in milliseconds...
int sr_next_power_of_two(size_t value, size_t *bits, size_t *power)
Get the number of necessary bits to hold a given value.
int sr_parse_voltage(const char *voltstr, uint64_t *p, uint64_t *q)
char ** sr_parse_probe_names(const char *spec, const char **dflt_names, size_t dflt_count, size_t max_count, size_t *ret_count)
Parse a probe names specification, allocate a string vector.
int sr_parse_period(const char *periodstr, uint64_t *p, uint64_t *q)
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...
Generic/unspecified error.
char * sr_text_next_word(char *s, char **next)
Isolates another space separated word in a text line.
int sr_vsnprintf_ascii(char *buf, size_t buf_size, const char *format, va_list args)
Composes a string with a format string (like printf) in the buffer pointed by buf (taking buf_size as...
char * sr_samplerate_string(uint64_t samplerate)
Convert a numeric samplerate value to its "natural" string representation.
SR_PRIV int sr_atod_ascii_digits(const char *str, double *ret, int *digits)
Convert text to a floating point value, and get its precision.
uint64_t q
Denominator of the rational number.
The public libsigrok header file to be used by frontends.
char * sr_period_string(uint64_t v_p, uint64_t v_q)
Convert a numeric period value to the "natural" string representation of its period value...
void sr_free_probe_names(char **names)
Release previously allocated probe names (string vector).
int sr_parse_sizestring(const char *sizestring, uint64_t *size)
Convert a "natural" string representation of a size value to uint64_t.
char * name
Name of channel.