22 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
28 #if GCC_VERSION >= 40900
39 ParserException::ParserException(
int lineno,
const std::string& msg) : std::runtime_error(
"line " + std::to_string(lineno) +
": " + msg) {}
41 std::string Parser::regexp_str =
"^([0-9]{12}([0-9][0-9])?),([0-9]+),([0-9]+),([+-]?[0-9.]*),([+-]?[0-9.]*),([^,\n\r]*),([^,\n\r]*[\r\n]*)$";
43 #if GCC_VERSION >= 40900
44 static std::regex regexp(Parser::regexp_str);
49 Regexp(
const std::string& re) {
50 if (
int i = regcomp(®, re.c_str(), REG_EXTENDED) != 0) {
52 regerror(i, ®, b,
sizeof(b));
53 std::runtime_error(
"Regex error: " + std::string(b));
66 RegexpMatch(
int nmatch) : nmatch(nmatch), regmatch(
new regmatch_t[nmatch]) {}
70 std::string str(
int i) {
72 throw std::out_of_range(
"out of range: " + std::to_string(i));
73 return val.substr(regmatch[i].rm_so, regmatch[i].rm_eo - regmatch[i].rm_so);
78 int r = regexec(&re.reg, s.c_str(), match.nmatch, match.regmatch, 0);
85 static Regexp regexp(Parser::regexp_str);
88 Parser::Parser(std::istream& in) : in(in), lineno(0) {}
93 return next(value, line);
103 if (line.size() == 0) {
119 #if GCC_VERSION >= 40900
124 if (not regex_match(line, match, regexp))
138 sscanf(match.str(1).c_str(),
"%04d%02d%02d%02d%02d%02d",
139 &value.year, &value.month, &value.mday,
140 &value.hour, &value.min, &value.sec);
141 value.station_id = strtoul(match.str(3).c_str(), NULL, 10);
142 value.variable_id = strtoul(match.str(4).c_str(), NULL, 10);
143 value.value1 = (match.str(5).empty() ? vm2::MISSING_DOUBLE : strtod(match.str(5).c_str(), NULL));
144 value.value2 = (match.str(6).empty() ? vm2::MISSING_DOUBLE : strtod(match.str(6).c_str(), NULL));
145 value.value3 = match.str(7);
146 value.flags = match.str(8);
152 out << std::setfill(
'0') << std::setw(4) << value.year
153 << std::setfill(
'0') << std::setw(2) << value.month
154 << std::setfill(
'0') << std::setw(2) << value.mday
155 << std::setfill(
'0') << std::setw(2) << value.hour
156 << std::setfill(
'0') << std::setw(2) << value.min
157 << std::setfill(
'0') << std::setw(2) << value.sec
163 << (value.value1 != vm2::MISSING_DOUBLE ? std::to_string(value.value1) :
"")
165 << (value.value2 != vm2::MISSING_DOUBLE ? std::to_string(value.value2) :
"")
167 << value.value3 <<
","
168 << value.flags << std::endl;
int lineno
Number of the last line parsed.
std::istream & in
Input stream.
static void serialize(std::ostream &out, const Value &value)
Serialize a value.
bool next(Value &value)
Read the next VM2 value.