fast_float/tests/string_test.cpp
Anders Dalvander 3775a81ced formatted code
2024-12-01 16:39:28 +01:00

1135 lines
22 KiB
C++

#include "fast_float/fast_float.h"
#include <cctype>
#include <cstdio>
#include <iostream>
#include <limits>
#include <stdexcept>
#include <string>
#include <system_error>
#include <vector>
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || \
defined(sun) || defined(__sun)
// Anything at all that is related to cygwin, msys and so forth will
// always use this fallback because we cannot rely on it behaving as normal
// gcc.
#include <locale>
#include <sstream>
// workaround for CYGWIN
double cygwin_strtod_l(char const *start, char **end) {
double d;
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
if (ss.fail()) {
*end = nullptr;
}
if (ss.eof()) {
ss.clear();
}
auto nread = ss.tellg();
*end = const_cast<char *>(start) + nread;
return d;
}
float cygwin_strtof_l(char const *start, char **end) {
float d;
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << start;
ss >> d;
if (ss.fail()) {
*end = nullptr;
}
if (ss.eof()) {
ss.clear();
}
auto nread = ss.tellg();
*end = const_cast<char *>(start) + nread;
return d;
}
#endif
inline void Assert(bool Assertion) {
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || \
defined(sun) || defined(__sun)
if (!Assertion) {
std::cerr << "Omitting hard failure on msys/cygwin/sun systems.";
}
#else
if (!Assertion) {
throw std::runtime_error("bug");
}
#endif
}
template <typename T> std::string to_string(T d) {
std::string s(64, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.*e",
std::numeric_limits<T>::max_digits10 - 1, d);
s.resize(size_t(written));
return s;
}
template <typename T> bool test() {
std::string input =
"0.1 1e1000 100000 3.14159265359 -1e-500 001 1e01 1e0000001 -inf";
std::vector<T> answers = {T(0.1),
std::numeric_limits<T>::infinity(),
100000,
T(3.14159265359),
-0.0,
1,
10,
10,
-std::numeric_limits<T>::infinity()};
std::vector<std::errc> expected_ec = {std::errc(),
std::errc::result_out_of_range,
std::errc(),
std::errc(),
std::errc::result_out_of_range,
std::errc(),
std::errc(),
std::errc(),
std::errc()};
char const *begin = input.data();
char const *end = input.data() + input.size();
for (size_t i = 0; i < answers.size(); i++) {
T result_value;
while ((begin < end) && (std::isspace(*begin))) {
begin++;
}
auto result = fast_float::from_chars(begin, end, result_value);
if (result.ec != expected_ec[i]) {
printf("parsing %.*s\n", int(end - begin), begin);
std::cerr << " I could not parse " << std::endl;
return false;
}
if (result_value != answers[i]) {
printf("parsing %.*s\n", int(end - begin), begin);
std::cerr << " Mismatch " << std::endl;
return false;
}
begin = result.ptr;
}
if (begin != end) {
std::cerr << " bad ending " << std::endl;
return false;
}
return true;
}
template <typename T> void strtod_from_string(std::string const &st, T &d);
template <> void strtod_from_string(std::string const &st, double &d) {
char *pr = (char *)st.c_str();
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || \
defined(sun) || defined(__sun)
d = cygwin_strtod_l(pr, &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtod_l(st.c_str(), &pr, c_locale);
#else
static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL);
d = strtod_l(st.c_str(), &pr, c_locale);
#endif
if (pr == st.c_str()) {
throw std::runtime_error("bug in strtod_from_string");
}
}
template <> void strtod_from_string(std::string const &st, float &d) {
char *pr = (char *)st.c_str();
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || \
defined(sun) || defined(__sun)
d = cygwin_strtof_l(st.c_str(), &pr);
#elif defined(_WIN32)
static _locale_t c_locale = _create_locale(LC_ALL, "C");
d = _strtof_l(st.c_str(), &pr, c_locale);
#else
static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL);
d = strtof_l(st.c_str(), &pr, c_locale);
#endif
if (pr == st.c_str()) {
throw std::runtime_error("bug in strtod_from_string");
}
}
template <typename T> bool partow_test() {
// credit:
// https://github.com/ArashPartow/strtk/blob/master/strtk_tokenizer_cmp.cpp#L568
// MIT license
std::string const strint_list[] = {
"9007199254740993",
"9007199254740994",
"9007199254740995",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"917049",
"4931205",
"6768064",
"6884243",
"5647132",
"7371203",
"-8629878",
"4941840",
"4543268",
"1075600",
"290",
"823",
"111",
"715",
"-866",
"367",
"666",
"-706",
"850",
"-161",
"9922547",
"6960207",
"1883152",
"2300759",
"-279294",
"4187292",
"3699841",
"8386395",
"-1441129",
"-887892",
"-635422",
"9742573",
"2326186",
"-5903851",
"5648486",
"3057647",
"2980079",
"2957468",
"7929158",
"1925615",
"879",
"130",
"292",
"705",
"817",
"446",
"576",
"750",
"523",
"-527",
"4365041",
"5624958",
"8990205",
"2652177",
"3993588",
"-298316",
"2901599",
"3887387",
"-5202979",
"1196268",
"5968501",
"7619928",
"3565643",
"1885272",
"-749485",
"2961381",
"2982579",
"2387454",
"4250081",
"5958205",
"00000",
"00001",
"00002",
"00003",
"00004",
"00005",
"00006",
"00007",
"00008",
"00009",
"4907034",
"2592882",
"3269234",
"549815",
"6256292",
"9721039",
"-595225",
"5587491",
"4596297",
"-3885009",
"673",
"-899",
"174",
"354",
"870",
"147",
"898",
"-510",
"369",
"859",
"6518423",
"5149762",
"8834164",
"-8085586",
"3233120",
"8166948",
"4172345",
"6735549",
"-934295",
"9481935",
"-430406",
"6932717",
"4087292",
"4047263",
"3236400",
"-3863050",
"4312079",
"6956261",
"5689446",
"3871332",
"535",
"691",
"326",
"-409",
"704",
"-568",
"301",
"951",
"121",
"384",
"4969414",
"9378599",
"7971781",
"5380630",
"5001363",
"1715827",
"6044615",
"9118925",
"9956168",
"-8865496",
"5962464",
"7408980",
"6646513",
"-634564",
"4188330",
"9805948",
"5625691",
"7641113",
"-4212929",
"7802447",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"2174248",
"7449361",
"9896659",
"-25961",
"1706598",
"2412368",
"-4617035",
"6314554",
"2225957",
"7521434",
"-9530566",
"3914164",
"2394759",
"7157744",
"9919392",
"6406949",
"-744004",
"9899789",
"8380325",
"-1416284",
"3402833",
"2150043",
"5191009",
"8979538",
"9565778",
"3750211",
"7304823",
"2829359",
"6544236",
"-615740",
"363",
"-627",
"129",
"656",
"135",
"113",
"381",
"646",
"198",
"38",
"8060564",
"-176752",
"1184717",
"-666343",
"-1273292",
"-485827",
"6241066",
"6579411",
"8093119",
"7481306",
"-4924485",
"7467889",
"9813178",
"7927100",
"3614859",
"7293354",
"9232973",
"4323115",
"1133911",
"9511638",
"4443188",
"2289448",
"5639726",
"9073898",
"8540394",
"5389992",
"1397726",
"-589230",
"1017086",
"1852330",
"-840",
"267",
"201",
"533",
"-675",
"494",
"315",
"706",
"-920",
"784",
"9097353",
"6002251",
"-308780",
"-3830169",
"4340467",
"2235284",
"3314444",
"1085967",
"4152107",
"5431117",
"-0000",
"-0001",
"-0002",
"-0003",
"-0004",
"-0005",
"-0006",
"-0007",
"-0008",
"-0009",
"-444999",
"2136400",
"6925907",
"6990614",
"3588271",
"8422028",
"-4034772",
"5804039",
"-6740545",
"9381873",
"-924923",
"1652367",
"2302616",
"6776663",
"2567821",
"-248935",
"2587688",
"7076742",
"-6461467",
"1562896",
"-768116",
"2338768",
"9887307",
"9992184",
"2045182",
"2797589",
"9784597",
"9696554",
"5113329",
"1067216",
"-76247763",
"58169007",
"29408062",
"85342511",
"42092201",
"-95817703",
"-1912517",
"-26275135",
"54656606",
"-58188878",
"473",
"74",
"374",
"-64",
"266",
"715",
"937",
"-249",
"249",
"780",
"3907360",
"-23063423",
"59062754",
"83711047",
"-95221044",
"34894840",
"-38562139",
"-82018330",
"14226223",
"-10799717",
"8529722",
"88961903",
"25608618",
"-39988247",
"33228241",
"38598533",
"21161480",
"-33723784",
"8873948",
"96505557",
"-47385048",
"-79413272",
"-85904404",
"87791158",
"49194195",
"13051222",
"57773302",
"31904423",
"3142966",
"27846156",
"7420011",
"-72376922",
"-68873971",
"23765361",
"4040725",
"-22359806",
"85777219",
"10099223",
"-90364256",
"-40158172",
"-7948696",
"-64344821",
"34404238",
"84037448",
"-85084788",
"-42078409",
"-56550310",
"96898389",
"-595829",
"-73166703",
"-0",
"-1",
"-2",
"-3",
"-4",
"-5",
"-6",
"-7",
"-8",
"-9",
"2147483647",
"31",
"2147483610",
"33",
"2147483573",
"37",
"2147483536",
"-82838342",
"64441808",
"43641062",
"-64419642",
"-44421934",
"75232413",
"-75773725",
"-89139509",
"12812089",
"-97633526",
"36090916",
"-57706234",
"17804655",
"4189936",
"-4100124",
"38803710",
"-39735126",
"-62397437",
"75801648",
"51302332",
"73433906",
"13015224",
"-12624818",
"91360377",
"11576319",
"-54467535",
"8892431",
"36319780",
"38832042",
"50172572",
"-317",
"109",
"-888",
"302",
"-463",
"716",
"916",
"665",
"826",
"513",
"42423473",
"41078812",
"40445652",
"-76722281",
"95092224",
"12075234",
"-4045888",
"-74396490",
"-57304222",
"-21726885",
"92038121",
"-31899682",
"21589254",
"-30260046",
"56000244",
"69686659",
"93327838",
"96882881",
"-91419389",
"77529147",
"43288506",
"1192435",
"-74095920",
"76756590",
"-31184683",
"-35716724",
"9451980",
"-63168350",
"62864002",
"26283194",
"37188395",
"29151634",
"99343471",
"-69450330",
"-55680090",
"-64957599",
"47577948",
"47107924",
"2490477",
"48633003",
"-82740809",
"-24122215",
"67301713",
"-63649610",
"75499016",
"82746620",
"17052193",
"4602244",
"-32721165",
"20837836",
"674",
"467",
"706",
"889",
"172",
"282",
"-795",
"188",
"87",
"153",
"64501793",
"53146328",
"5152287",
"-9674493",
"68105580",
"57245637",
"39740229",
"-74071854",
"86777268",
"86484437",
"-86962508",
"12644427",
"-62944073",
"59539680",
"43340539",
"30661534",
"20143968",
"-68183731",
"-48250926",
"42669063",
"000",
"001",
"002",
"003",
"004",
"005",
"006",
"007",
"008",
"009",
"2147483499",
"71",
"2147483462",
"73",
"2147483425",
"77",
"2147483388",
"87736852",
"-4444906",
"-48094147",
"54774735",
"54571890",
"-22473078",
"95053418",
"393654",
"-33229960",
"32276798",
"-48361110",
"44295939",
"-79813406",
"11630865",
"38544571",
"70972830",
"-9821748",
"-60965384",
"-13096675",
"-24569041",
"708",
"-467",
"-794",
"610",
"929",
"766",
"152",
"482",
"397",
"-191",
"97233152",
"51028396",
"-13796948",
"95437272",
"71352512",
"-83233730",
"-68517318",
"61832742",
"-42667174",
"-18002395",
"-92239407",
"12701336",
"-63830875",
"41514172",
"-5726049",
"18668677",
"69555144",
"-13737009",
"-22626233",
"-55078143",
"00",
"11",
"22",
"33",
"44",
"-00",
"-11",
"-22",
"-33",
"-44",
"000",
"111",
"222",
"333",
"444",
"-000",
"-111",
"-222",
"-333",
"-444",
"0000",
"1111",
"2222",
"3333",
"4444",
"-0000",
"-1111",
"-2222",
"-3333",
"-4444",
"00000",
"11111",
"22222",
"33333",
"44444",
"-00000",
"-11111",
"-22222",
"-33333",
"-44444",
"000000",
"111111",
"222222",
"333333",
"444444",
"-000000",
"-111111",
"-222222",
"-333333",
"-444444",
"0000000",
"1111111",
"2222222",
"3333333",
"4444444",
"-0000000",
"-1111111",
"-2222222",
"-3333333",
"-4444444",
"00000000",
"11111111",
"22222222",
"33333333",
"44444444",
"-00000000",
"-11111111",
"-22222222",
"-33333333",
"-44444444",
"000000000",
"111111111",
"222222222",
"333333333",
"444444444",
"-000000000",
"-111111111",
"-222222222",
"-333333333",
"-444444444",
"2147483351",
"51",
"2147483314",
"53",
"-2147483648",
"57",
"-2147483611",
"55",
"66",
"77",
"88",
"99",
"-55",
"-66",
"-77",
"-88",
"-99",
"555",
"666",
"777",
"888",
"999",
"-555",
"-666",
"-777",
"-888",
"-999",
"5555",
"6666",
"7777",
"8888",
"9999",
"-5555",
"-6666",
"-7777",
"-8888",
"-9999",
"55555",
"66666",
"77777",
"88888",
"99999",
"-55555",
"-66666",
"-77777",
"-88888",
"-99999",
"555555",
"666666",
"777777",
"888888",
"999999",
"-555555",
"-666666",
"-777777",
"-888888",
"-999999",
"5555555",
"6666666",
"7777777",
"8888888",
"9999999",
"-5555555",
"-6666666",
"-7777777",
"-8888888",
"-9999999",
"55555555",
"66666666",
"77777777",
"88888888",
"99999999",
"-55555555",
"-66666666",
"-77777777",
"-88888888",
"-99999999",
"555555555",
"666666666",
"777777777",
"888888888",
"999999999",
"-555555555",
"-666666666",
"-777777777",
"-888888888",
"-999999999",
"-2147483574",
"91",
"-2147483537",
"93",
"-2147483500",
"97",
"-2147483463",
"0000000011",
"0000000022",
"0000000033",
"0000000044",
"-000000011",
"-000000022",
"-000000033",
"-000000044",
"-000000088",
"0000000111",
"0000000222",
"0000000333",
"0000000444",
"-000000111",
"-000000222",
"-000000333",
"-000000444",
"-000000888",
"0000001111",
"0000002222",
"0000003333",
"0000004444",
"-000001111",
"-000002222",
"-000003333",
"-000004444",
"-000008888",
"0000011111",
"0000022222",
"0000033333",
"0000044444",
"-000011111",
"-000022222",
"-000033333",
"-000044444",
"-000088888",
"0000111111",
"0000222222",
"0000333333",
"0000444444",
"-000111111",
"-000222222",
"-000333333",
"-000444444",
"-000888888",
"0001111111",
"0002222222",
"0003333333",
"0004444444",
"-001111111",
"-002222222",
"-003333333",
"-004444444",
"-008888888",
"0011111111",
"0022222222",
"0033333333",
"0044444444",
"-011111111",
"-022222222",
"-033333333",
"-044444444",
"-088888888",
"0111111111",
"0222222222",
"0333333333",
"0444444444",
"-111111111",
"-222222222",
"-333333333",
"-444444444",
"-888888888",
"0000000055",
"0000000066",
"0000000077",
"0000000088",
"0000000099",
"-000000055",
"-000000066",
"-000000077",
"-000000099",
"0000000555",
"0000000666",
"0000000777",
"0000000888",
"0000000999",
"-000000555",
"-000000666",
"-000000777",
"-000000999",
"0000005555",
"0000006666",
"0000007777",
"0000008888",
"0000009999",
"-000005555",
"-000006666",
"-000007777",
"-000009999",
"0000055555",
"0000066666",
"0000077777",
"0000088888",
"0000099999",
"-000055555",
"-000066666",
"-000077777",
"-000099999",
"0000555555",
"0000666666",
"0000777777",
"0000888888",
"0000999999",
"-000555555",
"-000666666",
"-000777777",
"-000999999",
"0005555555",
"0006666666",
"0007777777",
"0008888888",
"0009999999",
"-005555555",
"-006666666",
"-007777777",
"-009999999",
"0055555555",
"0066666666",
"0077777777",
"0088888888",
"0099999999",
"-055555555",
"-066666666",
"-077777777",
"-099999999",
"0555555555",
"0666666666",
"0777777777",
"0888888888",
"0999999999",
"-555555555",
"-666666666",
"-777777777",
"-999999999",
"-2147483426",
"101",
"-2147483389",
"103",
"-2147483352",
"105",
"-2147483315",
"0000001234567890",
"0000001234567890",
"-0000001234567890",
"000001234567890",
"000001234567890",
"-000001234567890",
"00001234567890",
"00001234567890",
"-00001234567890",
"0001234567890",
"0001234567890",
"-0001234567890",
"001234567890",
"001234567890",
"-001234567890",
"01234567890",
"01234567890",
"-01234567890",
"1234567890",
"1234567890",
"-1234567890",
};
for (std::string const &st : strint_list) {
T expected_value;
strtod_from_string(st, expected_value);
T result_value;
auto result =
fast_float::from_chars(st.data(), st.data() + st.size(), result_value);
if (result.ec != std::errc() &&
result.ec != std::errc::result_out_of_range) {
printf("parsing %.*s\n", int(st.size()), st.data());
std::cerr << " I could not parse " << std::endl;
return false;
}
if (result.ptr != st.data() + st.size()) {
printf("parsing %.*s\n", int(st.size()), st.data());
std::cerr << " Did not get to the end " << std::endl;
return false;
}
if (result_value != expected_value) {
printf("parsing %.*s\n", int(st.size()), st.data());
std::cerr << "expected value : " << to_string(expected_value)
<< std::endl;
std::cerr << "result value : " << to_string(result_value) << std::endl;
std::cerr << " Mismatch " << std::endl;
return false;
}
}
return true;
}
int main() {
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || \
defined(sun) || defined(__sun)
std::cout << "Warning: msys/cygwin or solaris detected." << std::endl;
#endif
std::cout << "32 bits checks" << std::endl;
Assert(partow_test<float>());
Assert(test<float>());
std::cout << "64 bits checks" << std::endl;
Assert(partow_test<double>());
Assert(test<double>());
std::cout << "All ok" << std::endl;
return EXIT_SUCCESS;
}