-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathsplit_test.cpp
More file actions
165 lines (156 loc) · 5.29 KB
/
Copy pathsplit_test.cpp
File metadata and controls
165 lines (156 loc) · 5.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#define _SCL_SECURE_NO_WARNINGS
#define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING
#include "split_iterator.h"
#include "chash_set.h"
#include <chrono>
#include <iostream>
#include <random>
#include <unordered_map>
#include <unordered_set>
#include <cstring>
#include <string>
#include <climits>
#define assert(exp) assert_proc(exp, #exp, __FILE__, __LINE__)
auto assert_proc = [](bool no_error, char const *query, char const *file, size_t line)
{
if(!no_error)
{
struct hasher
{
size_t operator()(std::tuple<char const *, char const *, size_t> const &ref) const
{
return std::hash<std::uintptr_t>()(reinterpret_cast<std::uintptr_t>(std::get<0>(ref))) ^
std::hash<std::uintptr_t>()(reinterpret_cast<std::uintptr_t>(std::get<1>(ref))) ^
std::hash<size_t>()(std::get<2>(ref));
}
};
static chash_set<std::tuple<char const *, char const *, size_t>, hasher> check;
if(check.emplace(query, file, line).second)
{
printf("%s(%zd):%s\n", file, line, query);
}
}
};
int main()
{
auto test_to_real = [](char const *s)
{
double l = std::atof(s);
double r = to_value<double>(string_ref<>(s));
double rel = (l == 0.0) ? 0.0 : (l - r) / l;
printf("%f\n%f\n%f\n\n", l, r, rel);
};
test_to_real("1234567890.1234567890");
test_to_real("-1234567890.1234567890e3");
test_to_real("1234567890.1234567890e-3");
test_to_real("1234567890123456789012345678901234567890.1234567890");
test_to_real("-1234567890123456789012345678901234567890.1234567890e3");
test_to_real("1234567890123456789012345678901234567890.1234567890e-3");
test_to_real("0.000000000000000000000000000000000000123456789012345678901234567890");
test_to_real("-0.000000000000000000000000000000000000123456789012345678901234567890e3");
test_to_real("0.000000000000000000000000000000000000123456789012345678901234567890e-3");
[]
{
std::string str = "1234,5678.9012 3456";
for(auto item : make_split_any_of(str, ",. "))
{
if(item != "1234")
{
std::cout << to_value<float>(item) << std::endl;
}
}
for(auto item : make_split(str, "34"))
{
// Tokens may contain non-numeric characters; the new free-function
// to_value<int> reports that via std::invalid_argument, swallow
// it here so the demo loop keeps printing.
try
{
std::cout << to_value<int>(item) << std::endl;
}
catch(std::exception const &)
{
std::cout << 0 << std::endl;
}
}
}();
[]
{
std::string str = "/1//23/456///";
auto split = make_split(str, '/');
std::vector<std::string> token;
// std::copy through back_inserter requires implicit construction of
// std::string from the iterator's reference; std::string_view's
// string constructor is explicit (C++17), so build the strings
// manually instead.
for(auto item : split)
{
token.emplace_back(item.data(), item.size());
}
for(auto item : token)
{
std::cout << item << std::endl;
}
}();
[]
{
std::string str = "/1//23/456///";
auto split = make_split(str, '/');
for(size_t i = 0; i <= split.size(); ++i)
{
// to_value<int>() on an empty field throws invalid_argument under
// the new free-function API; guard explicitly so the demo loop
// still prints a placeholder for empty / out-of-range fields.
auto field = split[i];
if(field.empty())
{
std::cout << 0 << std::endl;
}
else
{
std::cout << to_value<int>(field) << std::endl;
}
}
}();
[]
{
auto str = "aaa,111,ccc";
std::string v1;
int v2 = 0;
string_ref<> v3;
make_split(string_ref<>(str), ',').fill(v1, v2, v3);
assert(v1 == "aaa");
assert(v2 == 111);
assert(v3 == "ccc");
}();
[]
{
std::wstring str = L"aaa,111,ccc";
std::wstring v1;
float v2 = 0.0f;
string_ref<wchar_t> v3;
make_split(str, L',').fill(v1, v2, v3);
assert(v1 == L"aaa");
assert(v2 == 111.0f);
assert(v3 == L"ccc");
}();
// Unsigned wrap-around (matches std::stoul semantics) — both the
// C++11/14 fallback and the C++17 std::from_chars path must agree.
{
unsigned u1 = to_value<unsigned>(string_ref<>("-5"));
assert(u1 == UINT_MAX - 4u);
unsigned long long u2 = to_value<unsigned long long>(string_ref<>("-1"));
assert(u2 == ~0ULL);
unsigned u3 = to_value<unsigned>(string_ref<>("0"));
assert(u3 == 0u);
unsigned u4 = to_value<unsigned>(string_ref<>("42"));
assert(u4 == 42u);
// Plain "+" sign still works on the signed-stripping path.
int i1 = to_value<int>(string_ref<>("+7"));
assert(i1 == 7);
int i2 = to_value<int>(string_ref<>("-7"));
assert(i2 == -7);
}
return 0;
}