|
- /*!
- * \file files.h
- * \brief
- * File functionality header
- *
- * \copyright Copyright (C) 2021 Christos Choutouridis <christos@choutouridis.net>
- *
- * <dl class=\"section copyright\"><dt>License</dt><dd>
- * All Rights Reserved.
- *
- * NOTICE: All information contained herein is, and remains
- * the property of Christos Choutouridis. The intellectual
- * and technical concepts contained herein are proprietary to
- * Christos Choutouridis and are protected by copyright law.
- * Dissemination of this information or reproduction of this material
- * is strictly forbidden unless prior written permission is obtained
- * from Christos Choutouridis.
- * </dd></dl>
- */
- #ifndef JSON_H_
- #define JSON_H_
-
- #include <cstddef>
- #include <cstdlib>
- #include <cstring>
- #include <cctype>
- #include <type_traits>
- #include <string_view>
- #include <array>
-
- using size_t = std::size_t;
-
- struct jpair_t {
- std::string_view key;
- std::string_view value;
- };
-
- template<size_t N>
- struct json_dec_t {
-
- using string_view = std::string_view;
-
- json_dec_t(const char* buffer, size_t size) noexcept :
- buffer_(buffer, size), valid_(true) {
- enum state_t {
- ST=0, KEY, COLON, VALUE, SP
- } state = ST;
-
- size_t pairs =0;
- char* begin = nullptr;
- int s =0;
- bool str_value = false; // flag to indicate the value is string
-
- for (size_t i=0 ; i<size ; ++i) {
- switch (state) {
- case ST:
- if (std::isspace(buffer[i]))
- continue; // skip white space
- if (buffer[i] == '{')
- state = KEY;
- break;
-
- case KEY:
- if (pairs >= N) {
- valid_ = false;
- break;
- }
- if (std::isspace(buffer[i]))
- continue; // skip white space
- if (buffer[i] == '\"') {
- if (!begin)
- begin = (char*)&buffer[i+1];
- else {
- s = (char*)&buffer[i] - begin;
- if (s > 0)
- pairs_[pairs].key = std::string_view{begin, (size_t)s};
- else
- pairs_[pairs].key = std::string_view{};
- begin =nullptr;
- s =0;
- state = COLON;
- }
- }
- else if (buffer[i] == '}')
- return;
- break;
-
- case COLON:
- if (std::isspace(buffer[i]))
- continue; // skip white space
- if (buffer[i] == ':')
- state = VALUE;
- else {
- valid_ = false;
- return;
- }
- break;
-
- case VALUE:
- if (pairs >= N) {
- valid_ = false;
- break;
- }
- if (!begin && std::isspace(buffer[i])) // consume pre-spaces
- continue;
- else if (!begin && !std::isspace(buffer[i])) { // first character
- if (buffer[i] == '\"') {
- begin = (char*)&buffer[i+1];
- str_value = true;
- }
- else {
- begin = (char*)&buffer[i];
- str_value = false;
- }
- }
- else if (begin) {
- if (str_value && (buffer[i] == '\"')) {
- s = (char*)&buffer[i] - begin;
- if (s > 0)
- pairs_[pairs].value = std::string_view{begin, (size_t)s};
- else
- pairs_[pairs].value = std::string_view{};
- ++pairs;
- begin =nullptr;
- s =0;
- state = SP;
- }
- else if (!str_value && (std::isspace(buffer[i]) || buffer[i] == ',' || buffer[i] == '}')) {
- s = (char*)&buffer[i] - begin;
- if (s > 0)
- pairs_[pairs].value = std::string_view{begin, (size_t)s};
- else
- pairs_[pairs].value = std::string_view{};
- ++pairs;
- begin =nullptr;
- s =0;
- if (std::isspace(buffer[i]))
- state = SP;
- else if (buffer[i] == ',')
- state = KEY;
- else if (buffer[i] == '}')
- return;
- }
- }
- break;
-
- case SP:
- if (std::isspace(buffer[i]))
- continue; // skip white space
- else if (buffer[i] == ',')
- state = KEY;
- else if (buffer[i] == '}')
- return;
- else {
- valid_ = false;
- return;
- }
- break;
- }
- }
- }
- template<typename T>
- T get (const char* key) {
- T t{};
- for (auto& it : pairs_) {
- if (it.key.compare(key) == 0) {
- extract_(it.value, &t);
- break;
- }
- }
- return t;
- }
- bool is_valid() const { return valid_; }
-
- private:
- /*!
- * Convert the text pointed by \c str to a value and store it to
- * \c value. The type of conversion is deduced by the compiler
- * \tparam T The type of the value
- * \param str pointer to string with the value
- * \param value pointer to converted value
- */
- void extract_(std::string_view str, bool* value) {
- *value = (
- !std::strncmp(str.data(), "true", str.size()) ||
- !std::strncmp(str.data(), "True", str.size()) ||
- !std::strncmp(str.data(), "TRUE", str.size()) ||
- !std::strncmp(str.data(), "1", str.size())
- ) ? true : false;
- }
- void extract_(std::string_view str, int* value) {
- *value = std::atoi(str.data());
- }
- void extract_(std::string_view str, unsigned int* value) {
- *value = (unsigned int)std::atoi(str.data());
- }
- void extract_(std::string_view str, long* value) {
- *value = std::atol(str.data());
- }
- void extract_(std::string_view str, unsigned long* value) {
- *value = (unsigned long)std::atol(str.data());
- }
- void extract_(std::string_view str, double* value) {
- *value = std::atof(str.data());
- }
- void extract_(std::string_view str, char** value) {
- *value = (char*)str.data();
- }
- void extract_(std::string_view str, string_view* value) {
- *value = str;
- }
- //! Specialization (as overload function) to handle void* types
- void extract_ (const char* str, void* value) noexcept {
- (void)*str; (void)value;
- }
- private:
- std::string_view buffer_;
- std::array<jpair_t, N> pairs_;
- bool valid_;
- };
-
-
-
- #endif /* JSON_H_ */
|