add nlohmann json to better support web service (#7325)

This commit is contained in:
Vincent Stumpf 2022-10-08 20:18:04 -07:00 committed by GitHub
parent 7d09041018
commit 6bb29c0743
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 24969 additions and 111 deletions

View File

@ -48,6 +48,7 @@ endmacro( CONFIGURE_WITH_LOCAL_OR_SYSTEM )
add_subdirectory( httplib )
add_subdirectory( json )
add_subdirectory( libconfig )
add_subdirectory( mysql )
add_subdirectory( pcre )

1
3rdparty/README.txt vendored
View File

@ -6,3 +6,4 @@ libconfig - library for processing structured configuration files (http://www.hy
mysql - library for MySQL Community Server (http://www.mysql.com)
pcre - library for Perl Compatible Regular Expressions (http://www.pcre.org)
zlib - library for DEFLATE lossless compression algorithm (http://www.zlib.net)
json - library for nlohmann json (https://github.com/nlohmann/json/tree/4b2c8ce6bcfe7f39f2bb9e680c1e7a4d67c2dd48)

7
3rdparty/json/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 2.8)
set (JSON_INCLUDE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}/include"
CACHE INTERNAL "json include dir" )
mark_as_advanced( JSON_INCLUDE_DIRS )

21
3rdparty/json/LICENSE.MIT vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013-2022 Niels Lohmann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

24641
3rdparty/json/include/nlohmann/json.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
#include <cstdint> // int64_t, uint64_t
#include <map> // map
#include <memory> // allocator
#include <string> // string
#include <vector> // vector
// #include <nlohmann/detail/abi_macros.hpp>
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
// This file contains all macro definitions affecting or depending on the ABI
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2
#warning "Already included a different version of the library!"
#endif
#endif
#endif
#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum)
#ifndef JSON_DIAGNOSTICS
#define JSON_DIAGNOSTICS 0
#endif
#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
#endif
#if JSON_DIAGNOSTICS
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
#else
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
#endif
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
#else
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
#endif
// Construct the namespace ABI tags component
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
#define NLOHMANN_JSON_ABI_TAGS \
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
// Construct the namespace version component
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
_v ## major ## _ ## minor ## _ ## patch
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
#define NLOHMANN_JSON_NAMESPACE_VERSION
#else
#define NLOHMANN_JSON_NAMESPACE_VERSION \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
NLOHMANN_JSON_VERSION_MINOR, \
NLOHMANN_JSON_VERSION_PATCH)
#endif
// Combine namespace components
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
#ifndef NLOHMANN_JSON_NAMESPACE
#define NLOHMANN_JSON_NAMESPACE \
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION)
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
namespace nlohmann \
{ \
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION) \
{
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_END
#define NLOHMANN_JSON_NAMESPACE_END \
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
} // namespace nlohmann
#endif
/*!
@brief namespace for Niels Lohmann
@see https://github.com/nlohmann
@since version 1.0.0
*/
NLOHMANN_JSON_NAMESPACE_BEGIN
/*!
@brief default JSONSerializer template argument
This serializer ignores the template arguments and uses ADL
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
for serialization.
*/
template<typename T = void, typename SFINAE = void>
struct adl_serializer;
/// a class to store JSON values
/// @sa https://json.nlohmann.me/api/basic_json/
template<template<typename U, typename V, typename... Args> class ObjectType =
std::map,
template<typename U, typename... Args> class ArrayType = std::vector,
class StringType = std::string, class BooleanType = bool,
class NumberIntegerType = std::int64_t,
class NumberUnsignedType = std::uint64_t,
class NumberFloatType = double,
template<typename U> class AllocatorType = std::allocator,
template<typename T, typename SFINAE = void> class JSONSerializer =
adl_serializer,
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
class CustomBaseClass = void>
class basic_json;
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
/// @sa https://json.nlohmann.me/api/json_pointer/
template<typename RefStringType>
class json_pointer;
/*!
@brief default specialization
@sa https://json.nlohmann.me/api/json/
*/
using json = basic_json<>;
/// @brief a minimal map-like container that preserves insertion order
/// @sa https://json.nlohmann.me/api/ordered_map/
template<class Key, class T, class IgnoredLess, class Allocator>
struct ordered_map;
/// @brief specialization that maintains the insertion order of object keys
/// @sa https://json.nlohmann.me/api/ordered_json/
using ordered_json = basic_json<nlohmann::ordered_map>;
NLOHMANN_JSON_NAMESPACE_END
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_

View File

@ -17,7 +17,7 @@ file(GLOB WEB_HEADERS ${WEB_SOURCE_DIR}/*.hpp)
file(GLOB WEB_SOURCES ${WEB_SOURCE_DIR}/*.cpp)
set( DEPENDENCIES common yaml-cpp httplib)
set( LIBRARIES ${GLOBAL_LIBRARIES})
set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${COMMON_BASE_INCLUDE_DIRS} ${HTTPLIB_INCLUDE_DIRS})
set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${COMMON_BASE_INCLUDE_DIRS} ${HTTPLIB_INCLUDE_DIRS} ${JSON_INCLUDE_DIRS})
set( DEFINITIONS "${GLOBAL_DEFINITIONS} ${COMMON_BASE_DEFINITIONS}" )
set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_HEADERS} ${WEB_HEADERS} ${WEB_SOURCES} )
source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_HEADERS} )

View File

@ -19,6 +19,9 @@ HTTPLIB_AR = ../../3rdparty/httplib/obj/httplib.a
HTTPLIB_H = $(shell find ../../3rdparty/httplib/ -type f -name "*.h")
HTTPLIB_INCLUDE = -I../../3rdparty/httplib
NLOHMANN_H = $(shell find ../../3rdparty/json/include/nlohmann/ -type f -name "*.hpp")
NLOHMANN_INCLUDE = -I../../3rdparty/json/include
WEB_OBJ = $(shell ls *.cpp | sed -e "s/\.cpp/\.o/g")
WEB_DIR_OBJ = $(WEB_OBJ:%=obj/%)
WEB_H = $(shell ls *.hpp)
@ -75,9 +78,9 @@ web-server: obj $(WEB_DIR_OBJ) $(COMMON_AR) $(LIBCONFIG_AR) $(RAPIDYAML_AR) $(HT
# web object files
obj/%.o: %.cpp $(WEB_H) $(COMMON_H) $(LIBCONFIG_H) $(HTTPLIB_H) $(RAPIDYAML_H)
obj/%.o: %.cpp $(WEB_H) $(COMMON_H) $(LIBCONFIG_H) $(HTTPLIB_H) $(RAPIDYAML_H) $(NLOHMANN_H)
@echo " CXX $<"
@@CXX@ @CXXFLAGS@ $(COMMON_INCLUDE) $(LIBCONFIG_INCLUDE) $(HTTPLIB_INCLUDE) $(RAPIDYAML_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
@@CXX@ @CXXFLAGS@ $(COMMON_INCLUDE) $(LIBCONFIG_INCLUDE) $(HTTPLIB_INCLUDE) $(RAPIDYAML_INCLUDE) $(NLOHMANN_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
# missing object files
$(COMMON_AR):

View File

@ -4,6 +4,7 @@
#include "charconfig_controller.hpp"
#include <string>
#include <nlohmann/json.hpp>
#include "../common/showmsg.hpp"
#include "../common/sql.hpp"
@ -23,26 +24,23 @@ HANDLER_FUNC(charconfig_save) {
auto account_id = std::stoi(req.get_file_value("AID").content);
auto char_id = std::stoi(req.get_file_value("GID").content);
auto world_name_str = req.get_file_value("WorldName").content;
auto world_name = world_name_str.c_str();
std::string data;
auto world_name = req.get_file_value("WorldName").content;
auto data = nlohmann::json::object();
if (req.has_file("data")) {
data = req.get_file_value("data").content;
addToJsonObject(data, "\"Type\": 1");
} else {
data = "{\"Type\": 1}";
data = nlohmann::json::parse(req.get_file_value("data").content);
}
SQLLock sl(WEB_SQL_LOCK);
sl.lock();
auto handle = sl.getHandle();
SqlStmt * stmt = SqlStmt_Malloc(handle);
if (SQL_SUCCESS != SqlStmt_Prepare(stmt,
"SELECT `account_id` FROM `%s` WHERE (`account_id` = ? AND `char_id` = ? AND `world_name` = ?) LIMIT 1",
"SELECT `data` FROM `%s` WHERE (`account_id` = ? AND `char_id` = ? AND `world_name` = ?) LIMIT 1",
char_configs_table)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, &account_id, sizeof(account_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_INT, &char_id, sizeof(char_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, (void *)world_name, strlen(world_name))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, (void *)world_name.c_str(), world_name.length())
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
) {
SqlStmt_ShowDebug(stmt);
@ -53,32 +51,10 @@ HANDLER_FUNC(charconfig_save) {
return;
}
if (SqlStmt_NumRows(stmt) <= 0) {
if (SQL_SUCCESS != SqlStmt_Prepare(stmt,
"INSERT INTO `%s` (`account_id`, `char_id`, `world_name`, `data`) VALUES (?, ?, ?, ?)",
char_configs_table)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, &account_id, sizeof(account_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_INT, &char_id, sizeof(char_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, (void *)world_name, strlen(world_name))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_STRING, (void *)data.c_str(), strlen(data.c_str()))
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
) {
SqlStmt_ShowDebug(stmt);
SqlStmt_Free(stmt);
sl.unlock();
res.status = HTTP_BAD_REQUEST;
res.set_content("Error", "text/plain");
return;
}
} else {
if (SQL_SUCCESS != SqlStmt_Prepare(stmt,
"UPDATE `%s` SET `data` = ? WHERE (`account_id` = ? AND `char_id` = ? AND `world_name` = ?)",
char_configs_table)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void *)data.c_str(), strlen(data.c_str()))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_INT, &account_id, sizeof(account_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_INT, &char_id, sizeof(char_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_STRING, (void *)world_name, strlen(world_name))
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
if (SqlStmt_NumRows(stmt) > 0) {
char databuf[SQL_BUFFER_SIZE];
if (SQL_SUCCESS != SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &databuf, sizeof(databuf), NULL, NULL)
|| SQL_SUCCESS != SqlStmt_NextRow(stmt)
) {
SqlStmt_ShowDebug(stmt);
SqlStmt_Free(stmt);
@ -87,11 +63,34 @@ HANDLER_FUNC(charconfig_save) {
res.set_content("Error", "text/plain");
return;
}
auto db_data = nlohmann::json::parse(databuf);
mergeData(db_data, data, false);
data = std::move(db_data);
}
auto data_str = data.dump();
if (SQL_SUCCESS != SqlStmt_Prepare(stmt,
"REPLACE INTO `%s` (`account_id`, `char_id`, `world_name`, `data`) VALUES (?, ?, ?, ?)",
char_configs_table)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, &account_id, sizeof(account_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_INT, &char_id, sizeof(char_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, (void *)world_name.c_str(), world_name.length())
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_STRING, (void *)data_str.c_str(), data_str.length())
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
) {
SqlStmt_ShowDebug(stmt);
SqlStmt_Free(stmt);
sl.unlock();
res.status = HTTP_BAD_REQUEST;
res.set_content("Error", "text/plain");
return;
}
SqlStmt_Free(stmt);
sl.unlock();
res.set_content(data, "application/json");
res.set_content(data_str, "application/json");
}
HANDLER_FUNC(charconfig_load) {
@ -158,5 +157,8 @@ HANDLER_FUNC(charconfig_load) {
sl.unlock();
databuf[sizeof(databuf) - 1] = 0;
res.set_content(databuf, "application/json");
auto response = nlohmann::json::parse(databuf);
response["Type"] = 1;
res.set_content(response.dump(), "application/json");
}

View File

@ -4,6 +4,7 @@
#include "merchantstore_controller.hpp"
#include <string>
#include <nlohmann/json.hpp>
#include "../common/showmsg.hpp"
#include "../common/sql.hpp"
@ -30,10 +31,8 @@ HANDLER_FUNC(merchantstore_save) {
if (req.has_file("data")) {
data = req.get_file_value("data").content;
addToJsonObject(data, "\"Type\": 1");
} else {
data = "{\"Type\": 1}";
}
SQLLock sl(WEB_SQL_LOCK);
sl.lock();
auto handle = sl.getHandle();
@ -165,5 +164,7 @@ HANDLER_FUNC(merchantstore_load) {
sl.unlock();
databuf[sizeof(databuf) - 1] = 0;
res.set_content(databuf, "application/json");
auto response = nlohmann::json::parse(databuf);
response["Type"] = 1;
res.set_content(response.dump(), "application/json");
}

View File

@ -4,6 +4,7 @@
#include "userconfig_controller.hpp"
#include <string>
#include <nlohmann/json.hpp>
#include "../common/showmsg.hpp"
#include "../common/sql.hpp"
@ -22,25 +23,22 @@ HANDLER_FUNC(userconfig_save) {
}
auto account_id = std::stoi(req.get_file_value("AID").content);
auto world_name_str = req.get_file_value("WorldName").content;
auto world_name = world_name_str.c_str();
std::string data;
auto world_name = req.get_file_value("WorldName").content;
auto data = nlohmann::json::object();
if (req.has_file("data")) {
data = req.get_file_value("data").content;
addToJsonObject(data, "\"Type\": 1");
} else {
data = "{\"Type\": 1}";
data = nlohmann::json::parse(req.get_file_value("data").content);
}
SQLLock sl(WEB_SQL_LOCK);
sl.lock();
auto handle = sl.getHandle();
SqlStmt * stmt = SqlStmt_Malloc(handle);
if (SQL_SUCCESS != SqlStmt_Prepare(stmt,
"SELECT `account_id` FROM `%s` WHERE (`account_id` = ? AND `world_name` = ?) LIMIT 1",
"SELECT `data` FROM `%s` WHERE (`account_id` = ? AND `world_name` = ?) LIMIT 1",
user_configs_table)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, &account_id, sizeof(account_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void *)world_name, strlen(world_name))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void *)world_name.c_str(), world_name.length())
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
) {
SqlStmt_ShowDebug(stmt);
@ -51,30 +49,10 @@ HANDLER_FUNC(userconfig_save) {
return;
}
if (SqlStmt_NumRows(stmt) <= 0) {
if (SQL_SUCCESS != SqlStmt_Prepare(stmt,
"INSERT INTO `%s` (`account_id`, `world_name`, `data`) VALUES (?, ?, ?)",
user_configs_table)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, &account_id, sizeof(account_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void *)world_name, strlen(world_name))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, (void *)data.c_str(), strlen(data.c_str()))
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
) {
SqlStmt_ShowDebug(stmt);
SqlStmt_Free(stmt);
sl.unlock();
res.status = HTTP_BAD_REQUEST;
res.set_content("Error", "text/plain");
return;
}
} else {
if (SQL_SUCCESS != SqlStmt_Prepare(stmt,
"UPDATE `%s` SET `data` = ? WHERE (`account_id` = ? AND `world_name` = ?)",
user_configs_table)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void *)data.c_str(), strlen(data.c_str()))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_INT, &account_id, sizeof(account_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, (void *)world_name, strlen(world_name))
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
if (SqlStmt_NumRows(stmt) > 0) {
char databuf[SQL_BUFFER_SIZE];
if (SQL_SUCCESS != SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &databuf, sizeof(databuf), NULL, NULL)
|| SQL_SUCCESS != SqlStmt_NextRow(stmt)
) {
SqlStmt_ShowDebug(stmt);
SqlStmt_Free(stmt);
@ -83,11 +61,34 @@ HANDLER_FUNC(userconfig_save) {
res.set_content("Error", "text/plain");
return;
}
auto db_data = nlohmann::json::parse(databuf);
mergeData(db_data, data, true);
data = std::move(db_data);
}
auto data_str = data.dump();
if (SQL_SUCCESS != SqlStmt_Prepare(stmt,
"REPLACE INTO `%s` (`account_id`, `world_name`, `data`) VALUES (?, ?, ?)",
user_configs_table)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, &account_id, sizeof(account_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void *)world_name.c_str(), world_name.length())
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, (void *)data_str.c_str(), data_str.length())
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
) {
SqlStmt_ShowDebug(stmt);
SqlStmt_Free(stmt);
sl.unlock();
res.status = HTTP_BAD_REQUEST;
res.set_content("Error", "text/plain");
return;
}
SqlStmt_Free(stmt);
sl.unlock();
res.set_content(data, "application/json");
res.set_content(data_str, "application/json");
}
HANDLER_FUNC(userconfig_load) {
@ -152,5 +153,6 @@ HANDLER_FUNC(userconfig_load) {
sl.unlock();
databuf[sizeof(databuf) - 1] = 0;
res.set_content(databuf, "application/json");
}
auto response = nlohmann::json::parse(databuf);
response["Type"] = 1;
res.set_content(response.dump(), "application/json");}

View File

@ -94,7 +94,7 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>$(DefineConstants);WIN32;FD_SETSIZE=4096;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;LIBCONFIG_STATIC;YY_USE_CONST;_DEBUG;_CONSOLE;_LIB;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\httplib\;$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\httplib\;$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;$(SolutionDir)\3rdparty\json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018;4200</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
@ -112,7 +112,7 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>$(DefineConstants);WIN32;FD_SETSIZE=4096;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;LIBCONFIG_STATIC;YY_USE_CONST;_DEBUG;_CONSOLE;_LIB;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\httplib\;$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\httplib\;$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;$(SolutionDir)\3rdparty\json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018</DisableSpecificWarnings>
</ClCompile>
<Link>
@ -131,7 +131,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>$(DefineConstants);WIN32;FD_SETSIZE=4096;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;LIBCONFIG_STATIC;YY_USE_CONST;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\httplib\;$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\httplib\;$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;$(SolutionDir)\3rdparty\json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018</DisableSpecificWarnings>
</ClCompile>
<Link>
@ -152,7 +152,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>$(DefineConstants);WIN32;FD_SETSIZE=4096;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;LIBCONFIG_STATIC;YY_USE_CONST;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\httplib\;$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\httplib\;$(SolutionDir)\3rdparty\rapidyaml\src;$(SolutionDir)\3rdparty\rapidyaml\ext\c4core\src;$(SolutionDir)\3rdparty\json\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018</DisableSpecificWarnings>
</ClCompile>
<Link>

View File

@ -6,36 +6,36 @@
#include <string>
#include <algorithm>
#include <iostream>
#include <nlohmann/json.hpp>
/**
* Appends to_append to the JSON object obj
* modifies the obj parameter
* Returns true on succes, false on failure
*
* Note: very hacky, if we ever add a json parser/emitter, replace this
* I just didn't want to add one just for this functionality
* Merge patch into orig recursively
* if merge_null is true, this operates like json::merge_patch
* if merge_null is false, then if patch has null, it does not override orig
* Returns true on success
*/
bool addToJsonObject(std::string& obj, const std::string& to_append) {
bool need_comma = false;
auto last_close_brace = std::find(obj.rbegin(), obj.rend(), '}');
if (last_close_brace == obj.rend()) {
return false;
bool mergeData(nlohmann::json &orig, const nlohmann::json &patch, bool merge_null) {
if (!patch.is_object()) {
// then it's a value
if ((patch.is_null() && merge_null) || (!patch.is_null())) {
orig = patch;
}
return true;
}
for (auto it = last_close_brace + 1; it != obj.rend(); ++it) {
if (*it == '}' || *it == '"' || *it == ':') {
// there was a value, we need to add a comma
need_comma = true;
break;
} else if (*it == '{') {
// there was no previous value, don't add comma
need_comma = false;
break;
if (!orig.is_object()) {
orig = nlohmann::json::object();
}
for (auto it = patch.begin(); it != patch.end(); ++it) {
if (it.value().is_null()) {
if (merge_null) {
orig.erase(it.key());
}
} else {
mergeData(orig[it.key()], it.value(), merge_null);
}
}
obj.erase(--(last_close_brace.base()));
if (need_comma) {
obj += ",";
}
obj += to_append + "}";
return true;
}

View File

@ -4,8 +4,10 @@
#ifndef WEB_UTILS_HPP
#define WEB_UTILS_HPP
#include <string>
bool addToJsonObject(std::string& obj, const std::string& to_append);
#include <string>
#include <nlohmann/json_fwd.hpp>
bool mergeData(nlohmann::json &orig, const nlohmann::json &patch, bool merge_null);
#endif