Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <map>
- #include <fstream>
- #include <cstring>
- #include <cmath>
- #include <cassert>
- // Add ifdef.
- #include <type_traits>
- class JSON
- {
- public:
- enum class Type : int
- {
- BOOL = 0,
- INT = 1,
- FLOAT = 2,
- STRING = 3,
- ARRAY = 4,
- OBJECT = 5,
- };
- void load(std::string_view filename);
- [[nodiscard]]
- bool save(std::string_view filename);
- template<class T>
- void setValue(T newValue);
- [[nodiscard]]
- Type getType() const;
- template<class T>
- [[nodiscard]]
- T getValue() const;
- [[nodiscard]]
- size_t getChildCount() const;
- [[nodiscard]]
- size_t getArraySize() const;
- JSON& operator[] (std::string_view nodeName);
- JSON& operator[] (size_t index);
- private:
- std::map<std::string, JSON> mapJson;
- std::vector<JSON> vectorJson;
- static int tabsCount;
- std::string value;
- Type type = Type::OBJECT;
- static void writeTabs(std::ofstream& file, size_t count);
- static void skipWhiteSpace(char*&file);
- void writeBool(std::ofstream& file);
- void writeInt(std::ofstream &file);
- void writeFloat(std::ofstream &file);
- void writeString(std::ofstream &file);
- void writeArray(std::ofstream &file);
- void writeObject(std::ofstream &file);
- void write(std::ofstream& file);
- [[nodiscard]]
- bool parseBool(char*& file);
- [[nodiscard]]
- bool parseNumber(char*&file);
- [[nodiscard]]
- bool parseString(char*& file);
- [[nodiscard]]
- bool parseArray(char*& file);
- [[nodiscard]]
- bool parseObject(char*& file);
- [[nodiscard]]
- bool parse(char*& file);
- };
- #define SJR_IMPLEMENTATION
- #ifdef SJR_IMPLEMENTATION
- // ==================== ====================
- // ====================PUBLIC====================
- // ==================== ====================
- void JSON::load(std::string_view filename)
- {
- std::ifstream file(filename.data());
- std::string str;
- if (!file.is_open())
- {
- std::cout << "Cannot load a file by path: " << filename << '\n';
- return;
- }
- file.seekg(0, std::ios::end);
- str.reserve(file.tellg());
- file.seekg(0, std::ios::beg);
- str.assign((std::istreambuf_iterator<char>(file)),{});
- char* fileData = str.data();
- if (!parse(fileData))
- {
- std::cout << "File doesn't correspong to json format file.";
- }
- }
- [[nodiscard]]
- bool JSON::save(std::string_view filename)
- {
- std::ofstream file(filename.data());
- if(!file.is_open())
- {
- return false;
- }
- write(file);
- file.close();
- return true;
- }
- template<class T>
- void JSON::setValue(T newValue)
- {
- if constexpr(std::is_same_v<T, bool>)
- {
- type = Type::BOOL;
- value = std::to_string(newValue);
- }
- if constexpr(std::is_same_v<T, int>)
- {
- type = Type::INT;
- value = std::to_string(newValue);
- }
- if constexpr(std::is_same_v<T, float>)
- {
- type = Type::FLOAT;
- value = std::to_string(newValue);
- }
- if constexpr (std::is_same_v<T, std::string>)
- {
- type = Type::STRING;
- value = newValue;
- }
- }
- [[nodiscard]]
- JSON::Type JSON::getType() const
- {
- return type;
- }
- template<class T>
- [[nodiscard]]
- T JSON::getValue() const
- {
- if constexpr(std::is_same_v<T, bool> || std::is_same_v<T, int>)
- {
- return std::stoi(value);
- }
- if constexpr(std::is_same_v<T, float>)
- {
- return std::stof(value);
- }
- if constexpr(std::is_same_v<T, std::string>)
- {
- return value;
- }
- }
- [[nodiscard]]
- size_t JSON::getChildCount() const
- {
- return mapJson.size();
- }
- [[nodiscard]]
- size_t JSON::getArraySize() const
- {
- return vectorJson.size();
- }
- [[nodiscard]]
- JSON& JSON::operator[] (std::string_view nodeName)
- {
- auto it = mapJson.find(nodeName.data());
- if (it != mapJson.end())
- {
- return it->second;
- }
- else
- {
- return mapJson[nodeName.data()];
- }
- }
- // Indexing starts with 0.
- //
- [[nodiscard]]
- JSON& JSON::operator[] (size_t index)
- {
- if (type != Type::ARRAY)
- {
- vectorJson.resize(index);
- type = Type::ARRAY;
- }
- if (index >= vectorJson.size())
- {
- vectorJson.resize(index + 1);
- }
- return vectorJson.at(index);
- }
- // ==================== ====================
- // ====================PRIVATE====================
- // ==================== ====================
- void JSON::writeTabs(std::ofstream& file, size_t count)
- {
- for (size_t i = 0u; i < count; ++i)
- {
- file << '\t';
- }
- }
- void JSON::skipWhiteSpace(char*&file)
- {
- while (isspace(*file))
- {
- ++file;
- }
- }
- void JSON::writeBool(std::ofstream& file)
- {
- file.setf(std::ios_base::boolalpha);
- file << static_cast<bool>(std::stoi(value));
- file.unsetf(std::ios::boolalpha);
- }
- void JSON::writeInt(std::ofstream &file)
- {
- file << std::stoi(value);
- }
- void JSON::writeFloat(std::ofstream &file)
- {
- file << std::stof(value);
- }
- void JSON::writeString(std::ofstream &file)
- {
- file << "\"" << value << "\"";
- }
- void JSON::writeArray(std::ofstream &file)
- {
- file << '[';
- for (auto it = vectorJson.begin(); it != vectorJson.end(); ++it)
- {
- it->write(file);
- if (it != (--vectorJson.end()))
- {
- file << ',' << ' ';
- }
- }
- file << ']';
- }
- void JSON::writeObject(std::ofstream &file)
- {
- if (!value.empty())
- {
- file << "\"" << value << "\"";
- file << ": ";
- }
- file << '{' << ' ';
- ++tabsCount;
- if (tabsCount == 1)
- {
- file << '\n' << '\t';
- }
- for (auto it = mapJson.begin(); it != mapJson.end(); ++it)
- {
- {
- file << "\"" << it->first << "\"";
- file << ": ";
- }
- it->second.write(file);
- if (it != (--mapJson.end()))
- {
- file << ", ";
- if(it->second.type == Type::ARRAY)
- {
- file << '\n';
- JSON::writeTabs(file, tabsCount);
- continue;
- }
- if(tabsCount == 1)
- {
- file << '\n';
- JSON::writeTabs(file, tabsCount);
- }
- }
- }
- --tabsCount;
- if(tabsCount == 0)
- {
- file << '\n';
- }
- file << '}';
- }
- void JSON::write(std::ofstream& file)
- {
- switch(type)
- {
- case Type::BOOL :
- writeBool(file);
- break;
- case Type::INT:
- writeInt(file);
- break;
- case Type::FLOAT :
- writeFloat(file);
- break;
- case Type::STRING:
- writeString(file);
- break;
- case Type::ARRAY:
- writeArray(file);
- break;
- case Type::OBJECT:
- writeObject(file);
- break;
- }
- }
- int JSON::tabsCount = 0;
- [[nodiscard]]
- bool JSON::parseBool(char*& file)
- {
- bool resultTrue = memcmp(file, "true", 4) == 0;
- bool resultFalse = memcmp(file, "false", 5) == 0;
- if (resultTrue || resultFalse)
- {
- value = std::to_string(resultTrue);
- file += resultTrue ? 4 : 5;
- type = Type::BOOL;
- return true;
- }
- return false;
- }
- [[nodiscard]]
- bool JSON::parseNumber(char*& file)
- {
- bool signNegative = *file == '-';
- bool signPositive = *file == '+';
- bool sign = signNegative | signPositive;
- int valueInt{0};
- float valueFloat{0.0f};
- if (sign || isdigit(*file))
- {
- if (sign)
- {
- ++file;
- }
- while (isdigit(*file))
- {
- valueInt *= 10;
- valueInt += *file - '0';
- ++file;
- }
- if (*file == '.')
- {
- ++file;
- type = Type::FLOAT;
- valueFloat = static_cast<float>(valueInt);
- while(isdigit(*file))
- {
- valueFloat *= 10;
- valueFloat += static_cast<float>(*file - '0');
- valueFloat /= 10;
- ++file;
- }
- value = std::to_string(valueFloat * (signNegative ? -1. : 1.));
- return true;
- }
- if (*file == 'e' || *file == 'E')
- {
- ++file;
- type = Type::FLOAT;
- valueFloat = static_cast<float>(valueInt);
- valueInt = 0;
- while (isdigit(*file))
- {
- valueInt *= 10;
- valueInt += *file - '0';
- }
- valueFloat *= static_cast<float>(pow(10, valueInt));
- value = std::to_string(valueFloat * (signNegative ? -1. : 1.));
- return true;
- }
- type = Type::INT;
- value = std::to_string(valueInt * (signNegative ? -1 : 1));
- return true;
- }
- return false;
- }
- [[nodiscard]]
- bool JSON::parseString(char*& file)
- {
- if (*file == '"')
- {
- ++file;
- type = Type::STRING;
- while (*file != '"')
- {
- JSON::skipWhiteSpace(file);
- if (*file == '"')
- {
- return true;
- }
- value += *file;
- ++file;
- }
- ++file;
- return true;
- }
- return false;
- }
- [[nodiscard]]
- bool JSON::parseArray(char*& file)
- {
- if (*file == '[')
- {
- ++file;
- type = Type::ARRAY;
- while (*file != ']')
- {
- JSON::skipWhiteSpace(file);
- if (*file == ']')
- {
- ++file;
- return true;
- }
- JSON newJSON;
- if (!newJSON.parse(file))
- {
- return false;
- }
- vectorJson.push_back(newJSON);
- JSON::skipWhiteSpace(file);
- if (*file == ']')
- {
- ++file;
- type = Type::ARRAY;
- return true;
- }
- if (*file != ',')
- {
- return false;
- }
- ++file;
- }
- ++file;
- return true;
- }
- return false;
- }
- [[nodiscard]]
- bool JSON::parseObject(char*& file)
- {
- if (*file == '{')
- {
- ++file;
- type = Type::OBJECT;
- while (*file != '}')
- {
- JSON::skipWhiteSpace(file);
- if (*file == '}')
- {
- ++file;
- return true;
- }
- if (*file == '"')
- {
- ++file;
- std::string nodeName{};
- while (*file != '"')
- {
- JSON::skipWhiteSpace(file);
- if (*file == '"')
- {
- break;
- }
- nodeName += *file;
- ++file;
- }
- if (*file != '"')
- {
- return true;
- }
- ++file;
- JSON::skipWhiteSpace(file);
- if (*file != ':')
- {
- return true;
- }
- ++file;
- JSON::skipWhiteSpace(file);
- JSON newNode;
- if (!newNode.parse(file)) {
- return true;
- }
- type = Type::OBJECT;
- mapJson[nodeName] = newNode;
- }
- JSON::skipWhiteSpace(file);
- if(*file == '}')
- {
- ++file;
- return true;
- }
- if(*file != ',')
- {
- return false;
- }
- ++file;
- }
- ++file;
- return true;
- }
- return false;
- }
- //
- //
- [[nodiscard]]
- bool JSON::parse(char*& file)
- {
- skipWhiteSpace(file);
- if (parseString(file))
- {
- return true;
- }
- if (parseBool(file))
- {
- return true;
- }
- if (parseNumber(file))
- {
- return true;
- }
- if (parseArray(file))
- {
- return true;
- }
- if (parseObject(file))
- {
- return true;
- }
- return false;
- }
- #endif
- int main()
- {
- JSON temp;
- temp.load("Smoke.par");
- std::cout << temp["Billboard"].getValue<std::string>() << '\n';
- //temp["z"][0]["ar"].setValue<bool>(true);
- temp.save("Wagh.txt");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement