-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgvc_map.hpp
More file actions
120 lines (101 loc) · 3.83 KB
/
gvc_map.hpp
File metadata and controls
120 lines (101 loc) · 3.83 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
/**
* camt parser - version 1.00
* --------------------------------------------------------
* Report bugs and download new versions at https://github.com/psynetic-software/camt-parser
*
* SPDX-FileCopyrightText: 2025 psynectic
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include <string>
#include <vector>
#include <unordered_map>
#include <tuple>
#include <sstream>
#include <algorithm>
#include <map>
namespace camt {
// ----------------------------- Embedded CSV -----------------------------
// Format:
// GVC;DC;Domain;Family;SubFamily;DomDesc;FamDesc;SubDesc;Comment
extern const char* kGvcCsvEmbedded;
inline std::string trim_copy(std::string_view sv) {
auto is_space = [](unsigned char c){ return std::isspace(c) != 0; };
size_t b = 0, e = sv.size();
while (b < e && is_space(static_cast<unsigned char>(sv[b]))) ++b;
while (e > b && is_space(static_cast<unsigned char>(sv[e-1]))) --e;
return std::string(sv.substr(b, e - b));
}
inline std::string upper_trim(std::string_view s) {
std::string r = trim_copy(s);
std::transform(r.begin(), r.end(), r.begin(),
[](unsigned char c){ return std::toupper(c); });
return r;
}
inline std::vector<std::string> split_semicolon(std::string_view line) {
std::vector<std::string> out;
size_t start = 0;
while (start <= line.size()) {
size_t pos = line.find(';', start);
if (pos == std::string_view::npos) {
out.emplace_back(trim_copy(line.substr(start)));
break;
}
out.emplace_back(trim_copy(line.substr(start, pos - start)));
start = pos + 1;
}
return out;
}
// ----------------------------- Minimal Map-Type ---------------------------
// Key = "PMNT;RCDT;VCOM;C" (Domain;Family;SubFamily;C|D)
// Val = "058" (three-digit GVC/ISO-Code)
using GvcKey = std::string;
using GvcMap = std::multimap<GvcKey, std::string>;
// Builds the map from the embedded CSV.
inline GvcMap build_gvc_map_from_embedded() {
GvcMap map;
std::istringstream iss(std::string{camt::kGvcCsvEmbedded});
std::string line;
int num_lines = 0;
// First line may be a header -> just read everything and filter
while (std::getline(iss, line)) {
auto cols = split_semicolon(line);
if (cols.size() < 5)
continue;
if (!cols[0].empty() && cols[0] == "GVC") continue; // Header
const std::string iso = trim_copy(cols[0]); // "058"
const char crFlag = cols[1].empty() ? '\0' : cols[1][0]; // 'C'/'D'
const std::string domain = upper_trim(cols[2]); // "PMNT"
const std::string family = upper_trim(cols[3]); // "RCDT"
const std::string variant = upper_trim(cols[4]); // "VCOM"
if (iso.empty() || (crFlag!='C' && crFlag!='D') ||
domain.empty() || family.empty() || variant.empty())
continue;
// Build key: "PMNT;RCDT;VCOM;C"
GvcKey key = domain + ";" + family + ";" + variant + ";" + std::string(1, crFlag);
map.insert({ key,iso }); // ISO/GVC Number
num_lines++;
}
return map;
}
// Singleton access (build once, then reuse)
inline const GvcMap& get_gvc_map() {
static GvcMap M = build_gvc_map_from_embedded();
return M;
}
// Lookup: build key from 3 codes + C/D
inline std::string lookup_gvc(const GvcMap& m,
std::string_view domain,
std::string_view family,
std::string_view variant,
char crFlag)
{
GvcKey key = upper_trim(domain) + ";" +
upper_trim(family) + ";" +
upper_trim(variant) + ";" +
std::string(1, crFlag);
if (auto it = m.find(key); it != m.end()) return it->second;
return {};
}
} // namespace camt