Compare commits
3
Commits
be77dffa01
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
795655edda | ||
|
|
c84fd4a614 | ||
|
|
43cfb349e9 |
@@ -283,6 +283,7 @@ class cli_device
|
||||
//! Clears the incoming data buffer
|
||||
void clear () noexcept {
|
||||
rx_q.clear();
|
||||
streams_.store(size_t(0), std::memory_order_release);
|
||||
}
|
||||
|
||||
//! \return Returns the size of the incoming data buffer
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
/*!
|
||||
* \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_ */
|
||||
@@ -50,7 +50,7 @@ namespace tbx {
|
||||
*
|
||||
* Requirements:
|
||||
* - size_t write_impl(const Char_t* buffer, size_t size) : Return the number of \c Char_t written
|
||||
* - size_t write_(const Char_t ch) : Return the number of \c Char_t written (normally one).
|
||||
* - size_t write_impl(const Char_t ch) : Return the number of \c Char_t written (normally one).
|
||||
*
|
||||
* \tparam Impl_t The derived type
|
||||
* \tparam Char_t The char type to use
|
||||
|
||||
Reference in New Issue
Block a user