-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Simplified JSON Parser - Save/Load functions to send/receive settings to/from the hook DLL
- Loading branch information
Showing
6 changed files
with
374 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#pragma once | ||
#include "cfg/option.h" | ||
#include "emulator.h" | ||
#include "Vanguard/VanguardJsonParser.h" | ||
#include <string> | ||
#include <variant> | ||
#include <format> | ||
|
||
#define VAR_NAME(Variable) (#Variable) | ||
|
||
using SettingsTypes = std::variant<bool, int, float>; | ||
using SettingsArray = std::vector< std::pair<std::string, SettingsTypes>>; | ||
|
||
class VanguardSettings | ||
{ | ||
public: | ||
SettingsArray array; | ||
std::pair<std::string, bool> Vsync; | ||
std::pair<std::string, bool> FloatVMUs; | ||
std::pair<std::string, int> Sh4Clock; | ||
|
||
// save the current value of required settings | ||
void SaveSettings() | ||
{ | ||
save_setting<bool>(VAR_NAME(Vsync), Vsync, &config::VSync); | ||
save_setting<bool>(VAR_NAME(FloatVMUs), FloatVMUs, &config::FloatVMUs); | ||
save_setting<int>(VAR_NAME(Sh4Clock), Sh4Clock, &config::Sh4Clock); | ||
|
||
} | ||
|
||
// load the settings values sent from the dll hook into the emulator's settings | ||
void LoadSettings(JsonParser::JsonValue settings) | ||
{ | ||
load_setting<bool>(&config::VSync, (*settings.json)[VAR_NAME(Vsync)]); | ||
load_setting<bool>(&config::FloatVMUs, (*settings.json)[VAR_NAME(FloatVMUs)]); | ||
load_setting<int>(&config::Sh4Clock, (*settings.json)[VAR_NAME(Sh4Clock)]); | ||
|
||
::SaveSettings(); | ||
} | ||
|
||
// Visits the variant value in a pair, determines the correct data type and returns it as a string | ||
std::string to_string(SettingsTypes var) | ||
{ | ||
return std::visit([](auto arg) {return std::format("{}", arg); }, var); | ||
} | ||
|
||
private: | ||
// saves the name and value of the setting to a pair, then push it onto the array | ||
template<typename T> | ||
void save_setting(std::string name, std::pair<std::string, SettingsTypes> variable, config::Option<T>* setting) | ||
{ | ||
variable.first = name; | ||
variable.second = *setting; | ||
array.push_back(variable); | ||
} | ||
|
||
// loads the value of the parsed setting based on the requested data type | ||
template<typename T> | ||
void load_setting(config::Option<T>* setting, JsonParser::JsonValue value) | ||
{ | ||
if (typeid(T) == typeid(bool)) | ||
*setting = value.b; | ||
|
||
else if (typeid(T) == typeid(int)) | ||
*setting = value.i; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// // | ||
// pulled and modified from https://github.com/UponTheSky/ray-tracing-in-series/blob/json-parser-devto/ray_tracer/utils/json_parser.cpp // | ||
// // | ||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
|
||
#include "Vanguard/VanguardJsonParser.h" | ||
#include "Vanguard/VanguardHelpers.h" | ||
#include <sstream> | ||
#include <algorithm> | ||
|
||
using namespace JsonParser; | ||
|
||
JsonValue JsonParser::ParseJson(const BSTR& data) | ||
{ | ||
// 1. read the text data | ||
std::string text; | ||
ReadData(data, text); | ||
|
||
// 2. parse the text with the helper function and return | ||
text_it start = text.begin(); | ||
return ParseJsonHelper(text, start); | ||
} | ||
|
||
void JsonParser::ReadData(const BSTR& data, std::string& output) | ||
{ | ||
std::string line; | ||
|
||
std::string converted_data = BSTRToString(data); | ||
|
||
std::stringstream json_data; | ||
json_data << converted_data; | ||
|
||
while (std::getline(json_data, line)) | ||
{ | ||
output.append(line); | ||
} | ||
} | ||
|
||
|
||
JsonValue JsonParser::ParsePrimitive(const std::string& text, text_it start, text_it end) | ||
{ | ||
std::string substr = text.substr(start - text.begin(), end - start); | ||
|
||
// flycast stores "yes" and "no" instead of "true" and "false" for...some reason | ||
if (substr.find("yes") != std::string::npos) | ||
{ | ||
return {.b = true}; | ||
} | ||
else if (substr.find("no") != std::string::npos) | ||
{ | ||
return {.b = false}; | ||
} | ||
else if (substr.find(".") != std::string::npos) | ||
{ | ||
return {.d = std::stod(substr)}; | ||
} | ||
else | ||
{ | ||
return {.i = std::stoi(substr)}; | ||
} | ||
} | ||
|
||
std::pair<std::string, JsonValue> JsonParser::RetriveKeyValuePair(const std::string& text, | ||
text_it& it) | ||
{ | ||
if (it == text.end()) | ||
throw std::invalid_argument("string is empty"); | ||
|
||
// ignore white spaces & line breaks | ||
while (*it == ' ' || *it == '\n') | ||
{ | ||
it++; | ||
} | ||
|
||
text_it curr_it; | ||
std::string key; | ||
JsonValue value; | ||
// if hit a double quote for the first time, it is a key | ||
if (*it == '\"') | ||
{ | ||
curr_it = ++it; | ||
while (*it != '\"') | ||
{ | ||
it++; | ||
} | ||
|
||
key = text.substr(curr_it - text.begin(), it - curr_it); | ||
if (*(++it) == ':') | ||
it++; | ||
else | ||
throw std::invalid_argument("did not find ':' designating a value to the key"); | ||
it++; | ||
} | ||
|
||
// now we need to have its corresponding value | ||
while (*it == ' ' || *it == '\n') | ||
{ | ||
it++; | ||
} | ||
|
||
if (*it == '{') | ||
{ | ||
// another json format | ||
value = ParseJsonHelper(text, it); | ||
} | ||
else | ||
{ | ||
// primitive value(double or int) | ||
curr_it = it; | ||
while (*it != ',' && *it != '\n' && *it != '}') | ||
{ | ||
it++; | ||
} | ||
value = ParsePrimitive(text, curr_it, it); | ||
} | ||
|
||
// after parsing the value, check whether the current iterator points to a comma | ||
if (*it == ',') | ||
{ | ||
it++; | ||
} | ||
|
||
return std::make_pair(key, value); | ||
} | ||
|
||
JsonValue JsonParser::ParseJsonHelper(const std::string& text, text_it& it) | ||
{ | ||
if (*it != '{') // must start with the left curly bracket | ||
throw std::invalid_argument("string does not start with '{'"); | ||
it++; | ||
|
||
std::map<std::string, JsonValue>* json_map = new std::map<std::string, JsonValue>; | ||
|
||
do | ||
{ | ||
const auto [key, value] = RetriveKeyValuePair(text, it); | ||
(*json_map)[key] = value; | ||
|
||
while (*it == ' ' || *it == '\n') | ||
{ | ||
it++; | ||
} | ||
} while (*it != '}'); | ||
|
||
it++; // after '}' | ||
|
||
return {.json = json_map}; | ||
} |
Oops, something went wrong.