| 397 | } |
| 398 | |
| 399 | bool |
| 400 | Table::parse(TextView src) { |
| 401 | unsigned line_no = 0; |
| 402 | while (src) { |
| 403 | auto line = src.take_prefix_at('\n').ltrim_if(&isspace); |
| 404 | ++line_no; |
| 405 | // skip blank and comment lines. |
| 406 | if (line.empty() || '#' == *line) { |
| 407 | continue; |
| 408 | } |
| 409 | |
| 410 | auto range_token = line.take_prefix_at(','); |
| 411 | IPRange range{range_token}; |
| 412 | if (range.empty()) { |
| 413 | std::cout << W().print("{} is not a valid range specification.", range_token); |
| 414 | continue; // This is an error, real code should report it. |
| 415 | } |
| 416 | |
| 417 | auto span = _arena.alloc(_size).rebind<std::byte>(); // need this broken out. |
| 418 | Row row{span}; // store the original span to preserve it. |
| 419 | for (auto const &col : _columns) { |
| 420 | auto token = this->token(line); |
| 421 | if (col->needs_localized_token()) { |
| 422 | token = this->localize(token); |
| 423 | } |
| 424 | if (!col->parse(token, span.subspan(0, col->size()))) { |
| 425 | std::cout << W().print("Value \"{}\" at index {} on line {} is invalid.", token, col->idx(), line_no); |
| 426 | } |
| 427 | // drop reference to storage used by this column. |
| 428 | span.remove_prefix(col->size()); |
| 429 | } |
| 430 | _space.mark(range, std::move(row)); |
| 431 | } |
| 432 | return true; |
| 433 | } |
| 434 | |
| 435 | auto |
| 436 | Table::find(IPAddr const &addr) -> Row * { |
no test coverage detected