/*! * \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; bool str_value = false; // flag to indicate the value is string 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])) // 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 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_ */