// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ios/chrome/tools/strings/grit_header_parsing.h"
#include <string>
#include <string_view>
#include <vector>
#include "base/containers/contains.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
namespace {
bool FillResourcesFromGritHeader(const base::FilePath& header,
ResourceMap& resource_map) {
std::string content;
if (!base::ReadFileToString(header, &content)) {
const base::File::Error error = base::File::GetLastFileError();
fprintf(stderr, "ERROR: error loading header %s: %s\n",
header.value().c_str(), base::File::ErrorToString(error).c_str());
return false;
}
std::vector<std::string_view> lines = base::SplitStringPiece(
content, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
for (std::string_view line : lines) {
if (!base::StartsWith(line, "#define "))
continue;
std::vector<std::string_view> items = base::SplitStringPiece(
line, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
if (items.size() != 3) {
fprintf(stderr, "ERROR: header %s contains invalid entry: %s\n",
header.value().c_str(), std::string(line).c_str());
return false;
}
const std::string_view key = items[1];
if (base::Contains(resource_map, key)) {
fprintf(stderr, "ERROR: entry duplicated in parsed headers: %s\n",
std::string(key).c_str());
return false;
}
int value = 0;
const std::string_view val = items[2];
if (!base::StringToInt(val, &value)) {
fprintf(stderr, "ERROR: header %s contains invalid entry: %s\n",
header.value().c_str(), std::string(line).c_str());
return false;
}
resource_map.emplace(key, value);
}
return true;
}
} // namespace
std::optional<ResourceMap> LoadResourcesFromGritHeaders(
const std::vector<base::FilePath>& headers) {
ResourceMap resource_map;
for (const base::FilePath& header : headers) {
if (!FillResourcesFromGritHeader(header, resource_map)) {
return std::nullopt;
}
}
return resource_map;
}