blob: 31a02310af86b7cd2df0eaa79bb323857c7edb6e [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "tz_ids.h"
#include <iostream>
#include <set>
#include <string>
#include <vector>
#include "common.h"
#include "src/lib/fxl/command_line.h"
#include "src/lib/fxl/strings/join_strings.h"
#include "src/lib/fxl/strings/split_string.h"
#include "third_party/icu/source/common/unicode/strenum.h"
#include "third_party/icu/source/common/unicode/utypes.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
namespace icu_data_extractor {
namespace {
constexpr const char kName[] = "tz-ids";
constexpr const char kArgFixedOrder[] = "fixed-order";
constexpr const char kArgDelimiter[] = "delimiter";
constexpr const char kDefaultDelimiter[] = "\n";
std::vector<std::string> GetFixedOrderIds(const fxl::CommandLine& sub_command_line) {
if (sub_command_line.HasOption(kArgFixedOrder)) {
std::string items_str;
sub_command_line.GetOptionValue(kArgFixedOrder, &items_str);
return fxl::SplitStringCopy(items_str, ",", fxl::WhiteSpaceHandling::kTrimWhitespace,
fxl::SplitResult::kSplitWantNonEmpty);
}
return std::vector<std::string>{};
}
} // namespace
std::string_view TzIds::Name() const { return kName; }
int TzIds::Execute(const fxl::CommandLine& command_line,
const fxl::CommandLine& sub_command_line) const {
const auto output_path = GetOutputPath(sub_command_line);
const auto fixed_order_ids = GetFixedOrderIds(sub_command_line);
std::set<std::string> fixed_set(fixed_order_ids.begin(), fixed_order_ids.end());
UErrorCode status = UErrorCode::U_ZERO_ERROR;
auto ids = std::unique_ptr<icu::StringEnumeration>(icu::TimeZone::createEnumeration());
auto count = ids->count(status);
if (U_FAILURE(status)) {
std::cerr << "Error: " << u_errorName(status) << std::endl;
return -1;
}
std::vector<std::string> reordered_ids;
reordered_ids.reserve(count);
reordered_ids.insert(reordered_ids.end(), fixed_order_ids.begin(), fixed_order_ids.end());
// `id` is owned by the enumeration, `ids`
for (const char* id = nullptr; (id = ids->next(nullptr, status)) != nullptr;) {
const std::string id_str(id);
if (fixed_set.erase(id_str) == 0) {
reordered_ids.push_back(id_str);
}
}
if (!fixed_set.empty()) {
std::cerr << "Fixed order IDs not found in ICU data: ";
for (const auto& id : fixed_set) {
std::cerr << id << " ";
}
std::cerr << std::endl;
return -1;
}
const std::string delimiter =
sub_command_line.GetOptionValueWithDefault(kArgDelimiter, kDefaultDelimiter);
const auto output = fxl::JoinStrings(reordered_ids, delimiter);
return WriteToOutputFileOrStdOut(sub_command_line, output);
}
void TzIds::PrintDocs(std::ostream& os) const {
os << " " << kName << "\n --" << kArgOutputPath
<< "=FILE\t\t\tPath to output file (if omitted, STDOUT)"
<< "\n --" << kArgFixedOrder << "=ID1,ID2,...\t\tList of time zone IDs to put at the top"
<< "\n --" << kArgDelimiter
<< "=DELIMITER\t\tOptional delimiter to insert between IDs (default: \"\\n\")"
<< "\n\n Extract a list of time zone IDs";
}
} // namespace icu_data_extractor