From c84fd4a614b2cb9390db7bca4ed742738299f264 Mon Sep 17 00:00:00 2001 From: Christos Choutouridis Date: Fri, 10 Dec 2021 17:20:16 +0200 Subject: [PATCH] DEV: a a json lazy decoder --- include/tbx.h | 1 + include/utils/json.h | 202 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 include/utils/json.h diff --git a/include/tbx.h b/include/tbx.h index 55c6df6..0095e7f 100644 --- a/include/tbx.h +++ b/include/tbx.h @@ -37,6 +37,7 @@ #include #include +#include #include #include #include diff --git a/include/utils/json.h b/include/utils/json.h new file mode 100644 index 0000000..fa82e48 --- /dev/null +++ b/include/utils/json.h @@ -0,0 +1,202 @@ +/*! + * \file files.h + * \brief + * File functionality header + * + * \copyright Copyright (C) 2021 Christos Choutouridis + * + *
License
+ * 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. + *
+ */ +#ifndef JSON_H_ +#define JSON_H_ + +#include +#include +#include +#include +#include +#include +#include + +using size_t = std::size_t; + +struct jpair_t { + std::string_view key; + std::string_view value; +}; + +template +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; + for (size_t i=0 ; i= 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])) + continue; + else if (!begin && !std::isspace(buffer[i])) + begin = (buffer[i] != '\"') ? (char*)&buffer[i] : (char*)&buffer[i+1]; + else if (begin && (std::isspace(buffer[i]) || buffer[i] == ',' || buffer[i] == '}')) { + s = (char*)&buffer[i] - begin; + s -= (buffer[i-1] == '\"') ? 1:0; + 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 + 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 pairs_; + bool valid_; +}; + + + +#endif /* JSON_H_ */