| 412 | } |
| 413 | |
| 414 | Status TimezoneDatabase::LoadZoneAliases(istream &is, const char* path) { |
| 415 | string line, alias, value; |
| 416 | const string err_msg_path_part = (path == nullptr) ? "" : string(" in ") + path; |
| 417 | int i = 0; |
| 418 | |
| 419 | while (is.good() && !is.eof()) { |
| 420 | i++; |
| 421 | getline(is, line); |
| 422 | |
| 423 | // Strip off comments. |
| 424 | size_t comment = line.find('#'); |
| 425 | if (comment != string::npos) { |
| 426 | line.resize(comment); |
| 427 | } |
| 428 | trim(line); |
| 429 | if (line.empty()) continue; |
| 430 | |
| 431 | // Parse lines formatted as "alias = value". |
| 432 | size_t equal_pos = line.find('='); |
| 433 | if (equal_pos == string::npos) { |
| 434 | return Status(Substitute("Error in line $0$1. '=' is missing.", i, |
| 435 | err_msg_path_part)); |
| 436 | } |
| 437 | |
| 438 | // Check if alias name is present. |
| 439 | alias = line.substr(0, equal_pos); |
| 440 | trim(alias); |
| 441 | if (alias.empty()) { |
| 442 | return Status(Substitute("Error in line $0$1. Time-zone alias name is missing.", i, |
| 443 | err_msg_path_part)); |
| 444 | } |
| 445 | |
| 446 | // Check if alias is already in 'tz_name_map_'. |
| 447 | if (tz_name_map_.find(alias) != tz_name_map_.end()) { |
| 448 | LOG(WARNING) << "Skipping line " << i << err_msg_path_part |
| 449 | << ". Duplicate time-zone alias: " << alias; |
| 450 | continue; |
| 451 | } |
| 452 | |
| 453 | // Value is either a fix offset in seconds or a time-zone name. |
| 454 | value = line.substr(equal_pos + 1, string::npos); |
| 455 | trim(value); |
| 456 | if (value.empty()) { |
| 457 | return Status(Substitute("Error in line $0$1. Missing value.", i, |
| 458 | err_msg_path_part)); |
| 459 | } |
| 460 | |
| 461 | int64_t offset_sec; |
| 462 | if (IsTimezoneOffsetValid(value, &offset_sec)) { |
| 463 | // Add time-zone with a fix offset to the map. |
| 464 | shared_ptr<Timezone> tz = make_shared<Timezone>( |
| 465 | cctz::fixed_time_zone(cctz::sys_seconds(offset_sec))); |
| 466 | tz_name_map_[alias] = tz; |
| 467 | } else { |
| 468 | // Check if the value is in the map. |
| 469 | auto it_value = tz_name_map_.find(value); |
| 470 | if (it_value != tz_name_map_.end()) { |
| 471 | tz_name_map_[alias] = it_value->second; |