Skip to content

Commit 9af6d05

Browse files
authored
#103 Refactored any converter so that anyConverters need not be visible. (#104)
1 parent 3b90169 commit 9af6d05

File tree

7 files changed

+88
-95
lines changed

7 files changed

+88
-95
lines changed

src/csv_file_scanner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ std::optional<std::vector<std::any>> CsvFileScanner::processNext()
151151
}
152152

153153
for (size_t i = 0; i < metadata_.size(); ++i) {
154-
const auto field = convertTo(anyConverters, metadata_[i].typeIndex, fields[i]);
154+
const auto field = convertTo(metadata_[i].typeIndex, fields[i]);
155155
if (!field.has_value()) {
156156
++errorLines_;
157157

src/to_any_converter.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,43 @@ namespace codein {
77

88
const std::any nullany;
99

10+
/**
11+
* @brief Make a type_index&converter to any pair to register the converter for a specific type.
12+
*
13+
* @tparam T The type of value which the string is converted into
14+
* @param f The converter function which convert string into a value of T
15+
* @return a pair of type_index & converter
16+
*/
17+
template <typename T>
18+
constexpr std::pair<
19+
const std::type_index,
20+
std::function<std::any(const std::string&)>
21+
>
22+
toAnyConverter(const std::function<T(const std::string&)> f)
23+
{
24+
return {
25+
std::type_index(typeid(T)),
26+
[g = f](const std::string& s) -> std::any
27+
{
28+
return g(s);
29+
}
30+
};
31+
}
32+
33+
/**
34+
* @brief Type alias for map between type index and string-to-value converter function.
35+
*/
36+
using AnyConverterMap = std::unordered_map<
37+
std::type_index,
38+
std::function<std::any(const std::string&)>
39+
>;
40+
41+
/**
42+
* @brief The hash table between type and string-to-value converter function.
43+
* Converter function's return type is std::any which can contain any value inside it.
44+
* FieldMetadataInfo provides type info with typeIndex and the type info can be used
45+
* to convert a string into a value of that type.
46+
*/
1047
AnyConverterMap anyConverters {
1148
toAnyConverter<int>([](const std::string& s) {
1249
return stoi(s);
@@ -25,6 +62,20 @@ AnyConverterMap anyConverters {
2562
}),
2663
};
2764

65+
std::any convertTo(const std::type_index& ti, const std::string& s) noexcept
66+
{
67+
try {
68+
if (const auto it = anyConverters.find(ti); it != anyConverters.cend()) {
69+
return it->second(s);
70+
}
71+
}
72+
catch (...) {
73+
// Absorb any exceptions and return null any value instead.
74+
}
75+
76+
return nullany;
77+
}
78+
2879
const std::unordered_map<std::string, std::type_index> typeMap {
2980
{"int", std::type_index(typeid(int))},
3081
{"bool", std::type_index(typeid(bool))},

src/to_any_converter.h

Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -10,73 +10,17 @@ namespace codein {
1010

1111
extern const std::any nullany;
1212

13-
/**
14-
* @brief Make a type_index&converter to any pair to register the converter for a specific type.
15-
*
16-
* @tparam T The type of value which the string is converted into
17-
* @param f The converter function which convert string into a value of T
18-
* @return a pair of type_index & converter
19-
*/
20-
template <typename T>
21-
constexpr std::pair<
22-
const std::type_index,
23-
std::function<std::any(const std::string&)>
24-
>
25-
toAnyConverter(const std::function<T(const std::string&)> f)
26-
{
27-
return {
28-
std::type_index(typeid(T)),
29-
[g = f](const std::string& s) -> std::any
30-
{
31-
return g(s);
32-
}
33-
};
34-
}
35-
36-
/**
37-
* @brief Type alias for map between type index and string-to-value converter function.
38-
*/
39-
using AnyConverterMap = std::unordered_map<
40-
std::type_index,
41-
std::function<std::any(const std::string&)>
42-
>;
43-
4413
/**
4514
* @brief Convert a string into ti type which is mapped to a certain value type
4615
* such as int/float/string.
4716
*
48-
* @param anyConverters Table for converter functions.
4917
* @param ti Type index
5018
* @param s String value
5119
* @return Value of type std::any. The type of return value cannot be known in advance.
5220
* So, the converted value is contained in any type though each converter
5321
* converts a string into a specific type according to ti.
5422
*/
55-
inline std::any convertTo(
56-
const AnyConverterMap& anyConverters,
57-
const std::type_index& ti,
58-
const std::string& s
59-
) noexcept
60-
{
61-
try {
62-
if (const auto it = anyConverters.find(ti); it != anyConverters.cend()) {
63-
return it->second(s);
64-
}
65-
}
66-
catch (...) {
67-
// Absorb any exceptions and return null any value instead.
68-
}
69-
70-
return nullany;
71-
}
72-
73-
/**
74-
* @brief The hash table between type and string-to-value converter function.
75-
* Converter function's return type is std::any which can contain any value inside it.
76-
* FieldMetadataInfo provides type info with typeIndex and the type info can be used
77-
* to convert a string into a value of that type.
78-
*/
79-
extern AnyConverterMap anyConverters;
23+
std::any convertTo(const std::type_index& ti, const std::string& s) noexcept;
8024

8125
std::type_index convertToTypeid(const std::string& typeName);
8226

test/any_converter_test.cpp

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,117 +9,117 @@ using namespace codein;
99

1010
TEST(AnyConverterTests, SuccessfulCases)
1111
{
12-
auto val = convertTo(anyConverters, tiInt, "1");
12+
auto val = convertTo(tiInt, "1");
1313
EXPECT_EQ(type_index(val.type()), tiInt);
1414
EXPECT_EQ(any_cast<int>(val), 1);
1515

16-
val = convertTo(anyConverters, tiInt, "-20");
16+
val = convertTo(tiInt, "-20");
1717
EXPECT_EQ(type_index(val.type()), tiInt);
1818
EXPECT_EQ(any_cast<signed int>(val), -20);
1919

20-
val = convertTo(anyConverters, tiInt, "1.1");
20+
val = convertTo(tiInt, "1.1");
2121
EXPECT_EQ(type_index(val.type()), tiInt);
2222
EXPECT_EQ(any_cast<int>(val), 1);
2323

24-
val = convertTo(anyConverters, tiInt, "7abc");
24+
val = convertTo(tiInt, "7abc");
2525
EXPECT_EQ(type_index(val.type()), tiInt);
2626
EXPECT_EQ(any_cast<int32_t>(val), 7);
2727

28-
val = convertTo(anyConverters, tiUint, "20");
28+
val = convertTo(tiUint, "20");
2929
EXPECT_EQ(type_index(val.type()), tiUint);
3030
EXPECT_EQ(any_cast<unsigned>(val), 20);
3131

32-
val = convertTo(anyConverters, tiUint, "20.14");
32+
val = convertTo(tiUint, "20.14");
3333
EXPECT_EQ(type_index(val.type()), tiUint);
3434
EXPECT_EQ(any_cast<unsigned>(val), 20);
3535

36-
val = convertTo(anyConverters, tiUint, "101.1.4");
36+
val = convertTo(tiUint, "101.1.4");
3737
EXPECT_EQ(type_index(val.type()), tiUint);
3838
EXPECT_EQ(any_cast<unsigned int>(val), 101);
3939

40-
val = convertTo(anyConverters, tiFloat, "1.1");
40+
val = convertTo(tiFloat, "1.1");
4141
EXPECT_EQ(type_index(val.type()), tiFloat);
4242
EXPECT_FLOAT_EQ(any_cast<float>(val), 1.1);
4343

44-
val = convertTo(anyConverters, tiFloat, "1.0E2");
44+
val = convertTo(tiFloat, "1.0E2");
4545
EXPECT_EQ(type_index(val.type()), tiFloat);
4646
EXPECT_FLOAT_EQ(any_cast<float>(val), 1.0E2);
4747

48-
val = convertTo(anyConverters, tiFloat, "12345");
48+
val = convertTo(tiFloat, "12345");
4949
EXPECT_EQ(type_index(val.type()), tiFloat);
5050
EXPECT_FLOAT_EQ(any_cast<float>(val), 12345.0);
5151

52-
val = convertTo(anyConverters, tiFloat, ".12345");
52+
val = convertTo(tiFloat, ".12345");
5353
EXPECT_EQ(type_index(val.type()), tiFloat);
5454
EXPECT_FLOAT_EQ(any_cast<float>(val), 0.12345);
5555

56-
val = convertTo(anyConverters, tiDouble, "0.00001");
56+
val = convertTo(tiDouble, "0.00001");
5757
EXPECT_EQ(type_index(val.type()), tiDouble);
5858
EXPECT_DOUBLE_EQ(any_cast<double>(val), 0.00001);
5959

60-
val = convertTo(anyConverters, tiDouble, "12345E-43");
60+
val = convertTo(tiDouble, "12345E-43");
6161
EXPECT_EQ(type_index(val.type()), tiDouble);
6262
EXPECT_DOUBLE_EQ(any_cast<double>(val), 12345E-43);
6363

64-
val = convertTo(anyConverters, tiDouble, ".12345");
64+
val = convertTo(tiDouble, ".12345");
6565
EXPECT_EQ(type_index(val.type()), tiDouble);
6666
EXPECT_DOUBLE_EQ(any_cast<double>(val), 0.12345);
6767

68-
val = convertTo(anyConverters, tiString, "1.1");
68+
val = convertTo(tiString, "1.1");
6969
EXPECT_EQ(type_index(val.type()), tiString);
7070
EXPECT_EQ(any_cast<string>(val), "1.1");
7171
}
7272

7373
TEST(AnyConverterTests, BoundaryValues)
7474
{
75-
auto val = convertTo(anyConverters, tiInt, to_string(INT32_MAX));
75+
auto val = convertTo(tiInt, to_string(INT32_MAX));
7676
EXPECT_EQ(type_index(val.type()), tiInt);
7777
EXPECT_EQ(any_cast<int>(val), INT32_MAX);
7878

79-
val = convertTo(anyConverters, tiInt, to_string(INT32_MIN));
79+
val = convertTo(tiInt, to_string(INT32_MIN));
8080
EXPECT_EQ(type_index(val.type()), tiInt);
8181
EXPECT_EQ(any_cast<int>(val), INT32_MIN);
8282

83-
val = convertTo(anyConverters, tiUint, to_string(UINT32_MAX));
83+
val = convertTo(tiUint, to_string(UINT32_MAX));
8484
EXPECT_EQ(type_index(val.type()), tiUint);
8585
EXPECT_EQ(any_cast<unsigned>(val), UINT32_MAX);
8686

87-
val = convertTo(anyConverters, tiFloat, to_string(FLT_MAX));
87+
val = convertTo(tiFloat, to_string(FLT_MAX));
8888
EXPECT_EQ(type_index(val.type()), tiFloat);
8989
EXPECT_FLOAT_EQ(any_cast<float>(val), FLT_MAX);
9090

9191
auto float_min = "1.1754944e-38";
92-
val = convertTo(anyConverters, tiFloat, float_min);
92+
val = convertTo(tiFloat, float_min);
9393
EXPECT_EQ(type_index(val.type()), tiFloat);
9494
EXPECT_FLOAT_EQ(any_cast<float>(val), FLT_MIN) << "val = " << any_cast<float>(val);
9595

96-
val = convertTo(anyConverters, tiDouble, to_string(DBL_MAX));
96+
val = convertTo(tiDouble, to_string(DBL_MAX));
9797
EXPECT_EQ(type_index(val.type()), tiDouble);
9898
EXPECT_DOUBLE_EQ(any_cast<double>(val), DBL_MAX);
9999

100100
auto double_min = "2.2250738585072014e-308";
101-
val = convertTo(anyConverters, tiDouble, double_min);
101+
val = convertTo(tiDouble, double_min);
102102
EXPECT_EQ(type_index(val.type()), tiDouble);
103103
EXPECT_DOUBLE_EQ(any_cast<double>(val), DBL_MIN) << "val = " << any_cast<double>(val);
104104
}
105105

106106
TEST(AnyConverterTests, FailureCases)
107107
{
108-
auto val = convertTo(anyConverters, tiInt, to_string(UINT32_MAX));
108+
auto val = convertTo(tiInt, to_string(UINT32_MAX));
109109
EXPECT_FALSE(val.has_value());
110110
EXPECT_THROW(any_cast<int>(val), bad_any_cast);
111111

112-
val = convertTo(anyConverters, tiUint, "abc");
112+
val = convertTo(tiUint, "abc");
113113
EXPECT_FALSE(val.has_value());
114114
EXPECT_THROW(any_cast<unsigned>(val), bad_any_cast);
115115

116116
/* TODO: implement this behavior
117-
val = convertTo(anyConverters, tiUint, "-1");
117+
val = convertTo(tiUint, "-1");
118118
EXPECT_FALSE(val.has_value());
119119
EXPECT_THROW(any_cast<unsigned>(val), bad_any_cast);
120120
*/
121121

122-
val = convertTo(anyConverters, type_index(typeid(long double)), "1");
122+
val = convertTo(type_index(typeid(long double)), "1");
123123
EXPECT_FALSE(val.has_value());
124124
EXPECT_THROW(any_cast<int>(val), bad_any_cast);
125125
}

test/csv_file_scanner_test.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,7 @@ TEST(CsvFileScannerTests, FileNameConstructorTest2)
330330
fields = parseLine(expectedLines[i]);
331331

332332
for (size_t k = 0; k < expectedMetadata1.size(); ++k) {
333-
expectedFields[i].emplace_back(convertTo(
334-
anyConverters, expectedMetadata1[k].typeIndex, fields[k]
335-
)
333+
expectedFields[i].emplace_back(convertTo(expectedMetadata1[k].typeIndex, fields[k])
336334
);
337335
}
338336
}

test/mock_scanner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class MockScanner : public codein::Iterator {
3838

3939
std::vector<std::any> r;
4040
for (size_t i = 0; i < metadata_.size(); ++i) {
41-
r.emplace_back(codein::convertTo(codein::anyConverters, metadata_[i].typeIndex, fields[i]));
41+
r.emplace_back(codein::convertTo(metadata_[i].typeIndex, fields[i]));
4242
}
4343

4444
return r;

test/projector_test.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ TEST_F(ProjectorTests, SanityTest)
4343
vector<string> fields = parseLine(lines[0]);
4444
std::vector<std::any> expected;
4545
for (size_t i = 0; i < metadata.size(); ++i) {
46-
expected.emplace_back(convertTo(anyConverters, metadata[i].typeIndex, fields[i]));
46+
expected.emplace_back(convertTo(metadata[i].typeIndex, fields[i]));
4747
}
4848

4949
auto scanner = makeIterator<CsvFileScanner>(metadataFileName, dataFileName);
@@ -89,9 +89,9 @@ TEST_F(ProjectorTests, SelectionTest)
8989

9090
auto fields = parseLine(lines[0]);
9191
std::vector<std::any> expected;
92-
expected.emplace_back(convertTo(anyConverters, metadata[4].typeIndex, fields[4]));
93-
expected.emplace_back(convertTo(anyConverters, metadata[2].typeIndex, fields[2]));
94-
expected.emplace_back(convertTo(anyConverters, metadata[0].typeIndex, fields[0]));
92+
expected.emplace_back(convertTo(metadata[4].typeIndex, fields[4]));
93+
expected.emplace_back(convertTo(metadata[2].typeIndex, fields[2]));
94+
expected.emplace_back(convertTo(metadata[0].typeIndex, fields[0]));
9595

9696
auto scanner = makeIterator<CsvFileScanner>(metadataFileName, dataFileName);
9797

@@ -149,9 +149,9 @@ TEST_F(ProjectorTests, ProjExprTest)
149149

150150
auto fields = parseLine(lines[0]);
151151
std::vector<std::any> expected;
152-
expected.emplace_back(convertTo(anyConverters, metadata[4].typeIndex, fields[4]) + any(" LA"s));
153-
expected.emplace_back(convertTo(anyConverters, metadata[2].typeIndex, fields[2]) == any(-3));
154-
expected.emplace_back(convertTo(anyConverters, metadata[0].typeIndex, fields[0]) * any(3.0));
152+
expected.emplace_back(convertTo(metadata[4].typeIndex, fields[4]) + any(" LA"s));
153+
expected.emplace_back(convertTo(metadata[2].typeIndex, fields[2]) == any(-3));
154+
expected.emplace_back(convertTo(metadata[0].typeIndex, fields[0]) * any(3.0));
155155

156156
auto scanner = makeIterator<CsvFileScanner>(metadataFileName, dataFileName);
157157

0 commit comments

Comments
 (0)