#include "SaveMap.h" #include #include #include "Game/ObjectFactory.h" extern std::vector factories; extern std::vector base_object_factories; ISave* SaveMap::MakeObjectByName(const std::string& name) { for (ObjectFactory& factory : base_object_factories) { if (name == factory.name) { return factory.factory(); } } for (ObjectFactory& factory : factories) { if (name == factory.name) { return factory.factory(); } } throw std::runtime_error("Object not found"); } SaveMap::SaveMap(const char* class_name) : class_name(class_name) { if (class_name == nullptr) throw std::runtime_error("Can't create save map with null name"); } SaveMap::SaveMap(const std::string& json_data) { for (size_t i = 0; i < json_data.length() - 1;) { size_t key_begin = i = json_data.find_first_of('\"', i) + 1; size_t key_end = i = json_data.find_first_of('\"', i); std::string name = json_data.substr(key_begin, key_end - key_begin); if (class_name.empty()) { size_t begin = json_data.find(':', i) + 2; size_t end = i = json_data.find('\"', begin); i++; class_name = json_data.substr(begin, end - begin); continue; } if (name[0] == 'i') { size_t begin = json_data.find(':', i) + 2; size_t end = i = json_data.find_first_of(",}", i); i++; std::string value = json_data.substr(begin, end - begin - 1); save_long[name.c_str() + 1] = std::stoll(value); } else if (name[0] == 'd') { size_t begin = json_data.find(':', i) + 2; size_t end = i = json_data.find_first_of(",}", i); i++; std::string value = json_data.substr(begin, end - begin - 1); save_double[name.c_str() + 1] = std::stod(value); } else if (name[0] == 's') { size_t begin = json_data.find(':', i) + 2; size_t end = i = json_data.find('\"', begin); i++; std::string value; if (begin != end) value = json_data.substr(begin, end - begin); else value = ""; save_string[name.c_str() + 1] = value; } else if (name[0] == 'o') { size_t begin = i = json_data.find('{', i); int open = 1, close = 0; while (close < open) { i++; if (json_data[i] == '{') open++; else if (json_data[i] == '}') close++; } size_t end = i; i++; std::string object_json = json_data.substr(begin, end - begin + 1); begin = object_json.find(':') + 2; end = object_json.find('\"', begin); std::string object_name = object_json.substr(begin, end - begin); ISave* object_ptr = MakeObjectByName(object_name); object_ptr->load(std::make_shared(object_json)); save_objects[name.c_str() + 1] = object_ptr; } else if (name[0] == 'v') { std::string key = name.substr(2, name.length() - 2); size_t begin_arr = i = json_data.find('[', i); int open = 1, close = 0; while (close < open) { i++; if (json_data[i] == '[') open++; else if (json_data[i] == ']') close++; } size_t end_arr = i; i++; std::string arr_data = json_data.substr(begin_arr, end_arr - begin_arr + 1); if (name[1] == 'i') { save_vector_integer[key] = std::vector(); if (arr_data.length() == 2) continue; std::vector& vector_integer = save_vector_integer[key]; size_t j = 1; while (j < arr_data.length()) { size_t end_val = arr_data.find_first_of(",]", j); vector_integer.push_back(std::stoll(arr_data.substr(j, end_val - j))); j = end_val + 1; } } else if (name[1] == 'd') { save_vector_double[key] = std::vector(); if (arr_data.length() == 2) continue; std::vector& vector_double = save_vector_double[key]; size_t j = 1; while (j < arr_data.length()) { size_t end_val = arr_data.find_first_of(",]", j); vector_double.push_back(std::stod(arr_data.substr(j, end_val - j))); j = end_val + 1; } } else if (name[1] == 's') { save_vector_strings[key] = std::vector(); if (arr_data.length() == 2) continue; std::vector& vector_strings = save_vector_strings[key]; size_t j = 0; while (j < arr_data.length()) { size_t begin = arr_data.find('\"', j) + 1; size_t end = j = arr_data.find('\"', begin); std::string value; if (begin != end) value = arr_data.substr(begin, end - begin); else value = ""; vector_strings.push_back(value); j += 3; } } else if (name[1] == 'o') { save_vector_objects[key] = std::vector(); if (arr_data.length() == 2) continue; std::vector& vector_object = save_vector_objects[key]; size_t j = 1; while (j < arr_data.length()) { size_t beg_val = j; open = 1; close = 0; while (close < open) { j++; if (arr_data[j] == '{') open++; else if (arr_data[j] == '}') close++; } size_t end_val = j; j++; std::string object_json = arr_data.substr(beg_val, end_val - beg_val + 1); size_t begin_name = object_json.find(':') + 2; size_t end_name = object_json.find('\"', begin_name); std::string object_name = object_json.substr(begin_name, end_name - begin_name); ISave* object_ptr = MakeObjectByName(object_name); object_ptr->load(std::make_shared(object_json)); vector_object.push_back(object_ptr); j = arr_data.find_first_of(",]", j) + 1; } } } else if (name[0] == 'l') { std::string key = name.substr(2, name.length() - 2); size_t begin_arr = i = json_data.find('[', i); int open = 1, close = 0; while (close < open) { i++; if (json_data[i] == '[') open++; else if (json_data[i] == ']') close++; } size_t end_arr = i; i++; std::string arr_data = json_data.substr(begin_arr, end_arr - begin_arr + 1); if (name[1] == 'i') { save_list_integer[key] = std::list(); if (arr_data.length() == 2) continue; std::list& list_integer = save_list_integer[key]; size_t j = 1; while (j < arr_data.length()) { size_t end_val = arr_data.find_first_of(",]", j); list_integer.push_back(std::stoll(arr_data.substr(j, end_val - j))); j = end_val + 1; } } else if (name[1] == 'd') { save_list_double[key] = std::list(); if (arr_data.length() == 2) continue; std::list& list_double = save_list_double[key]; size_t j = 1; while (j < arr_data.length()) { size_t end_val = arr_data.find_first_of(",]", j); list_double.push_back(std::stod(arr_data.substr(j, end_val - j))); j = end_val + 1; } } else if (name[1] == 's') { save_list_strings[key] = std::list(); if (arr_data.length() == 2) continue; std::list& list_strings = save_list_strings[key]; size_t j = 2; while (j < arr_data.length()) { size_t begin = j; size_t end = j = arr_data.find('\"', begin + 1); std::string value = arr_data.substr(begin, end - begin); list_strings.push_back(value); j += 3; } } else if (name[1] == 'o') { save_list_objects[key] = std::list(); if (arr_data.length() == 2) continue; std::list& list_object = save_list_objects[key]; size_t j = 1; while (j < arr_data.length()) { size_t beg_val = j; open = 1; close = 0; while (close < open) { j++; if (arr_data[j] == '{') open++; else if (arr_data[j] == '}') close++; } size_t end_val = j; j++; std::string object_json = arr_data.substr(beg_val, end_val - beg_val + 1); size_t begin_name = object_json.find(':') + 2; size_t end_name = object_json.find('\"', begin_name); std::string object_name = object_json.substr(begin_name, end_name - begin_name); ISave* object_ptr = MakeObjectByName(object_name); object_ptr->load(std::make_shared(object_json)); list_object.push_back(object_ptr); j = arr_data.find_first_of(",]", j) + 1; } } } else if (name == "Parent parameters") { size_t parent_begin = i = json_data.find('{', i); int open = 1, close = 0; while (close < open) { i++; if (json_data[i] == '{') open++; else if (json_data[i] == '}') close++; } size_t parent_end = i; i++; std::string str = json_data.substr(parent_begin, parent_end - parent_begin + 1); parent_ = std::make_shared(str); } } } SaveMap::SaveMap(SaveMap& save_map): class_name(save_map.class_name), parent_(save_map.parent_), save_long(save_map.save_long), save_double(save_map.save_double), save_string(save_map.save_string), save_objects(save_map.save_objects), save_vector_integer(save_map.save_vector_integer), save_vector_double(save_map.save_vector_double), save_vector_strings(save_map.save_vector_strings), save_vector_objects(save_map.save_vector_objects), save_list_integer(save_map.save_list_integer), save_list_double(save_map.save_list_double), save_list_strings(save_map.save_list_strings), save_list_objects(save_map.save_list_objects) { } SaveMap::SaveMap(SaveMap&& save_map) noexcept : class_name(std::move(save_map.class_name)), parent_(std::move(save_map.parent_)), save_long(std::move(save_map.save_long)), save_double(std::move(save_map.save_double)), save_string(std::move(save_map.save_string)), save_objects(std::move(save_map.save_objects)), save_vector_integer(std::move(save_map.save_vector_integer)), save_vector_double(std::move(save_map.save_vector_double)), save_vector_strings(std::move(save_map.save_vector_strings)), save_vector_objects(std::move(save_map.save_vector_objects)), save_list_integer(std::move(save_map.save_list_integer)), save_list_double(std::move(save_map.save_list_double)), save_list_strings(std::move(save_map.save_list_strings)), save_list_objects(std::move(save_map.save_list_objects)) { } std::shared_ptr SaveMap::SaveInteger(const char* name, int value) noexcept { save_long[name] = value; return std::shared_ptr(this); } std::shared_ptr SaveMap::SaveDouble(const char* name, double value) noexcept { save_double[name] = value; return std::shared_ptr(this); } std::shared_ptr SaveMap::SaveString(const char* name, const std::string& value) noexcept { save_string[name] = value; return std::shared_ptr(this); } std::shared_ptr SaveMap::SaveObject(const char* name, ISave* object) noexcept { save_objects[name] = object; return std::shared_ptr(this); } std::shared_ptr SaveMap::SaveVectorInteger(const char* name, std::vector&& value) noexcept { save_vector_integer[name] = std::move(value); return std::shared_ptr(this); } std::shared_ptr SaveMap::SaveVectorDouble(const char* name, std::vector&& value) noexcept { save_vector_double[name] = std::move(value); return std::shared_ptr(this); } std::shared_ptr SaveMap::SaveVectorStrings(const char* name, std::vector&& value) noexcept { save_vector_strings[name] = std::move(value); return std::shared_ptr(this); } std::shared_ptr SaveMap::SaveVectorObject(const char* name, std::vector&& value) noexcept { save_vector_objects[name] = std::move(value); return std::shared_ptr(this); } std::shared_ptr SaveMap::SaveListInteger(const char* name, std::list&& value) noexcept { save_list_integer[name] = std::move(value); return std::shared_ptr(this); } std::shared_ptr SaveMap::SaveListDouble(const char* name, std::list&& value) noexcept { save_list_double[name] = std::move(value); return std::shared_ptr(this); } std::shared_ptr SaveMap::SaveListStrings(const char* name, std::list&& value) noexcept { save_list_strings[name] = std::move(value); return std::shared_ptr(this); } std::shared_ptr SaveMap::SaveListObject(const char* name, std::list&& value) noexcept { save_list_objects[name] = std::move(value); return std::shared_ptr(this); } long long SaveMap::GetInteger(const char* name) { return save_long[name]; } double SaveMap::GetDouble(const char* name) { return save_double[name]; } const char* SaveMap::GetString(const char* name) { return save_string[name].c_str(); } ISave* SaveMap::GetObject(const char* name) { return save_objects[name]; } std::vector& SaveMap::GetVectorInteger(const char* name) { return save_vector_integer[name]; } std::vector& SaveMap::GetVectorDouble(const char* name) { return save_vector_double[name]; } std::vector SaveMap::GetVectorString(const char* name) { return save_vector_strings[name]; } std::vector& SaveMap::GetVectorObject(const char* name) { return save_vector_objects[name]; } std::list& SaveMap::GetListInteger(const char* name) { return save_list_integer[name]; } std::list& SaveMap::GetListDouble(const char* name) { return save_list_double[name]; } std::list& SaveMap::GetListString(const char* name) { return save_list_strings[name]; } std::list& SaveMap::GetListObject(const char* name) { return save_list_objects[name]; } std::string SaveMap::serialize() noexcept { std::string buffer = R"({"Class name":")" + class_name + '\"'; for (auto& [key, value] : save_long) buffer += ",\"i" + key + "\":" + std::to_string(value); for (auto& [key, value] : save_double) buffer += ",\"d" + key + "\":" + std::to_string(value); for (auto& [key, value] : save_string) buffer += ",\"s" + key + "\":\"" + value + '\"'; for (auto& [key, value] : save_objects) buffer += ",\"o" + key + "\":\"" + value->save()->serialize(); for (auto& [key, value] : save_vector_integer) { if (value.empty()) { buffer += ",\"vi" + key + "\":[]"; continue; } buffer += ",\"vi" + key + "\":["; for (auto& item : value) buffer += std::to_string(item) + ','; buffer.replace(buffer.length() - 1, buffer.length() - 1, "]"); } for (auto& [key, value] : save_vector_double) { if (value.empty()) { buffer += ",\"vd" + key + "\":[]"; continue; } buffer += ",\"vd" + key + "\":["; for (auto& item : value) buffer += std::to_string(item) + ','; buffer.replace(buffer.length() - 1, buffer.length() - 1, "]"); } for (auto& [key, value] : save_vector_objects) { if (value.empty()) { buffer += ",\"vo" + key + "\":[]"; continue; } buffer += ",\"vo" + key + "\":["; for (auto& item : value) buffer += item->save()->serialize() + ','; buffer.replace(buffer.length() - 1, buffer.length() - 1, "]"); } for (auto& [key, value] : save_vector_strings) { if (value.empty()) { buffer += ",\"vs" + key + "\":[]"; continue; } buffer += ",\"vs" + key + "\":["; for (auto& item : value) buffer += '\"' + item + "\","; buffer.replace(buffer.length() - 1, buffer.length() - 1, "]"); } for (auto& [key, value] : save_list_integer) { if (value.empty()) { buffer += ",\"li" + key + "\":[]"; continue; } buffer += ",\"li" + key + "\":["; for (auto& item : value) buffer += std::to_string(item) + ','; buffer.replace(buffer.length() - 1, buffer.length() - 1, "]"); } for (auto& [key, value] : save_list_double) { if (value.empty()) { buffer += ",\"ld" + key + "\":[]"; continue; } buffer += ",\"ld" + key + "\":["; for (auto& item : value) buffer += std::to_string(item) + ','; buffer.replace(buffer.length() - 1, buffer.length() - 1, "]"); } for (auto& [key, value] : save_list_objects) { if (value.empty()) { buffer += ",\"lo" + key + "\":[]"; continue; } buffer += ",\"lo" + key + "\":["; for (auto& item : value) buffer += item->save()->serialize() + ','; buffer.replace(buffer.length() - 1, buffer.length() - 1, "]"); } for (auto& [key, value] : save_list_strings) { if (value.empty()) { buffer += ",\"ls" + key + "\":[]"; continue; } buffer += ",\"ls" + key + "\":["; for (auto& item : value) buffer += '\"' + item + "\","; buffer.replace(buffer.length() - 1, buffer.length() - 1, "]"); } if (parent_ != nullptr) { buffer += ",\"Parent parameters\":" + parent_->serialize() + '}'; } else buffer += '}'; return buffer; } std::shared_ptr SaveMap::connect_to(const std::shared_ptr& parent) { if (this->parent_ != nullptr) throw std::runtime_error("Can't connect to second parent"); this->parent_ = parent; return std::shared_ptr(this); }