Browse Source

DEV: a a json lazy decoder

master
parent
commit
c84fd4a614
2 changed files with 203 additions and 0 deletions
  1. +1
    -0
      include/tbx.h
  2. +202
    -0
      include/utils/json.h

+ 1
- 0
include/tbx.h View File

@@ -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
- 0
include/utils/json.h View 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…
Cancel
Save