From 5c023df3527c35696caa11f599a8a1cc8cda75d9 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 24 Aug 2018 23:23:01 +0200 Subject: [PATCH] added new JsonBuffer class which will obsolete struct buffer --- common/include/villas/json_buffer.hpp | 58 +++++++++++ common/lib/CMakeLists.txt | 1 + common/lib/buffer.c | 1 - common/lib/json_buffer.cpp | 56 +++++++++++ common/tests/CMakeLists.txt | 1 + common/tests/json_buffer.cpp | 135 ++++++++++++++++++++++++++ 6 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 common/include/villas/json_buffer.hpp create mode 100644 common/lib/json_buffer.cpp create mode 100644 common/tests/json_buffer.cpp diff --git a/common/include/villas/json_buffer.hpp b/common/include/villas/json_buffer.hpp new file mode 100644 index 000000000..25cd1f150 --- /dev/null +++ b/common/include/villas/json_buffer.hpp @@ -0,0 +1,58 @@ +/** A simple buffer for encoding streamed JSON messages. + * + * @file + * @author Steffen Vogel + * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLAScommon + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#pragma once + +#include + +#include + +#include + +namespace villas { + +class Buffer : public std::vector { + +public: + void append(const char *data, size_t len) + { + insert(end(), data, data + len); + } + +}; + +class JsonBuffer : public Buffer +{ + +protected: + static int callback(const char *data, size_t len, void *ctx); + +public: + /** Encode JSON document /p j and append it to the buffer */ + int encode(json_t *j); + + /** Decode JSON document from the beginning of the buffer */ + json_t * decode(); +}; + +} // namespace villas diff --git a/common/lib/CMakeLists.txt b/common/lib/CMakeLists.txt index c87964d23..5a23fdc49 100644 --- a/common/lib/CMakeLists.txt +++ b/common/lib/CMakeLists.txt @@ -24,6 +24,7 @@ add_library(villas-common SHARED advio.c bitset.c buffer.c + json_buffer.cpp compat.c crypt.c hash_table.c diff --git a/common/lib/buffer.c b/common/lib/buffer.c index 2069971a5..842106135 100644 --- a/common/lib/buffer.c +++ b/common/lib/buffer.c @@ -1,6 +1,5 @@ /** A simple growing buffer. * - * @file * @author Steffen Vogel * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) diff --git a/common/lib/json_buffer.cpp b/common/lib/json_buffer.cpp new file mode 100644 index 000000000..74ce77341 --- /dev/null +++ b/common/lib/json_buffer.cpp @@ -0,0 +1,56 @@ +/** A simple buffer for encoding streamed JSON messages. + * + * @author Steffen Vogel + * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLAScommon + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include +#include + +using namespace villas; + +json_t * JsonBuffer::decode() +{ + json_t *j; + json_error_t err; + + j = json_loadb(data(), size(), JSON_DISABLE_EOF_CHECK, &err); + if (!j) + return nullptr; + + /* Remove decoded JSON document from beginning */ + erase(begin(), begin() + err.position); + + return j; +} + +int JsonBuffer::encode(json_t *j) +{ + return json_dump_callback(j, callback, this, 0); +} + +int JsonBuffer::callback(const char *data, size_t len, void *ctx) +{ + Buffer *b = static_cast(ctx); + + /* Append junk of JSON to buffer */ + b->insert(b->end(), &data[0], &data[len]); + + return 0; +} diff --git a/common/tests/CMakeLists.txt b/common/tests/CMakeLists.txt index da8f1fbaa..3b8e930ce 100644 --- a/common/tests/CMakeLists.txt +++ b/common/tests/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable(unit-tests-common logging.cpp advio.cpp + json_buffer.cpp bitset.cpp graph.cpp hash_table.cpp diff --git a/common/tests/json_buffer.cpp b/common/tests/json_buffer.cpp new file mode 100644 index 000000000..eeb602ee4 --- /dev/null +++ b/common/tests/json_buffer.cpp @@ -0,0 +1,135 @@ +/** Unit tests for buffer + * + * @author Steffen Vogel + * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLAScommon + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include +#include + +#include +#include + +#include + +using namespace villas; + +void init_logging(); + +using villas::Buffer; + +TestSuite(buffer, + .description = "Buffer datastructure", + .init = init_logging +); + +Test(json_buffer, decode) +{ + JsonBuffer buf; + json_t *j; + json_t *k; + + const char *e = "{\"id\": \"5a786626-fbc6-4c04-98c2-48027e68c2fa\"}"; + size_t len = strlen(e); + + buf.insert(buf.begin(), e, e+len); + + k = json_loads(e, 0, NULL); + cr_assert_not_null(k); + + j = buf.decode(); + cr_assert_not_null(j); + cr_assert(json_equal(j, k)); +} + +Test(json_buffer, encode) +{ + int ret; + JsonBuffer buf; + json_t *k; + + const char *e = "{\"id\": \"5a786626-fbc6-4c04-98c2-48027e68c2fa\"}"; + + k = json_loads(e, 0, NULL); + cr_assert_not_null(k); + + ret = buf.encode(k); + cr_assert_eq(ret, 0); + + char *f = buf.data(); + cr_assert_not_null(f); + + cr_assert_str_eq(e, f); + + json_decref(k); +} + +Test(json_buffer, encode_decode) +{ + int ret; + JsonBuffer buf; + json_t *k; + json_t *j; + + const char *e = "{\"id\": \"5a786626-fbc6-4c04-98c2-48027e68c2fa\"}"; + + k = json_loads(e, 0, NULL); + cr_assert_not_null(k); + + ret = buf.encode(k); + cr_assert_eq(ret, 0); + + j = buf.decode(); + cr_assert_not_null(j); + + cr_assert(json_equal(j, k)); + + json_decref(j); + json_decref(k); +} + +Test(json_buffer, multiple) +{ + int ret; + const int N = 100; + + JsonBuffer buf; + json_t *k[N]; + json_t *j[N]; + + std::srand(std::time(nullptr)); + + for (int i = 0; i < N; i++) { + k[i] = json_pack("{ s: i }", "id", std::rand()); + cr_assert_not_null(k[i]); + + ret = buf.encode(k[i]); + cr_assert_eq(ret, 0); + } + + for (int i = 0; i < N; i++) { + j[i] = buf.decode(); + cr_assert_not_null(j[i]); + + cr_assert(json_equal(k[i], j[i])); + + json_decref(k[i]); + json_decref(j[i]); + } +}