mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
253 lines
18 KiB
C++
253 lines
18 KiB
C++
#include "fast_float/fast_float.h"
|
|
#include <iostream>
|
|
#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(const char* start, char** end) {
|
|
double d;
|
|
std::stringstream ss;
|
|
ss.imbue(std::locale::classic());
|
|
ss << start;
|
|
ss >> d;
|
|
size_t nread = ss.tellg();
|
|
*end = const_cast<char*>(start) + nread;
|
|
return d;
|
|
}
|
|
#endif
|
|
|
|
inline void Assert(bool Assertion) {
|
|
if (!Assertion)
|
|
throw std::runtime_error("bug");
|
|
}
|
|
|
|
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()};
|
|
const char * begin = input.data();
|
|
const char * end = input.data() + input.size();
|
|
for(size_t i = 0; i < answers.size(); i++) {
|
|
T result_value;
|
|
auto result = fast_float::from_chars(begin, end,
|
|
result_value);
|
|
if (result.ec != std::errc()) {
|
|
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(const std::string &st, T& d);
|
|
|
|
template <>
|
|
void strtod_from_string(const std::string &st, double& d) {
|
|
char *pr = (char *)st.c_str();
|
|
#ifdef _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(const std::string &st, float& d) {
|
|
char *pr = (char *)st.c_str();
|
|
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun)
|
|
d = cygwin_strtod_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
|
|
const std::string 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(const std::string& 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()) {
|
|
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 detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << 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;
|
|
}
|