|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
Locale-tolerant numeric parsing with unit suffixes. More...
#include <stdbool.h>#include <stddef.h>Go to the source code of this file.
Data Structures | |
| struct | log_value_t |
A cell split into its parts. digits keeps its separators. More... | |
| struct | log_votes_t |
| Running tally of the evidence seen so far. More... | |
| struct | log_unit_tally_t |
| Tally of unit suffixes seen in one column, in first-seen order. More... | |
Enumerations | |
| enum | log_conv_t { LOG_CONV_AUTO = 0 , LOG_CONV_DE , LOG_CONV_EN } |
| Decimal convention of a file. More... | |
| enum | log_ambig_t { LOG_AMBIG_THOUSANDS = 0 , LOG_AMBIG_DECIMAL } |
| What a wholly ambiguous file defaults to. More... | |
| enum | log_evidence_t { LOG_EV_NONE = 0 , LOG_EV_AMBIGUOUS , LOG_EV_DE , LOG_EV_EN } |
| What one numeric string proves about the convention. More... | |
Functions | |
| bool | log_split_value (const char *raw, log_value_t *out) |
| Split a raw cell into numeric text, exponent and unit. | |
| log_evidence_t | log_evidence_of (const char *digits) |
| Inspect one already-split numeric string and report what it proves. | |
| void | log_votes_reset (log_votes_t *v) |
| Clear the tally. | |
| void | log_votes_add (log_votes_t *v, const char *raw) |
| Feed one raw cell. | |
| log_conv_t | log_votes_result (const log_votes_t *v, log_ambig_t fallback, bool *confident, bool *conflict) |
| Decide the convention from the tally. | |
| bool | log_is_well_formed (const char *digits, log_conv_t convention) |
Is digits well formed under convention? | |
| bool | log_parse_with (const char *raw, log_conv_t convention, double *value, char *unit, size_t unit_size) |
| Parse one cell with a known convention. | |
| bool | log_parse_loose (const char *raw, log_ambig_t fallback, double *value) |
| Parse a standalone value, inferring the convention from it alone. | |
| void | log_unit_tally_reset (log_unit_tally_t *t) |
| Clear a unit tally. | |
| void | log_unit_tally_add (log_unit_tally_t *t, const char *unit) |
| Add a unit suffix to a tally. | |
| void | log_unit_dominant (const log_unit_tally_t *t, char *out, size_t out_size, bool *mixed) |
The most common non-empty suffix. mixed reports more than one. | |
| void | log_unit_from_header (const char *header, char *name, size_t name_size, char *unit, size_t unit_size) |
| Pull a unit out of a column header: "voltage (V)", "current [A]", "speed km/h", "power (W)". "gyroADC[0]" keeps its index – that is an axis number, not a unit. | |
| double | log_time_unit_scale (const char *unit) |
| Seconds per unit for a time column, or 0 when the name is not a time unit. | |
Locale-tolerant numeric parsing with unit suffixes.
"1,234" is ambiguous: German reads 1.234, English reads 1234. Guessing per value is unsafe, because the same column would then parse inconsistently: "1,234" as 1234 on one row and "10,23" as 10.23 on the next implies two conventions in one column, which no exporter produces.
So the convention is decided per file, from every value in it. Most files contain at least one value that settles it:
"1.234,56" both separators -> the last one is the decimal (German) "1,234.56" both separators -> the last one is the decimal (English) "10,23" one, 2 trailing -> not a thousands group (German) "1.5" one, 1 trailing -> not a thousands group (English) "1.234.567" repeated -> that separator groups (German) "1,234" one, 3 trailing -> ambiguous, no evidence
Only when every value is ambiguous does the fallback apply.
The evidence gatherer is a streaming accumulator rather than a function over an array: the firmware reads logs off a card and never holds the whole file. Values arrive once, are voted on, and are forgotten.
Pure C, no ESP-IDF.
SPDX-License-Identifier: MIT
| enum log_ambig_t |
| enum log_conv_t |
| enum log_evidence_t |
| log_evidence_t log_evidence_of | ( | const char * | digits | ) |
Inspect one already-split numeric string and report what it proves.
| digits | Numeric text as log_split_value() gives it. |
| bool log_is_well_formed | ( | const char * | digits, |
| log_conv_t | convention ) |
Is digits well formed under convention?
Strict on purpose. Stripping the grouping separator and parsing what is left turns the German "1.234,56" into 1.23456 when read as English: a silently wrong number. Rejecting lets the caller surface the mismatch.
| digits | Numeric text as log_split_value() gives it. |
| convention | The convention to check against. |
| bool log_parse_loose | ( | const char * | raw, |
| log_ambig_t | fallback, | ||
| double * | value ) |
Parse a standalone value, inferring the convention from it alone.
| raw | The raw cell text. |
| fallback | The default for an ambiguous value. |
| value | Receives the number. |
| bool log_parse_with | ( | const char * | raw, |
| log_conv_t | convention, | ||
| double * | value, | ||
| char * | unit, | ||
| size_t | unit_size ) |
Parse one cell with a known convention.
| raw | The raw cell text. |
| convention | The convention of the file. |
| value | Receives the number. |
| unit | Receives the unit suffix. |
| unit_size | Size of unit, bytes. |
| bool log_split_value | ( | const char * | raw, |
| log_value_t * | out ) |
Split a raw cell into numeric text, exponent and unit.
Grouping characters that are never decimal points – ASCII space, the apostrophe Swiss exporters use, U+00A0 and U+202F – are removed here, so digits carries only digits, '.' and ','.
| raw | The raw cell text. |
| out | Receives the parts. |
| double log_time_unit_scale | ( | const char * | unit | ) |
Seconds per unit for a time column, or 0 when the name is not a time unit.
| unit | The unit name. |
| void log_unit_dominant | ( | const log_unit_tally_t * | t, |
| char * | out, | ||
| size_t | out_size, | ||
| bool * | mixed ) |
The most common non-empty suffix. mixed reports more than one.
| t | The tally. |
| out | Receives the suffix. |
| out_size | Size of out, bytes. |
| mixed | Receives true when more than one suffix was seen. |
| void log_unit_from_header | ( | const char * | header, |
| char * | name, | ||
| size_t | name_size, | ||
| char * | unit, | ||
| size_t | unit_size ) |
Pull a unit out of a column header: "voltage (V)", "current [A]", "speed km/h", "power (W)". "gyroADC[0]" keeps its index – that is an axis number, not a unit.
| header | The column header. |
| name | Receives the name without the unit. |
| name_size | Size of name, bytes. |
| unit | Receives the unit. |
| unit_size | Size of unit, bytes. |
| void log_unit_tally_add | ( | log_unit_tally_t * | t, |
| const char * | unit ) |
Add a unit suffix to a tally.
| t | The tally. |
| unit | The unit suffix. |
| void log_unit_tally_reset | ( | log_unit_tally_t * | t | ) |
Clear a unit tally.
| t | The tally. |
| void log_votes_add | ( | log_votes_t * | v, |
| const char * | raw ) |
Feed one raw cell.
Cells that hold no number are ignored.
| v | The tally. |
| raw | The raw cell text. |
| void log_votes_reset | ( | log_votes_t * | v | ) |
Clear the tally.
| v | The tally. |
| log_conv_t log_votes_result | ( | const log_votes_t * | v, |
| log_ambig_t | fallback, | ||
| bool * | confident, | ||
| bool * | conflict ) |
Decide the convention from the tally.
| v | The tally. |
| fallback | The default for a wholly ambiguous file. |
| confident | set false when nothing proved anything and the fallback had to decide. |
| conflict | set true when both conventions were proven, which means the file itself is inconsistent; the caller reports it rather than silently picking the winner. |