Skip to content
Snippets Groups Projects
Commit f95f4d50 authored by Sergey Yakubov's avatar Sergey Yakubov
Browse files

finished config files for c++ code

parent 950e8d25
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,8 @@
#include <string>
#include <memory>
#include <vector>
#include <string>
#include "common/error.h"
......@@ -14,10 +16,16 @@ class JsonParser {
public:
JsonParser(const std::string& json, bool read_from_file);
~JsonParser();
JsonParser(JsonParser&& other);
Error GetUInt64(const std::string& name, uint64_t* val) const noexcept;
Error GetString(const std::string& name, std::string* val) const noexcept;
Error GetArrayUInt64(const std::string& name, std::vector<uint64_t>* val) const noexcept;
Error GetArrayString(const std::string& name, std::vector<std::string>* val) const noexcept;
JsonParser Embedded(const std::string& name) const noexcept;
private:
std::unique_ptr<RapidJson> rapid_json_;
JsonParser(RapidJson* rapid_json_);
};
}
......
......@@ -11,6 +11,16 @@ JsonParser::~JsonParser() {
JsonParser::JsonParser(const std::string& json, bool read_from_file) : rapid_json_{new RapidJson(json, read_from_file)} {
}
Error JsonParser::GetArrayUInt64(const std::string& name, std::vector<uint64_t>* val) const noexcept {
return rapid_json_->GetArrayUInt64(name, val);
}
Error JsonParser::GetArrayString(const std::string& name, std::vector<std::string>* val) const noexcept {
return rapid_json_->GetArrayString(name, val);
}
Error JsonParser::GetUInt64(const std::string& name, uint64_t* val) const noexcept {
return rapid_json_->GetUInt64(name, val);
}
......@@ -19,6 +29,18 @@ Error JsonParser::GetString(const std::string& name, std::string* val) const noe
return rapid_json_->GetString(name, val);
}
JsonParser JsonParser::Embedded(const std::string& name) const noexcept {
RapidJson* rapid_json = new RapidJson(*rapid_json_.get(), name);
return JsonParser(rapid_json);
}
JsonParser::JsonParser(RapidJson* json) : rapid_json_{json} {
}
JsonParser::JsonParser(JsonParser&& other) {
rapid_json_ = std::move(other.rapid_json_);
}
}
......
#include "rapid_json.h"
#include "rapid_json.h"
using namespace rapidjson;
......@@ -11,6 +12,10 @@ RapidJson::RapidJson(const std::string& json, bool read_from_file): io__{new Sys
}
Error RapidJson::LazyInitialize()const noexcept {
if (embedded_error_) {
return TextError(embedded_error_->Explain());
}
if (initialized_)
return nullptr;
......@@ -27,19 +32,26 @@ Error RapidJson::LazyInitialize()const noexcept {
return TextError("Cannot parse document");
}
return nullptr;
object_ = doc_.GetObject();
return nullptr;
}
hidra2::Error CheckValueType(const std::string& name, ValueType type, const Value& val) {
bool res = false;
switch (type) {
case ValueType::kObject:
res = val.IsObject();
break;
case ValueType::kString:
res = val.IsString();
break;
case ValueType::kUint64:
res = val.IsInt64();
break;
case ValueType::kArray:
res = val.IsArray();
break;
}
if (!res) {
return TextError("wrong type: " + name);
......@@ -54,8 +66,8 @@ hidra2::Error RapidJson::GetValue(const std::string& name, ValueType type, Value
return err;
}
auto iterator = doc_.FindMember(name.c_str());
if (iterator == doc_.MemberEnd()) {
auto iterator = object_.FindMember(name.c_str());
if (iterator == object_.MemberEnd()) {
return TextError("cannot find: " + name);
}
......@@ -63,7 +75,6 @@ hidra2::Error RapidJson::GetValue(const std::string& name, ValueType type, Value
return CheckValueType(name, type, *val);
}
Error RapidJson::GetUInt64(const std::string& name, uint64_t* val) const noexcept {
Value json_val;
if (Error err = GetValue(name, ValueType::kUint64, &json_val)) {
......@@ -73,9 +84,6 @@ Error RapidJson::GetUInt64(const std::string& name, uint64_t* val) const noexcep
return nullptr;
}
Error RapidJson::GetString(const std::string& name, std::string* val) const noexcept {
Value json_val;
if (Error err = GetValue(name, ValueType::kString, &json_val)) {
......@@ -86,4 +94,47 @@ Error RapidJson::GetString(const std::string& name, std::string* val) const noex
}
Error RapidJson::GetArrayUInt64(const std::string& name, std::vector<uint64_t>* val) const noexcept {
Value json_val;
if (Error err = GetValue(name, ValueType::kArray, &json_val)) {
return err;
}
for (auto& v : json_val.GetArray()) {
if (!v.IsInt64()) {
return TextError("wrong type of array element: " + name);
}
val->push_back(v.GetInt());
}
return nullptr;
}
Error RapidJson::GetArrayString(const std::string& name, std::vector<std::string>* val) const noexcept {
Value json_val;
if (Error err = GetValue(name, ValueType::kArray, &json_val)) {
return err;
}
for (auto& v : json_val.GetArray()) {
if (!v.IsString()) {
return TextError("wrong type of array element: " + name);
}
val->push_back(v.GetString());
}
return nullptr;
}
RapidJson::RapidJson(const RapidJson& parent, const std::string& subname) {
auto err = parent.GetValue(subname, ValueType::kObject, &object_);
if (err) {
embedded_error_ = std::move(err);
return;
}
initialized_ = true;
}
}
\ No newline at end of file
......@@ -10,21 +10,29 @@ namespace hidra2 {
enum class ValueType {
kUint64,
kString
kString,
kObject,
kArray
};
class RapidJson {
public:
RapidJson(const std::string& json, bool read_from_file);
RapidJson(const RapidJson& parent, const std::string& subname);
Error GetUInt64(const std::string& name, uint64_t* val) const noexcept;
Error GetString(const std::string& name, std::string* val) const noexcept;
Error GetArrayUInt64(const std::string& name, std::vector<uint64_t>* val) const noexcept;
Error GetArrayString(const std::string& name, std::vector<std::string>* val) const noexcept;
std::unique_ptr<IO> io__;
private:
mutable rapidjson::Document doc_;
mutable rapidjson::Value object_;
std::string json_;
bool read_from_file_;
mutable bool initialized_ = false;
Error LazyInitialize() const noexcept;
Error embedded_error_ = nullptr;
hidra2::Error GetValue(const std::string& name, ValueType type, rapidjson::Value* val)const noexcept;
};
......
......@@ -18,6 +18,7 @@ using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SetArgPointee;
using ::testing::HasSubstr;
using ::testing::ElementsAre;
using hidra2::JsonParser;
using hidra2::RapidJson;
......@@ -27,7 +28,7 @@ using hidra2::IO;
namespace {
TEST(ParseString, CorrectConvertToJson) {
TEST(ParseString, SimpleConvertToJson) {
std::string json = R"({"_id":2,"foo":"foo","bar":1})";
JsonParser parser{json, false};
......@@ -48,6 +49,67 @@ TEST(ParseString, CorrectConvertToJson) {
}
TEST(ParseString, EmbeddedConvertToJson) {
std::string json = R"({"id":{"test":2}})";
JsonParser parser{json, false};
uint64_t id;
auto err1 = parser.Embedded("id").GetUInt64("test", &id);
ASSERT_THAT(err1, Eq(nullptr));
ASSERT_THAT(id, Eq(2));
}
TEST(ParseString, DoubleEmbeddedConvertToJson) {
std::string json = R"({"id":{"test":{"test2":2}}})";
JsonParser parser{json, false};
uint64_t id;
auto err1 = parser.Embedded("id").Embedded("test").GetUInt64("test2", &id);
ASSERT_THAT(err1, Eq(nullptr));
ASSERT_THAT(id, Eq(2));
}
TEST(ParseString, ErrorOnWrongEmbeddedKey) {
std::string json = R"({"id1":{"test":2}})";
JsonParser parser{json, false};
uint64_t id;
auto err = parser.Embedded("id").GetUInt64("test", &id);
ASSERT_THAT(err, Ne(nullptr));
ASSERT_THAT(err->Explain(), ::testing::HasSubstr("cannot find"));
}
TEST(ParseString, ErrorOnWrongEmbeddedSubKey) {
std::string json = R"({"id1":{"test1":2}})";
JsonParser parser{json, false};
uint64_t id;
auto err = parser.Embedded("id").GetUInt64("test", &id);
ASSERT_THAT(err, Ne(nullptr));
ASSERT_THAT(err->Explain(), ::testing::HasSubstr("cannot find"));
}
TEST(ParseString, ErrorOnWrongKey) {
std::string json = R"({"_id":"2"})";
JsonParser parser{json, false};
uint64_t id;
auto err = parser.GetUInt64("_id1", &id);
ASSERT_THAT(err, Ne(nullptr));
ASSERT_THAT(err->Explain(), ::testing::HasSubstr("cannot find"));
}
TEST(ParseString, ErrorOnWrongType) {
std::string json = R"({"_id":"2"})";
......@@ -75,6 +137,46 @@ TEST(ParseString, ErrorOnWrongDocument) {
}
TEST(ParseString, IntArrayConvertToJson) {
std::string json = R"({"array":[1,2,3]})";
JsonParser parser{json, false};
std::vector<uint64_t> vec;
auto err = parser.GetArrayUInt64("array", &vec);
ASSERT_THAT(err, Eq(nullptr));
ASSERT_THAT(vec, ElementsAre(1, 2, 3));
}
TEST(ParseString, IntArrayErrorConvertToJson) {
std::string json = R"({"array":[1,2,"3"]})";
JsonParser parser{json, false};
std::vector<uint64_t> vec;
auto err = parser.GetArrayUInt64("array", &vec);
ASSERT_THAT(err, Ne(nullptr));
ASSERT_THAT(err->Explain(), HasSubstr("type"));
}
TEST(ParseString, StringArrayConvertToJson) {
std::string json = R"({"array":["s1","s2","s3"]})";
JsonParser parser{json, false};
std::vector<std::string> vec;
auto err = parser.GetArrayString("array", &vec);
ASSERT_THAT(err, Eq(nullptr));
ASSERT_THAT(vec, ElementsAre("s1", "s2", "s3"));
}
class ParseFileTests : public Test {
public:
RapidJson parser{"filename", true};
......
......@@ -4,6 +4,8 @@ find_package(Threads)
add_subdirectory(common/cpp)
add_subdirectory(system_io)
add_subdirectory(json_parser)
if(BUILD_MONGODB_CLIENTLIB)
add_subdirectory(mongo_db)
endif()
......
add_subdirectory(parse_config_file)
set(TARGET_NAME parse_config_file)
set(SOURCE_FILES parse_config_file.cpp)
################################
# Executable and link
################################
add_executable(${TARGET_NAME} ${SOURCE_FILES})
target_link_libraries(${TARGET_NAME} test_common hidra2-worker)
target_include_directories(${TARGET_NAME} PUBLIC ${HIDRA2_CXX_COMMON_INCLUDE_DIR})
################################
# Testing
################################
add_integration_test(${TARGET_NAME} parseOK "${CMAKE_CURRENT_SOURCE_DIR}/config.json OK")
add_integration_test(${TARGET_NAME} parseFails "${CMAKE_CURRENT_SOURCE_DIR}/config_bad.json FAIL")
{
"server":"some_string",
"port": 10,
"//": "This is a way to make comments",
"some_array":[1,2,3],
"//": "Another comment",
"some_string_array":["s1","s2","s3"],
"embedded_stuff":
{
"some_string":"embedded_string",
"some_int": 20
}
}
\ No newline at end of file
{
"server":"some_string",
"port": 10,
"some_array":1,
"some_string_array":["s1","s2","s3"],
"embedded_stuff":
{
"some_string":"embedded_string",
"some_int": 20
}
}
\ No newline at end of file
#include "json_parser/json_parser.h"
#include <iostream>
#include <string>
#include <vector>
#include "testing.h"
using hidra2::M_AssertEq;
using namespace hidra2;
struct Settings {
uint64_t port;
std::string server;
std::vector<uint64_t> intarray;
std::vector<std::string> stringarray;
std::string embedded_string;
uint64_t some_int;
};
void AssertSettings(const Settings& settings) {
M_AssertEq(10, settings.port);
M_AssertEq(3, settings.intarray.size());
M_AssertEq(1, settings.intarray[0]);
M_AssertEq(2, settings.intarray[1]);
M_AssertEq(3, settings.intarray[2]);
M_AssertEq(3, settings.stringarray.size());
M_AssertEq("s1", settings.stringarray[0]);
M_AssertEq("s2", settings.stringarray[1]);
M_AssertEq("s3", settings.stringarray[2]);
M_AssertEq("some_string", settings.server);
M_AssertEq("embedded_string", settings.embedded_string);
M_AssertEq(20, settings.some_int);
}
Settings Parse(const std::string& fname, Error* err) {
hidra2::JsonParser parser(fname, true);
Settings settings;
(*err = parser.GetUInt64("port", &settings.port)) ||
(*err = parser.GetArrayString("some_string_array", &settings.stringarray)) ||
(*err = parser.GetArrayUInt64("some_array", &settings.intarray)) ||
(*err = parser.Embedded("embedded_stuff").GetString("some_string", &settings.embedded_string)) ||
(*err = parser.Embedded("embedded_stuff").GetUInt64("some_int", &settings.some_int)) ||
(*err = parser.GetString("server", &settings.server)
);
return settings;
}
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cout << "Wrong number of arguments" << std::endl;
exit(EXIT_FAILURE);
}
auto fname = std::string{argv[1]};
auto res = std::string{argv[2]};
Error err;
auto settings = Parse(fname, &err);
if (err) {
return ! (res == "FAIL");
} else {
AssertSettings(settings);
return ! (res == "OK");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment