blob: 0e9a0b373d6836130725daee0842f536da7f0c37 [file] [log] [blame]
// Copyright 2020 The Chromium 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 "tools/json_schema_compiler/manifest_parse_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
namespace json_schema_compiler {
namespace manifest_parse_util {
namespace {
// Alias for a pointer to a base::Value const function which converts the
// base::Value into type T. This is used by ParseHelper below.
template <typename T>
using ValueTypeConverter = T (base::Value::*)() const;
template <typename T, typename U>
bool ParseHelper(const base::DictionaryValue& dict,
base::StringPiece key,
base::Value::Type expected_type,
ValueTypeConverter<U> type_converter,
T* out,
std::u16string* error,
std::vector<base::StringPiece>* error_path_reversed) {
DCHECK(type_converter);
DCHECK(out);
const base::Value* value =
FindKeyOfType(dict, key, expected_type, error, error_path_reversed);
if (!value)
return false;
*out = (value->*type_converter)();
return true;
}
} // namespace
void PopulateInvalidEnumValueError(
base::StringPiece key,
const std::string& value,
std::u16string* error,
std::vector<base::StringPiece>* error_path_reversed) {
DCHECK(error);
DCHECK(error->empty());
DCHECK(error_path_reversed);
DCHECK(error_path_reversed->empty());
error_path_reversed->push_back(key);
*error = base::ASCIIToUTF16(
base::StringPrintf("Specified value '%s' is invalid.", value.c_str()));
}
std::u16string GetArrayParseError(size_t error_index,
const std::u16string& item_error) {
return base::ASCIIToUTF16(
base::StringPrintf("Parsing array failed at index %" PRIuS ": %s",
error_index, base::UTF16ToASCII(item_error).c_str()));
}
void PopulateFinalError(std::u16string* error,
std::vector<base::StringPiece>* error_path_reversed) {
DCHECK(error);
DCHECK(error_path_reversed);
DCHECK(!error->empty());
DCHECK(!error_path_reversed->empty());
// Reverse the path to ensure the constituent keys are in the correct order.
std::reverse(error_path_reversed->begin(), error_path_reversed->end());
*error = base::ASCIIToUTF16(
base::StringPrintf("Error at key '%s'. %s",
base::JoinString(*error_path_reversed, ".").c_str(),
base::UTF16ToASCII(*error).c_str()));
}
const base::Value* FindKeyOfType(
const base::DictionaryValue& dict,
base::StringPiece key,
base::Value::Type expected_type,
std::u16string* error,
std::vector<base::StringPiece>* error_path_reversed) {
DCHECK(error);
DCHECK(error->empty());
DCHECK(error_path_reversed);
DCHECK(error_path_reversed->empty());
const base::Value* value = dict.FindKey(key);
if (!value) {
error_path_reversed->push_back(key);
*error = u"Manifest key is required.";
return nullptr;
}
if (value->type() != expected_type) {
error_path_reversed->push_back(key);
*error = base::ASCIIToUTF16(
base::StringPrintf("Type is invalid. Expected %s, found %s.",
base::Value::GetTypeName(expected_type),
base::Value::GetTypeName(value->type())));
return nullptr;
}
return value;
}
bool ParseFromDictionary(const base::DictionaryValue& dict,
base::StringPiece key,
int* out,
std::u16string* error,
std::vector<base::StringPiece>* error_path_reversed) {
return ParseHelper(dict, key, base::Value::Type::INTEGER,
&base::Value::GetInt, out, error, error_path_reversed);
}
bool ParseFromDictionary(const base::DictionaryValue& dict,
base::StringPiece key,
bool* out,
std::u16string* error,
std::vector<base::StringPiece>* error_path_reversed) {
return ParseHelper(dict, key, base::Value::Type::BOOLEAN,
&base::Value::GetBool, out, error, error_path_reversed);
}
bool ParseFromDictionary(const base::DictionaryValue& dict,
base::StringPiece key,
double* out,
std::u16string* error,
std::vector<base::StringPiece>* error_path_reversed) {
return ParseHelper(dict, key, base::Value::Type::DOUBLE,
&base::Value::GetDouble, out, error, error_path_reversed);
}
bool ParseFromDictionary(const base::DictionaryValue& dict,
base::StringPiece key,
std::string* out,
std::u16string* error,
std::vector<base::StringPiece>* error_path_reversed) {
return ParseHelper(dict, key, base::Value::Type::STRING,
&base::Value::GetString, out, error, error_path_reversed);
}
} // namespace manifest_parse_util
} // namespace json_schema_compiler