Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Json #161

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

Json #161

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ find_package(SDL2 CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(cxxopts CONFIG REQUIRED)
find_package(ZLIB REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(RapidJSON REQUIRED)
find_package(FFMPEG COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE REQUIRED)
CPMAddPackage(NAME imgui VERSION 1.90 DOWNLOAD_ONLY YES
URL https://github.com/ocornut/imgui/archive/refs/tags/v1.90.zip
Expand Down
4 changes: 4 additions & 0 deletions src/Abyss/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ add_library(Abyss
Common/Animation.h
Common/CommandLineOpts.cpp Common/CommandLineOpts.h
Common/Configuration.cpp Common/Configuration.h
Common/JSON.cpp Common/JSON.h
Common/Logging.h
Common/MouseProvider.h
Common/MouseState.cpp Common/MouseState.h
Expand Down Expand Up @@ -81,9 +82,12 @@ target_link_libraries(Abyss
stormlib::stormlib
absl::flat_hash_map
absl::btree
nlohmann_json::nlohmann_json
${FFMPEG_LIBRARIES}
${OSX_VIDEOTOOLBOX}
${OSX_COREMEDIA}
${OSX_SECURITY}
PRIVATE
rapidjson
)

25 changes: 25 additions & 0 deletions src/Abyss/Common/JSON.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "JSON.h"
#include <format>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <rapidjson/istreamwrapper.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <stdexcept>

namespace Abyss::Common {

nlohmann::json parseJson(std::string_view json) {
rapidjson::Document d;
d.Parse<rapidjson::kParseCommentsFlag | rapidjson::kParseTrailingCommasFlag>(json.data(), json.length());
if (d.HasParseError()) {
throw std::runtime_error(
std::format("JSON parse error ({}) at offset {}", rapidjson::GetParseError_En(d.GetParseError()), d.GetErrorOffset()));

Check failure on line 17 in src/Abyss/Common/JSON.cpp

View workflow job for this annotation

GitHub Actions / MacOS

no member named 'format' in namespace 'std'
}
rapidjson::StringBuffer sb;
rapidjson::Writer writer(sb);
d.Accept(writer);
return nlohmann::json::parse(sb.GetString());
}

} // namespace Abyss::Common
11 changes: 11 additions & 0 deletions src/Abyss/Common/JSON.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include <nlohmann/json.hpp>
#include <string_view>

namespace Abyss::Common {

// Like normal nlohmann, but supports comments and trailing commas
nlohmann::json parseJson(std::string_view json);

} // namespace Abyss::Common
3 changes: 3 additions & 0 deletions src/OD2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ target_sources(OpenDiablo2
# Scenes
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Layouts/Layout.cpp Layouts/Layout.h
Layouts/Profile.cpp Layouts/Profile.h

# Main Menu
Scenes/MainMenu/MainMenu.cpp Scenes/MainMenu/MainMenu.h
Scenes/MainMenu/Logo.cpp Scenes/MainMenu/Logo.h
Expand Down
54 changes: 54 additions & 0 deletions src/OD2/Layouts/Layout.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "Layout.h"
#include "Abyss/Common/JSON.h"
#include "Abyss/Singletons.h"
#include <absl/container/flat_hash_map.h>
#include <absl/strings/str_cat.h>

namespace OD2::Layouts {

namespace {

void mergeFromParent(nlohmann::json &object, nlohmann::json &parent) {
if (parent.contains("fields")) {
nlohmann::json fields = std::move(parent["fields"]);
if (object.contains("fields")) {
fields.merge_patch(object["fields"]);
}
object["fields"] = std::move(fields);
}
if (object.contains("children") && parent.contains("children")) {
absl::flat_hash_map<std::string, nlohmann::json *> brothers;
for (auto &c : parent["children"]) {
if (c.contains("name")) {
brothers[c["name"].get<std::string_view>()] = &c;
}
}
for (auto &c : object["children"]) {
if (c.contains("name")) {
auto it = brothers.find(c["name"].get<std::string_view>());
if (it != brothers.end()) {
nlohmann::json &brother = *it->second;
mergeFromParent(c, brother);
}
}
}
}
}

nlohmann::json readMergedLayout(std::string_view name) {
nlohmann::json me = Abyss::Common::parseJson(Abyss::Singletons::getFileProvider().loadString(absl::StrCat("/data/global/ui/layouts/", name)));
if (me.contains("basedOn")) {
nlohmann::json parent = readMergedLayout(me["basedOn"].get<std::string_view>());
mergeFromParent(me, parent);
}
return me;
}

} // namespace

Layout::Layout(std::string_view name, const Profile &profile) {
_data = readMergedLayout(name);
profile.resolveReferences(_data);
}

} // namespace OD2::Layouts
17 changes: 17 additions & 0 deletions src/OD2/Layouts/Layout.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include "Profile.h"
#include <nlohmann/json.hpp>
#include <string_view>

namespace OD2::Layouts {

class Layout {
nlohmann::json _data;

public:
// Reads from /data/global/ui/layouts/{name} (name should include .json extension)
explicit Layout(std::string_view name, const Profile &profile);
};

} // namespace OD2::Layouts
46 changes: 46 additions & 0 deletions src/OD2/Layouts/Profile.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "Profile.h"
#include "Abyss/Common/JSON.h"
#include "Abyss/Singletons.h"
#include <format>
#include <nlohmann/json.hpp>
#include <stdexcept>

namespace OD2::Layouts {

namespace {

nlohmann::json readMergedProfile(std::string_view name) {
nlohmann::json me =
Abyss::Common::parseJson(Abyss::Singletons::getFileProvider().loadString(std::format("/data/global/ui/layouts/_profile{}.json", name)));
if (me.contains("basedOn")) {
nlohmann::json base = readMergedProfile(me["basedOn"].get<std::string_view>());
base.merge_patch(me);
return base;
}
return me;
}

bool resolveDataReferences(nlohmann::json &object, const nlohmann::json &profile) {
bool again = false;
for (auto &[k, v] : object.items()) {
if (v.is_structured()) {
again = resolveDataReferences(v, profile) || again;
} else if (v.is_string() && v.get<std::string_view>().starts_with('$')) {
v = profile.at(v.get<std::string_view>().substr(1));
again = true;
}
}
return again;
}

} // namespace

Profile::Profile(std::string_view name) {
_data = readMergedProfile(name);
while (resolveDataReferences(_data, _data)) {
}
}

void Profile::resolveReferences(nlohmann::json &object) const { resolveDataReferences(object, _data); }

} // namespace OD2::Layouts
17 changes: 17 additions & 0 deletions src/OD2/Layouts/Profile.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <nlohmann/json.hpp>
#include <string_view>

namespace OD2::Layouts {

class Profile {
nlohmann::json _data;

public:
// Reads from /data/global/ui/layouts/_profile{name}.json
explicit Profile(std::string_view name);
void resolveReferences(nlohmann::json &object) const;
};

} // namespace OD2::Layouts
4 changes: 3 additions & 1 deletion vcpkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "0.0.1",
"dependencies": [
"cxxopts",
{
{
"name": "sdl2",
"features": [
"alsa"
Expand All @@ -15,6 +15,8 @@
"name": "sdl2",
"platform": "!linux"
},
"nlohmann-json",
"rapidjson",
"spdlog",
"zlib",
{
Expand Down
Loading