DEV: a a json lazy decoder
This commit is contained in:
parent
43cfb349e9
commit
c84fd4a614
@ -37,6 +37,7 @@
|
||||
#include <cont/queue.h>
|
||||
#include <cont/equeue.h>
|
||||
|
||||
#include <utils/json.h>
|
||||
#include <utils/shared.h>
|
||||
#include <utils/print.h>
|
||||
#include <utils/timer_delay.h>
|
||||
|
202
include/utils/json.h
Normal file
202
include/utils/json.h
Normal file
@ -0,0 +1,202 @@
|
||||
/*!
|
||||
* \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;
|
||||
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]))
|
||||
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<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_ */
|
Loading…
x
Reference in New Issue
Block a user