number_text.h
Numbers in text, whatever the C locale says.
#include <sonore/number_text.h>- 4other declarations
On this page
Design notes
A plugin does not own its process. Hosts call setlocale() -- a German or a Spanish DAW sets LC_NUMERIC to a comma locale -- and from then on every printf("%g") in the plugin writes "0,5" and every strtod reads "0.5" as 0. In a JSON settings file that turns [0.5] into [0,5], two numbers; in an SVG it truncates every coordinate at the point; in a saved state it puts a knob back at zero. Nobody sees it on the developer's machine.
The fix is the one every portable parser uses: format with the C library, which rounds correctly, then turn the locale's decimal point into '.'; and parse by turning '.' into the locale's decimal point first. The library does the arithmetic -- exactly, which a hand-written digit loop does not -- and only the one character that varies is translated.
Functions 4
- fn
inline char localeDecimalPoint()The decimal point the C library is using right now.numtext::localeDecimalPoint · number_text.h:28 - fn
inline void format(char* out, size_t capacity, double value, const char* format = "%.17g")Format withnumtext::format · number_text.h:35format(a single floating conversion, "%.17g" by default -- enough digits that the value reads back exactly) and '.' as the point. - fn
inline size_t parse(const char* text, size_t length, double* out)Parse a number written with '.' from the start ofnumtext::parse · number_text.h:48text(at mostlengthcharacters). Returns how many characters it used, 0 if there was no number there;*outis untouched then. Correctly rounded, because the C library does the conversion. - fn
inline double parseOr(const std::string& text, double fallback)The numbernumtext::parseOr · number_text.h:88textstarts with, as parse() reads it, orfallbackwhen it does not start with one. Text after the number is ignored, so "12abc" is 12 and "2.5 dB" is 2.5 -- what ApplicationProperties::getDoubleValue promises, as the reference's string-to-double does; leading spaces are not skipped. A caller that must refuse trailing text uses parse() and compares the count it returns with the length.