From bea30c3f8949ebd9fdf4a9bf0a987652889930f5 Mon Sep 17 00:00:00 2001 From: Juan Carrano Date: Wed, 19 Jun 2019 17:53:58 +0200 Subject: [PATCH] sys/ubjson: remove module. The ubjson module has a number of quality defects and is unsafe. Considering CBOR is popular, standarized and supported in RIOT and that the ubjson implementation is a home-grown one whose API will likely be unfamiliar to new users, I propose to delete it. This removal, of course, dows not have to be NOW. We can deprecate it for one or two releases before. What's wrong with this module? - Unsafe: the parsing is done recursively. This is embedded in the API, so it is not possible to fix it without changing the API. A document with too much nesting can cause a stack overflow. - Does not validate writing: it is possible to produce invalid output. From the docs: > The library won't complain if you write multiple values that are not > inside an array or object. The result will just not be properly serialized. - Poorly tested. As shown by #11702, #11703 the tests were not even detecting that a False was stored as True. - In line with the previous remark, see https://github.com/RIOT-OS/RIOT/blob/68dc5b0d6e0422df9c3653c2cb8021fc35974aae/tests/unittests/tests-ubjson/tests-ubjson.c#L66-L77 Why is the following code in the unit tests?? ```c irq_disable(); sched_set_status(data->main_thread, STATUS_PENDING); ``` - #2175 is still unfixed after 3.5 years. - Code quality. The code has multiline macros that assign variables and return. See https://github.com/RIOT-OS/RIOT/blob/c3325148755c64a56b256253151a485498bcbc9b/sys/ubjson/ubjson-write.c#L34-L41 Can we mark it as deprecated this release and sweep it in the following one? --- sys/include/ubjson.h | 594 ------------------ sys/ubjson/Makefile | 1 - sys/ubjson/ubjson-internal.h | 62 -- sys/ubjson/ubjson-read.c | 392 ------------ sys/ubjson/ubjson-write.c | 189 ------ tests/unittests/tests-ubjson/Makefile | 1 - tests/unittests/tests-ubjson/Makefile.include | 4 - .../tests-ubjson/test-ubjson-empty-array.c | 127 ---- .../tests-ubjson/test-ubjson-empty-object.c | 130 ---- tests/unittests/tests-ubjson/tests-ubjson.c | 116 ---- tests/unittests/tests-ubjson/tests-ubjson.h | 54 -- 11 files changed, 1670 deletions(-) delete mode 100644 sys/include/ubjson.h delete mode 100644 sys/ubjson/Makefile delete mode 100644 sys/ubjson/ubjson-internal.h delete mode 100644 sys/ubjson/ubjson-read.c delete mode 100644 sys/ubjson/ubjson-write.c delete mode 100644 tests/unittests/tests-ubjson/Makefile delete mode 100644 tests/unittests/tests-ubjson/Makefile.include delete mode 100644 tests/unittests/tests-ubjson/test-ubjson-empty-array.c delete mode 100644 tests/unittests/tests-ubjson/test-ubjson-empty-object.c delete mode 100644 tests/unittests/tests-ubjson/tests-ubjson.c delete mode 100644 tests/unittests/tests-ubjson/tests-ubjson.h diff --git a/sys/include/ubjson.h b/sys/include/ubjson.h deleted file mode 100644 index df6fb16fe3ba..000000000000 --- a/sys/include/ubjson.h +++ /dev/null @@ -1,594 +0,0 @@ -/* - * Copyright (C) 2014 René Kijewski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @defgroup sys_ubjson Universal Binary JSON library - * @ingroup sys_serialization - * @brief Provides a library to read and write UBJSON serialized data - * - * @deprecated This module is deprecated and will be removed in release 2020.01. - * @{ - * - * @file - * @brief Headers for the UBJSON module - * - * @author René Kijewski - * - * @deprecated This module is deprecated and will be removed in release 2020.01. - */ - -#ifndef UBJSON_H -#define UBJSON_H - -#include -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* *************************************************************************** - * READ FUNCTIONS / DEFINITIONS - *************************************************************************** */ - -/** - * @brief Status code of ubjson_read(), ubjson_read_array() and ubjson_read_object() callback - * - * When ubjson_read(), ubjson_read_array() and ubjson_read_object() iteratively invokes the gives callback function. - * The callback function then has to invoke another function such as ubjson_get_i32(), depending on the parameter `type`. - */ -typedef enum { - /** - * @brief There is no such value. - * - * Only used in the callback of ubjson_read() for parameter `type2`. - */ - UBJSON_ABSENT, - - /** - * @brief The next datum is a null value. - * - * As you might have already guessed: you cannot read a null value. - */ - UBJSON_TYPE_NULL, - - /** - * @brief The next datum is a no-op value. - * - * As you might have already guessed: you cannot read a no-op value. - */ - UBJSON_TYPE_NOOP, - - /** - * @brief The next datum is a boolean. - * - * The `content` is the boolean value. - * Use ubjson_get_bool() or use `content` verbatim. - */ - UBJSON_TYPE_BOOL, - - /** - * @brief The next datum is an integer that fits into an int32_t. - * - * Use ubjson_get_i32() to read the value. - * `content` is one of ::ubjson_int32_type_t. - */ - UBJSON_TYPE_INT32, - - /** - * @brief The next datum is an integer that fits into an int64_t. - * - * Use ubjson_get_i64() to read the value. - */ - UBJSON_TYPE_INT64, - - /** - * @brief The next datum is a 32 bit floating point value. - * - * Use ubjson_get_float() to read the value. - */ - UBJSON_TYPE_FLOAT, - - /** - * @brief The next datum is a 64 bit floating point value. - * - * Use ubjson_get_double() to read the value. - */ - UBJSON_TYPE_DOUBLE, - - /* NOTE: High-precision numbers are not implemented, yet. Implement if needed. */ - /* UBJSON_TYPE_HP_NUMBER, */ - - /** - * @brief The next datum is a string (blob). - * - * Use ubjson_get_string() to read the value. - * `content` is the length of the blob. - */ - UBJSON_TYPE_STRING, - - /** - * @brief The next datum is an array. - * - * Use ubjson_read_array() to read its contents. - */ - UBJSON_ENTER_ARRAY, - - /** - * @brief The next datum is an object. - * - * Use ubjson_read_object() to read its contents. - */ - UBJSON_ENTER_OBJECT, - - /** - * @brief The next datum is an array index. - * - * This value is emitted for every index in a call to ubjson_read_array(). - * - * `content1` is the array index. - * `type2` and `content2` describe the value of the index. - * - * Arrays can be nested. - */ - UBJSON_INDEX, - - /** - * @brief The next datum is an object key. - * - * This value is emitted for every index in a call to ubjson_read_object(). - * - * `content1` is the length of the key, invoke ubjson_get_string(). - * `type2` and `content2` describe the value. - * - * Objects can be nested. - */ - UBJSON_KEY, -} ubjson_type_t; - -/** - * @brief Length of the UBJSON_TYPE_INT32 datum. - */ -typedef enum { - UBJSON_INT32_INT8, /**< The stream contains an int8_t. */ - UBJSON_INT32_UINT8, /**< The stream contains an uint8_t. */ - UBJSON_INT32_INT16, /**< The stream contains an int16_t. */ - UBJSON_INT32_INT32, /**< The stream contains an int32_t. */ -} ubjson_int32_type_t; - -/** - * @brief Return value of ::ubjson_read_callback_t and ubjson_read() - * - * The callback invoked by ubjson_read(), ubjson_read_array() or ubjson_read_object() can return an error value. - * The error value is then returned by the read function. - * - * The values UBJSON_INVALID_DATA, UBJSON_PREMATURELY_ENDED, and UBJSON_SIZE_ERROR are returned on encoding errors, too. - */ -typedef enum { - UBJSON_OKAY, /**< success / do continue */ - UBJSON_ABORTED, /**< aborted / do abort */ - UBJSON_INVALID_DATA, /**< invalid marker or type*/ - UBJSON_PREMATURELY_ENDED, /**< the stream abruptly ended */ - UBJSON_SIZE_ERROR, /**< the length of a field exceeded SSIZE_MAX */ -} ubjson_read_callback_result_t; - -struct __attribute__ ((deprecated("The UBJSON module will be removed in release 2020.01"))) ubjson_cookie; - -/** - * @brief A cookie passed between the read and write functions. - * @details You probably want to wrap the cookie in some other data structure, - * which you retrieve with container_of() in the callback. - */ -typedef struct ubjson_cookie ubjson_cookie_t -__attribute__ ((deprecated("The UBJSON module will be removed in release 2020.01"))); - -/** - * @brief Method called by ubjson_read() to get more data. - * @param[in] cookie The cookie that was passed to ubjson_read(). - * @param[out] buf The buffer that should be written to. - * @param[in] max_len The length of the buffer. Always `>= 1`. - * @return @arg `< 0` on error. UBJSON_PREMATURELY_ENDED will be return by ubjson_read(). - * @arg `> 0` the amount of read data, which must not exceed max_len. - */ -typedef ssize_t (*ubjson_read_t)(ubjson_cookie_t *__restrict cookie, void *buf, size_t max_len); - -/** - * @brief Method called by ubjson_read() to denote the next element in the structure. - * @details Depending on the value of type1 a different function, such as ubjson_get_i32(), - * must be invoked by the callback function. - * - * With ubjson_read_array() or ubjson_read_object() the value of type1 is - * UBJSON_INDEX or UBJSON_KEY, resp. - * @param[in] cookie The cookie that was passed to ubjson_read(). - * @param[in] type1 The type of the next datum. - * @param[in] content1 The sub-type of the next datum. - * @param[in] type2 The type of the value that belongs to the next key/index, or UBJSON_ABSENT. - * @param[in] content2 The sub-type of the value that belongs to the next key/index. - * @returns Either UBJSON_OKAY or UBJSON_ABORTED. - */ -typedef ubjson_read_callback_result_t (*ubjson_read_callback_t)(ubjson_cookie_t *__restrict cookie, - ubjson_type_t type1, ssize_t content1, - ubjson_type_t type2, ssize_t content2); - -/** - * @brief Method called by ubjson_write_null() and friends. - * @details The function in invoked multiple times per written value. - * You should use some kind of buffer if you send the data over a stream. - * - * The function must write the whole buffer before returning. - * @param[in] cookie The cookie that was passed to ubjson_write_init(). - * @param[in] buf Data to write, never NULL. - * @param[in] len Data to write, always >= 0. - * @returns @arg `< 0` to indicate an error. - * @arg `> 0` to indicate success. - */ -typedef ssize_t (*ubjson_write_t)(ubjson_cookie_t *__restrict cookie, const void *buf, size_t len); - -/** - * @brief See @ref ubjson_cookie_t. - */ -struct ubjson_cookie { - /** - * @brief Read/write function - * @internal - */ - union { - ubjson_read_t read; /**< read function */ - ubjson_write_t write; /**< write function */ - } rw; - - /** - * @brief Callback function - * @internal - */ - union { - ubjson_read_callback_t read; /**< Callback when a datum was read. */ - } callback; /**< @internal */ - - /** - * @brief One byte push-back buffer. - * @internal - */ - char marker; -}; - -/** - * @brief Used to read with a setup cookie. - * @details You need to use this function instead of ubjson_read() only if - * your UBJSON data contains further UBJSON serialized data in a string. - * - * UBJSON data in a typed array may or may not work. - * @param[in] cookie The cookie that is passed to the callback function. - * @returns The same as ubjson_read(). - */ -ubjson_read_callback_result_t ubjson_read_next(ubjson_cookie_t *__restrict cookie); - -/** - * @brief The entry function to read UBJSON serialized data. - * @details This function invokes the callback function. - * The value of type1 in the callback indicates which function - * to call inside the callback function, e.g. ubjson_get_i32(). - * - * Nested calls to ubjson_read_array(), ubjson_read_object() or ubjson_read_next() - * invoke the same callback function, possibly multiple times. - * - * You probably want to wrap the cookie in some other data structure, - * which you retrieve with container_of() in the callback. - * - * @deprecated This function and its containing module are deprecated and - * will be removed in release 2020.01. - * - * @param[in] cookie The cookie that is passed to the callback function. - * @param[in] read The function that is called to receive more data. - * @param[in] callback The callback function. - * @returns See \ref ubjson_read_callback_result_t - */ -static inline ubjson_read_callback_result_t ubjson_read(ubjson_cookie_t *__restrict cookie, - ubjson_read_t read, - ubjson_read_callback_t callback) -{ - cookie->rw.read = read; - cookie->callback.read = callback; - cookie->marker = 0; - return ubjson_read_next(cookie); -} - -/** - * @brief Use in a callback if type1 is UBJSON_KEY or UBJSON_INDEX. - * @details Call like ``ubjson_peek_value(cookie, &type2, &content2)``. - * @param[in] cookie The cookie that was passed to the callback. - * @param[in,out] type Pointer to a variable that was initialized with the value of type2, returns the new type1. - * @param[in,out] content Pointer to a variable that was initialized with the value of content2, returns the new content1. - * @returns The same as ubjson_read(). - */ -ubjson_read_callback_result_t ubjson_peek_value(ubjson_cookie_t *__restrict cookie, - ubjson_type_t *type, ssize_t *content); - -/** - * @brief Call if type1 of the callback was UBJSON_TYPE_INT32. - * @details The value of content1 is one of ubjson_int32_type_t. - * @param[in] cookie The cookie that was passed to the callback function. - * @param[in] content The content1 that was passed to the callback function. - * @param[out] dest The read datum. - * @returns The result of the read callback, probably the amount of read bytes. - */ -ssize_t ubjson_get_i32(ubjson_cookie_t *__restrict cookie, ssize_t content, int32_t *dest); - -/** - * @brief Call if type1 of the callback was UBJSON_TYPE_INT64. - * @param[in] cookie The cookie that was passed to the callback function. - * @param[in] content The content1 that was passed to the callback function. - * @param[out] dest The read datum. - * @returns The result of the read callback, probably the amount of read bytes. - */ -ssize_t ubjson_get_i64(ubjson_cookie_t *__restrict cookie, ssize_t content, int64_t *dest); - -/** - * @brief Call if type1 of the callback was UBJSON_TYPE_STRING. - * @details content1 is the length of the string/blob. - * The result is not null-terminated! - * @param[in] cookie The cookie that was passed to the callback function. - * @param[in] content The content1 that was passed to the callback function. - * @param[out] dest Buffer to read the string into. - * @returns The result of the read callback, probably the amount of read bytes. - */ -ssize_t ubjson_get_string(ubjson_cookie_t *__restrict cookie, ssize_t content, void *dest); - -/** - * @brief Call if type1 of the callback was UBJSON_TYPE_BOOL. - * @details content1 is the value of the bool. The function only exists for symmetry. - * @param[in] cookie The cookie that was passed to the callback function. - * @param[in] content The content1 that was passed to the callback function. - * @param[out] dest The read datum. - * @returns `1`, the invocation cannot fail. - */ -static inline ssize_t ubjson_get_bool(ubjson_cookie_t *__restrict cookie, ssize_t content, bool *dest) -{ - (void) cookie; - *dest = content; - return 1; -} - -/** - * @brief Call if type1 of the callback was UBJSON_TYPE_FLOAT. - * @param[in] cookie The cookie that was passed to the callback function. - * @param[in] content The content1 that was passed to the callback function. - * @param[out] dest The read datum. - * @returns The result of the read callback, probably the amount of read bytes. - */ -static inline ssize_t ubjson_get_float(ubjson_cookie_t *__restrict cookie, ssize_t content, float *dest) -{ - (void) content; - union { - float f; - int32_t i; - } value; - ubjson_read_callback_result_t result = ubjson_get_i32(cookie, UBJSON_INT32_INT32, &value.i); - *dest = value.f; - return result; -} - -/** - * @brief Call if type1 of the callback was UBJSON_TYPE_DOUBLE. - * @param[in] cookie The cookie that was passed to the callback function. - * @param[in] content The content1 that was passed to the callback function. - * @param[out] dest The read datum. - * @returns The result of the read callback, probably the amount of read bytes. - */ -static inline ssize_t ubjson_get_double(ubjson_cookie_t *__restrict cookie, ssize_t content, double *dest) -{ - (void) content; - union { - double f; - int64_t i; - } value; - ubjson_read_callback_result_t result = ubjson_get_i64(cookie, -1, &value.i); - *dest = value.f; - return result; -} - -/** - * @brief Call if type1 of the callback was UBJSON_ENTER_ARRAY. - * @details Inside this call the callback function will be invoked multiple times, - * once per array element, with type1=UBJSON_INDEX, - * and content1=running index in the array. - * - * Use ubjson_peek_value() to determine the type of the element. - * @param[in] cookie The cookie that was passed to the callback function. - * @returns The same as ubjson_read(). - */ -ubjson_read_callback_result_t ubjson_read_array(ubjson_cookie_t *__restrict cookie); - - -/** - * @brief Call if type1 of the callback was UBJSON_ENTER_OBJECT. - * @details Inside this call the callback function will be invoked multiple times, - * once per object element, with type1=UBJSON_KEY, - * and content1=length of the key string. - * - * First read the key with ubjson_get_string(), then - * use ubjson_peek_value() to determine the type of the element. - * @param[in] cookie The cookie that was passed to the callback function. - * @returns The same as ubjson_read(). - */ -ubjson_read_callback_result_t ubjson_read_object(ubjson_cookie_t *__restrict cookie); - -/* *************************************************************************** - * WRITE FUNCTIONS / DEFINITIONS - *************************************************************************** */ - -/** - * @brief The first call when you serialize data to UBJSON. - * @details There is no corresponding "ubjson_write_finish" function. - * The programmer needs to ensure that the API is used correctly. - * The library won't complain if you write multiple values that are not - * inside an array or object. The result will just not be properly serialized. - * - * @deprecated This function and its containing module are deprecated and - * will be removed in release 2020.01 - * - * @param[out] cookie The cookie that will be passed to ubjson_write_null() and friends. - * @param[in] write_fun The function that will be called to write data. - */ -static inline void ubjson_write_init(ubjson_cookie_t *__restrict cookie, ubjson_write_t write_fun) -{ - cookie->rw.write = write_fun; -} - -/** - * @brief Write a null value. - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - */ -ssize_t ubjson_write_null(ubjson_cookie_t *__restrict cookie); - -/** - * @brief Write a no-operation value. - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_write_noop(ubjson_cookie_t *__restrict cookie); - -/** - * @brief Write a boolean value. - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @param[in] value The boolean value to write. - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_write_bool(ubjson_cookie_t *__restrict cookie, bool value); - -/** - * @brief Write an integer value. - * @details The library will determine the smallest serialization for the value itself. - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @param[in] value The integer value to write. - */ -ssize_t ubjson_write_i32(ubjson_cookie_t *__restrict cookie, int32_t value); - -/** - * @brief Write an integer value. - * @details The library will determine the smallest serialization for the value itself. - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @param[in] value The integer value to write. - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_write_i64(ubjson_cookie_t *__restrict cookie, int64_t value); - -/** - * @brief Write a floating point value. - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @param[in] value The integer value to write. - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_write_float(ubjson_cookie_t *__restrict cookie, float value); - -/** - * @brief Write a floating point value. - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @param[in] value The integer value to write. - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_write_double(ubjson_cookie_t *__restrict cookie, double value); - -/** - * @brief Write a string or blob. - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @param[in] value The string or blob to write. - * @param[in] len The length of the string or blob. - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_write_string(ubjson_cookie_t *__restrict cookie, const void *value, size_t len); - -/** - * @brief Open an array. - * @details Write multiple elements inside this array. - * Call ubjson_close_array() after the whole content was written. - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_open_array(ubjson_cookie_t *__restrict cookie); - -/** - * @brief Open an array with a known length. - * @details Do not call ubjson_close_array(). - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @param[in] len Length of the array. - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_open_array_len(ubjson_cookie_t *__restrict cookie, size_t len); - -/** - * @brief Close an array that was opened with ubjson_open_array(). - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_close_array(ubjson_cookie_t *__restrict cookie); - -/** - * @brief Open an object. - * @details Write multiple keys inside this object. - * Call ubjson_close_object() after the whole content was written. - * - * For each element first write the key with ubjson_write_key(), - * then invoke the function to write the value. - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_open_object(ubjson_cookie_t *__restrict cookie); - -/** - * @brief Open an object with a known length. - * @details For each element first write the key with ubjson_write_key(), - * then invoke the function to write the value. - * - * Do not call ubjson_close_object(). - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @param[in] len Number of keys inside the object. - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_open_object_len(ubjson_cookie_t *__restrict cookie, size_t len); - -/** - * @brief Write a key inside an object. - * @details For each element first write the key, - * then invoke the function to write the value. - * - * It is up to the programmer to ensure that there are no duplicated keys. - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @param[in] value The key, should be a UTF-8 string. - * @param[in] len The length of the key. - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_write_key(ubjson_cookie_t *__restrict cookie, const void *value, size_t len); - -/** - * @brief Close an array that was opened with ubjson_open_object(). - * @param[in] cookie The cookie that was initialized with ubjson_write_init(). - * @returns The result of the supplied @ref ubjson_write_t function. - */ -ssize_t ubjson_close_object(ubjson_cookie_t *__restrict cookie); - -#ifdef __cplusplus -} -#endif - -#endif /* UBJSON_H */ -/** @} */ diff --git a/sys/ubjson/Makefile b/sys/ubjson/Makefile deleted file mode 100644 index 48422e909a47..000000000000 --- a/sys/ubjson/Makefile +++ /dev/null @@ -1 +0,0 @@ -include $(RIOTBASE)/Makefile.base diff --git a/sys/ubjson/ubjson-internal.h b/sys/ubjson/ubjson-internal.h deleted file mode 100644 index 01cdb564cafb..000000000000 --- a/sys/ubjson/ubjson-internal.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2014 René Kijewski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef UBJSON_INTERNAL_H -#define UBJSON_INTERNAL_H - -/* compare http://ubjson.org/type-reference/ */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - UBJSON_MARKER_NULL = 'Z', - UBJSON_MARKER_NOOP = 'N', - - UBJSON_MARKER_TRUE = 'T', - UBJSON_MARKER_FALSE = 'F', - - UBJSON_MARKER_INT8 = 'i', - UBJSON_MARKER_UINT8 = 'U', - UBJSON_MARKER_INT16 = 'I', - UBJSON_MARKER_INT32 = 'l', - UBJSON_MARKER_INT64 = 'L', - - UBJSON_MARKER_FLOAT32 = 'd', - UBJSON_MARKER_FLOAT64 = 'D', - UBJSON_MARKER_HP_NUMBER = 'H', - - UBJSON_MARKER_CHAR = 'C', - UBJSON_MARKER_STRING = 'S', - - UBJSON_MARKER_ARRAY_START = '[', - UBJSON_MARKER_ARRAY_END = ']', - - UBJSON_MARKER_OBJECT_START = '{', - UBJSON_MARKER_OBJECT_END = '}', - - UBJSON_MARKER_COUNT = '#', - UBJSON_MARKER_TYPE = '$', -} ubjson_marker_t; - -#ifdef __cplusplus -} -#endif - -#endif /* UBJSON_INTERNAL_H */ diff --git a/sys/ubjson/ubjson-read.c b/sys/ubjson/ubjson-read.c deleted file mode 100644 index c50493d07523..000000000000 --- a/sys/ubjson/ubjson-read.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2014 René Kijewski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @ingroup sys_ubjson - * @{ - * @file - * @brief Universal Binary JSON deserializer - * @author René Kijewski - * @} - */ - -#include "ubjson-internal.h" -#include "ubjson.h" -#include "byteorder.h" - -#define READ_MARKER() \ - do { \ - result = _ubjson_read_marker(cookie, &marker); \ - if (result != UBJSON_OKAY) { \ - return result; \ - } \ - } while (0) - -static ubjson_read_callback_result_t _ubjson_read_marker(ubjson_cookie_t *restrict cookie, - char *marker) -{ - while (1) { - ssize_t bytes_read; - - *marker = cookie->marker; - if (!*marker) { - bytes_read = cookie->rw.read(cookie, marker, 1); - } - else { - cookie->marker = 0; - bytes_read = 1; - } - - if (bytes_read == 1) { - return UBJSON_OKAY; - } - else if (bytes_read != 0) { - return UBJSON_PREMATURELY_ENDED; - } - } -} - -ssize_t ubjson_get_string(ubjson_cookie_t *restrict cookie, ssize_t length, void *dest_) -{ - ssize_t total = 0; - char *dest = dest_; - while (total < length) { - ssize_t read = cookie->rw.read(cookie, dest, length - total); - if (read < 0) { - return read; - } - total += read; - dest += read; - } - return total; -} - -ssize_t ubjson_get_i32(ubjson_cookie_t *restrict cookie, ssize_t content, int32_t *dest) -{ - static const int8_t LENGTHS[] = { 1, 1, 2, 4 }; - - union { - int8_t i8; - uint8_t u8; - network_uint16_t i16; - network_uint32_t i32; - } value; - - int type = content; - - ssize_t result = ubjson_get_string(cookie, LENGTHS[type], &value); - if (result > 0) { - switch (type) { - case UBJSON_INT32_INT8: - *dest = value.i8; - break; - case UBJSON_INT32_UINT8: - *dest = value.u8; - break; - case UBJSON_INT32_INT16: - *dest = (int16_t) byteorder_ntohs(value.i16); - break; - case UBJSON_INT32_INT32: - *dest = (int32_t) byteorder_ntohl(value.i32); - break; - default: - return -1; - } - } - return result; -} - -ssize_t ubjson_get_i64(ubjson_cookie_t *restrict cookie, ssize_t content, int64_t *dest) -{ - (void) content; - - network_uint64_t buf; - ssize_t result = ubjson_get_string(cookie, 8, &buf); - *dest = byteorder_ntohll(buf); - return result; -} - -static ubjson_read_callback_result_t _ubjson_read_length(ubjson_cookie_t *restrict cookie, - ssize_t *len) -{ - ubjson_type_t type; - ssize_t content = 0; - ubjson_read_callback_result_t result = ubjson_peek_value(cookie, &type, &content); - if (result != UBJSON_OKAY) { - return result; - } - - int64_t len64 = -1; - ssize_t read; - if (type == UBJSON_TYPE_INT32) { - int32_t len32; - read = ubjson_get_i32(cookie, content, &len32); - if (read > 0) { - len64 = len32; - } - } - else if (type == UBJSON_TYPE_INT64) { - read = ubjson_get_i64(cookie, content, &len64); - } - else { - return UBJSON_INVALID_DATA; - } - - if (read <= 0) { - return UBJSON_PREMATURELY_ENDED; - } - else if ((ssize_t) len64 < 0) { - return UBJSON_SIZE_ERROR; - } - else if (len64 < 0) { - return UBJSON_INVALID_DATA; - } - - *len = len64; - return UBJSON_OKAY; -} - -static ubjson_read_callback_result_t _ubjson_get_call(ubjson_cookie_t *restrict cookie, - char marker, - ubjson_type_t *type, ssize_t *content) -{ - *content = -1; - - switch (marker) { - case UBJSON_MARKER_NULL: - *type = UBJSON_TYPE_NULL; - break; - - case UBJSON_MARKER_NOOP: - *type = UBJSON_TYPE_NOOP; - break; - - case UBJSON_MARKER_TRUE: - case UBJSON_MARKER_FALSE: - *type = UBJSON_TYPE_BOOL, - *content = (marker == UBJSON_MARKER_TRUE); - break; - - case UBJSON_MARKER_INT8: - *content = UBJSON_INT32_INT8; - *type = UBJSON_TYPE_INT32; - break; - - case UBJSON_MARKER_UINT8: - *content = UBJSON_INT32_UINT8; - *type = UBJSON_TYPE_INT32; - break; - - case UBJSON_MARKER_INT16: - *content = UBJSON_INT32_INT16; - *type = UBJSON_TYPE_INT32; - break; - - case UBJSON_MARKER_INT32: - *content = UBJSON_INT32_INT32; - *type = UBJSON_TYPE_INT32; - break; - - case UBJSON_MARKER_INT64: - *type = UBJSON_TYPE_INT64; - break; - - case UBJSON_MARKER_CHAR: - *type = UBJSON_TYPE_STRING; - break; - - case UBJSON_MARKER_FLOAT32: - *type = UBJSON_TYPE_FLOAT; - break; - - case UBJSON_MARKER_FLOAT64: - *type = UBJSON_TYPE_DOUBLE; - break; - - case UBJSON_MARKER_STRING: { - ubjson_read_callback_result_t result = _ubjson_read_length(cookie, content); - if (result != UBJSON_OKAY) { - return result; - } - *type = UBJSON_TYPE_STRING; - break; - } - - case UBJSON_MARKER_ARRAY_START: - *type = UBJSON_ENTER_ARRAY; - break; - - case UBJSON_MARKER_OBJECT_START: - *type = UBJSON_ENTER_OBJECT; - break; - - /* NOTE: High-precision numbers are not implemented, yet. Implement if needed. - * - * case UBJSON_MARKER_HP_NUMBER: - * ... - * break; - */ - - case UBJSON_MARKER_ARRAY_END: - case UBJSON_MARKER_OBJECT_END: - case UBJSON_MARKER_COUNT: - case UBJSON_MARKER_TYPE: - default: - return UBJSON_INVALID_DATA; - } - - return UBJSON_OKAY; -} - -typedef bool (*_ubjson_read_struct_continue)(ubjson_cookie_t *restrict cookie, char marker, - ubjson_read_callback_result_t *result, - ssize_t count, ssize_t index, - ubjson_type_t *type1, ssize_t *content1); - -static ubjson_read_callback_result_t _ubjson_read_struct(ubjson_cookie_t *restrict cookie, - _ubjson_read_struct_continue get_continue) -{ - ubjson_read_callback_result_t result; - ssize_t count = -1; - char marker, type_marker = 0; - - READ_MARKER(); - - if (marker == UBJSON_MARKER_TYPE) { - READ_MARKER(); - if (marker == 0) { - return UBJSON_INVALID_DATA; - } - type_marker = marker; - READ_MARKER(); - } - - if (marker == UBJSON_MARKER_COUNT) { - result = _ubjson_read_length(cookie, &count); - if (result != UBJSON_OKAY) { - return result; - } - READ_MARKER(); - } - - cookie->marker = marker; - - if ((type_marker != 0) && (count < 0)) { - /* If a type is specified, a count must be specified as well. - * Otherwise a ']' could either be data (e.g. the character ']'), - * or be meant to close the array. - */ - return UBJSON_INVALID_DATA; - } - - for (ssize_t index = 0; (count < 0) || (index < count); ++index) { - ubjson_type_t type1; - ssize_t content1; - - READ_MARKER(); - if (!get_continue(cookie, marker, &result, count, index, &type1, &content1) - || (result != UBJSON_OKAY)) { - break; - } - - result = cookie->callback.read(cookie, type1, content1, - UBJSON_ABSENT, (unsigned char) type_marker); - if (result != UBJSON_OKAY) { - break; - } - } - - return result; -} - -static bool _ubjson_read_array_continue(ubjson_cookie_t *restrict cookie, char marker, - ubjson_read_callback_result_t *result, - ssize_t count, ssize_t index, - ubjson_type_t *type1, ssize_t *content1) -{ - if (marker == UBJSON_MARKER_ARRAY_END) { - if (count >= 0) { - *result = UBJSON_INVALID_DATA; - } - return false; - } - - cookie->marker = marker; - - *type1 = UBJSON_INDEX; - *content1 = index; - return true; -} - -static bool _ubjson_read_object_continue(ubjson_cookie_t *restrict cookie, char marker, - ubjson_read_callback_result_t *result, - ssize_t count, ssize_t index, - ubjson_type_t *type1, ssize_t *content1) -{ - (void) index; - - if (marker == UBJSON_MARKER_OBJECT_END) { - if (count >= 0) { - *result = UBJSON_INVALID_DATA; - } - return false; - } - - cookie->marker = marker; - - *type1 = UBJSON_KEY; - *result = _ubjson_read_length(cookie, content1); - return true; -} - -ubjson_read_callback_result_t ubjson_read_array(ubjson_cookie_t *restrict cookie) -{ - return _ubjson_read_struct(cookie, _ubjson_read_array_continue); -} - -ubjson_read_callback_result_t ubjson_read_object(ubjson_cookie_t *restrict cookie) -{ - return _ubjson_read_struct(cookie, _ubjson_read_object_continue); -} - -ubjson_read_callback_result_t ubjson_read_next(ubjson_cookie_t *restrict cookie) -{ - char marker; - ubjson_read_callback_result_t result; - READ_MARKER(); - - ubjson_type_t type; - ssize_t content; - result = _ubjson_get_call(cookie, marker, &type, &content); - if (result != UBJSON_OKAY) { - return result; - } - - return cookie->callback.read(cookie, type, content, UBJSON_ABSENT, 0); -} - -ubjson_read_callback_result_t ubjson_peek_value(ubjson_cookie_t *restrict cookie, - ubjson_type_t *type, ssize_t *content) -{ - char marker = (char) *content; - if (marker == 0) { - ubjson_read_callback_result_t result; - READ_MARKER(); - } - return _ubjson_get_call(cookie, marker, type, content); -} diff --git a/sys/ubjson/ubjson-write.c b/sys/ubjson/ubjson-write.c deleted file mode 100644 index 3028d566558b..000000000000 --- a/sys/ubjson/ubjson-write.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2014 René Kijewski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @ingroup sys_ubjson - * @{ - * @file - * @brief Universal Binary JSON deserializer - * @author René Kijewski - * @} - */ - -#include "ubjson-internal.h" -#include "ubjson.h" -#include "byteorder.h" - -#include - -#define WRITE_CALL(FUN, ...) \ - do { \ - ssize_t wrote = (FUN)(__VA_ARGS__); \ - if (wrote < 0) { \ - return wrote; \ - } \ - result += wrote; \ - } while (0) - -#define WRITE_BUF(BUF, COUNT) \ - WRITE_CALL(cookie->rw.write, cookie, (BUF), (COUNT)) - -#define WRITE_MARKER(MARKER) \ - do { \ - char marker_buf[] = { (char) (MARKER) }; \ - WRITE_BUF(marker_buf, 1); \ - } while (0) - -#define MARKER_FUN(NAME, MARKER) \ - ssize_t NAME(ubjson_cookie_t *restrict cookie) \ - { \ - ssize_t result = 0; \ - WRITE_MARKER((MARKER)); \ - return result; \ - } - -MARKER_FUN(ubjson_write_null, UBJSON_MARKER_NULL) -MARKER_FUN(ubjson_write_noop, UBJSON_MARKER_NOOP) - -MARKER_FUN(ubjson_open_array, UBJSON_MARKER_ARRAY_START) -MARKER_FUN(ubjson_close_array, UBJSON_MARKER_ARRAY_END) - -MARKER_FUN(ubjson_open_object, UBJSON_MARKER_OBJECT_START) -MARKER_FUN(ubjson_close_object, UBJSON_MARKER_OBJECT_END) - -ssize_t ubjson_write_bool(ubjson_cookie_t *restrict cookie, bool value) -{ - static const char marker_false[] = { UBJSON_MARKER_FALSE }; - static const char marker_true[] = { UBJSON_MARKER_TRUE }; - return cookie->rw.write(cookie, value ? &marker_true : &marker_false, 1); -} - -ssize_t ubjson_write_i32(ubjson_cookie_t *restrict cookie, int32_t value) -{ - ssize_t result = 0; - if ((INT8_MIN <= value) && (value <= INT8_MAX)) { - WRITE_MARKER(UBJSON_MARKER_INT8); - WRITE_MARKER((uint8_t) value); - } - else if ((0 <= value) && (value <= UINT8_MAX)) { - WRITE_MARKER(UBJSON_MARKER_UINT8); - WRITE_MARKER((uint8_t) value); - } - else if ((INT16_MIN <= value) && (value <= UINT16_MAX)) { - WRITE_MARKER(UBJSON_MARKER_INT16); - network_uint16_t buf = byteorder_htons((uint16_t) value); - WRITE_BUF(&buf, sizeof(buf)); - } - else { - WRITE_MARKER(UBJSON_MARKER_INT32); - network_uint32_t buf = byteorder_htonl((uint32_t) value); - WRITE_BUF(&buf, sizeof(buf)); - } - return result; -} - -ssize_t ubjson_write_i64(ubjson_cookie_t *restrict cookie, int64_t value) -{ - if ((INT32_MIN <= value) && (value <= INT32_MAX)) { - return ubjson_write_i32(cookie, (int32_t) value); - } - - ssize_t result = 0; - WRITE_MARKER(UBJSON_MARKER_INT64); - network_uint64_t buf = byteorder_htonll((uint64_t) value); - WRITE_BUF(&buf, sizeof(buf)); - return result; -} - -ssize_t ubjson_write_float(ubjson_cookie_t *restrict cookie, float value) -{ - union { - float f; - uint32_t i; - } v = { .f = value }; - - ssize_t result = 0; - WRITE_MARKER(UBJSON_MARKER_FLOAT32); - network_uint32_t buf = byteorder_htonl(v.i); - WRITE_BUF(&buf, sizeof(buf)); - return result; -} - -ssize_t ubjson_write_double(ubjson_cookie_t *restrict cookie, double value) -{ - union { - double f; - uint64_t i; - } v = { .f = value }; - - ssize_t result = 0; - WRITE_MARKER(UBJSON_MARKER_FLOAT64); - network_uint64_t buf = byteorder_htonll(v.i); - WRITE_BUF(&buf, sizeof(buf)); - return result; -} - -ssize_t ubjson_write_string(ubjson_cookie_t *restrict cookie, const void *value, size_t len) -{ - ssize_t result = 0; - WRITE_MARKER(UBJSON_MARKER_STRING); - WRITE_CALL(ubjson_write_key, cookie, value, len); - return result; -} - -static ssize_t _ubjson_write_length(ubjson_cookie_t *restrict cookie, size_t len) -{ - ssize_t result = 0; - WRITE_MARKER(UBJSON_MARKER_COUNT); - WRITE_CALL(ubjson_write_i64, cookie, (int64_t) len); - return result; -} - -ssize_t ubjson_open_array_len(ubjson_cookie_t *restrict cookie, size_t len) -{ - ssize_t result = 0; - WRITE_CALL(ubjson_open_array, cookie); - if (len > 0) { - WRITE_CALL(_ubjson_write_length, cookie, len); - } - else { - WRITE_CALL(ubjson_close_array, cookie); - } - return result; -} - -ssize_t ubjson_open_object_len(ubjson_cookie_t *restrict cookie, size_t len) -{ - ssize_t result = 0; - WRITE_CALL(ubjson_open_object, cookie); - if (len > 0) { - WRITE_CALL(_ubjson_write_length, cookie, len); - } - else { - WRITE_CALL(ubjson_close_object, cookie); - } - return result; -} - -ssize_t ubjson_write_key(ubjson_cookie_t *restrict cookie, const void *value, size_t len) -{ - ssize_t result = 0; - WRITE_CALL(ubjson_write_i64, cookie, (int64_t) len); - WRITE_BUF(value, len); - return result; -} diff --git a/tests/unittests/tests-ubjson/Makefile b/tests/unittests/tests-ubjson/Makefile deleted file mode 100644 index 48422e909a47..000000000000 --- a/tests/unittests/tests-ubjson/Makefile +++ /dev/null @@ -1 +0,0 @@ -include $(RIOTBASE)/Makefile.base diff --git a/tests/unittests/tests-ubjson/Makefile.include b/tests/unittests/tests-ubjson/Makefile.include deleted file mode 100644 index d4978f02bb57..000000000000 --- a/tests/unittests/tests-ubjson/Makefile.include +++ /dev/null @@ -1,4 +0,0 @@ -USEMODULE += ubjson -USEMODULE += pipe - -CFLAGS += -Wno-error=deprecated-declarations diff --git a/tests/unittests/tests-ubjson/test-ubjson-empty-array.c b/tests/unittests/tests-ubjson/test-ubjson-empty-array.c deleted file mode 100644 index 585a9da63f90..000000000000 --- a/tests/unittests/tests-ubjson/test-ubjson-empty-array.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2014 René Kijewski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "tests-ubjson.h" - -typedef enum { - BEFORE_ARRAY_1 = __LINE__, - IN_ARRAY_1 = __LINE__, - - BEFORE_ARRAY_2 = __LINE__, - IN_ARRAY_2 = __LINE__, - - BEFORE_END = __LINE__, -} test_ubjson_empty_array_state_t; - -typedef struct { - ubjson_cookie_t cookie; - test_ubjson_empty_array_state_t state; -} test_ubjson_empty_array_receiver_cookie_t; - -static void test_ubjson_empty_array_receiver_callback_sub( - ubjson_cookie_t *restrict cookie, - ubjson_type_t type1, ssize_t content1, - ubjson_type_t type2, ssize_t content2, - ubjson_read_callback_result_t *result) -{ - *result = UBJSON_ABORTED; - - (void) content1, (void) type2, (void) content2; - - test_ubjson_empty_array_receiver_cookie_t *state; - state = container_of(cookie, test_ubjson_empty_array_receiver_cookie_t, cookie); - - switch (state->state) { - case BEFORE_ARRAY_1: - TEST_ASSERT_EQUAL_INT(UBJSON_ENTER_ARRAY, type1); - state->state = IN_ARRAY_1; - TEST_ASSERT_EQUAL_INT(UBJSON_OKAY, ubjson_read_array(cookie)); - state->state = BEFORE_ARRAY_2; - break; - - case IN_ARRAY_1: - TEST_FAIL("The empty array was not empty (1)"); - break; - - case BEFORE_ARRAY_2: - TEST_ASSERT_EQUAL_INT(UBJSON_ENTER_ARRAY, type1); - state->state = IN_ARRAY_2; - TEST_ASSERT_EQUAL_INT(UBJSON_OKAY, ubjson_read_array(cookie)); - state->state = BEFORE_END; - break; - - case IN_ARRAY_2: - TEST_FAIL("The empty array was not empty (2)"); - break; - - case BEFORE_END: - TEST_FAIL("Content after the end"); - break; - - default: - TEST_FAIL("The cookie was corrupted"); - break; - } - - *result = UBJSON_OKAY; -} - -static ubjson_read_callback_result_t test_ubjson_empty_array_receiver_callback( - ubjson_cookie_t *restrict cookie, - ubjson_type_t type1, ssize_t content1, - ubjson_type_t type2, ssize_t content2) -{ - ubjson_read_callback_result_t result; - test_ubjson_empty_array_receiver_callback_sub(cookie, type1, content1, type2, content2, &result); - return result; -} - -static void test_ubjson_empty_array_receiver(void) -{ - test_ubjson_empty_array_receiver_cookie_t state; - state.state = BEFORE_ARRAY_1; - - TEST_ASSERT_EQUAL_INT(UBJSON_OKAY, - ubjson_read(&state.cookie, test_ubjson_read_fun, - test_ubjson_empty_array_receiver_callback)); - TEST_ASSERT_EQUAL_INT(BEFORE_ARRAY_2, state.state); - - TEST_ASSERT_EQUAL_INT(UBJSON_OKAY, - ubjson_read(&state.cookie, test_ubjson_read_fun, - test_ubjson_empty_array_receiver_callback)); - TEST_ASSERT_EQUAL_INT(BEFORE_END, state.state); -} - -#undef EMBUNIT_ERROR_RETURN -#define EMBUNIT_ERROR_RETURN - -static void test_ubjson_empty_array_sender(void) -{ - ubjson_cookie_t cookie; - ubjson_write_init(&cookie, test_ubjson_write_fun); - - TEST_ASSERT(ubjson_open_array(&cookie) > 0); - TEST_ASSERT(ubjson_close_array(&cookie) > 0); - TEST_ASSERT(ubjson_open_array_len(&cookie, 0) > 0); -} - -void test_ubjson_empty_array(void) -{ - test_ubjson_test(test_ubjson_empty_array_sender, - test_ubjson_empty_array_receiver); -} diff --git a/tests/unittests/tests-ubjson/test-ubjson-empty-object.c b/tests/unittests/tests-ubjson/test-ubjson-empty-object.c deleted file mode 100644 index 359c61a74e03..000000000000 --- a/tests/unittests/tests-ubjson/test-ubjson-empty-object.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2014 René Kijewski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "tests-ubjson.h" - -typedef enum { - BEFORE_ARRAY_1 = __LINE__, - IN_ARRAY_1 = __LINE__, - - BEFORE_ARRAY_2 = __LINE__, - IN_ARRAY_2 = __LINE__, - - BEFORE_END = __LINE__, -} test_ubjson_empty_object_state_t; - -typedef struct { - ubjson_cookie_t cookie; - test_ubjson_empty_object_state_t state; -} test_ubjson_empty_object_receiver_cookie_t; - -static void test_ubjson_empty_object_receiver_callback_sub( - ubjson_cookie_t *restrict cookie, - ubjson_type_t type1, ssize_t content1, - ubjson_type_t type2, ssize_t content2, - ubjson_read_callback_result_t *result) -{ - *result = UBJSON_ABORTED; - - (void) content1, (void) type2, (void) content2; - - test_ubjson_empty_object_receiver_cookie_t *state; - state = container_of(cookie, test_ubjson_empty_object_receiver_cookie_t, cookie); - - switch (state->state) { - case BEFORE_ARRAY_1: - TEST_ASSERT_EQUAL_INT(UBJSON_ENTER_OBJECT, type1); - state->state = IN_ARRAY_1; - TEST_ASSERT_EQUAL_INT(UBJSON_OKAY, ubjson_read_object(cookie)); - state->state = BEFORE_ARRAY_2; - break; - - case IN_ARRAY_1: - TEST_FAIL("The empty object was not empty (1)"); - break; - - case BEFORE_ARRAY_2: - TEST_ASSERT_EQUAL_INT(UBJSON_ENTER_OBJECT, type1); - state->state = IN_ARRAY_2; - TEST_ASSERT_EQUAL_INT(UBJSON_OKAY, ubjson_read_object(cookie)); - state->state = BEFORE_END; - break; - - case IN_ARRAY_2: - TEST_FAIL("The empty object was not empty (2)"); - break; - - case BEFORE_END: - TEST_FAIL("Content after the end"); - break; - - default: - TEST_FAIL("The cookie was corrupted"); - break; - } - - *result = UBJSON_OKAY; -} - -static ubjson_read_callback_result_t test_ubjson_empty_object_receiver_callback( - ubjson_cookie_t *restrict cookie, - ubjson_type_t type1, ssize_t content1, - ubjson_type_t type2, ssize_t content2) -{ - ubjson_read_callback_result_t result; - test_ubjson_empty_object_receiver_callback_sub(cookie, type1, content1, type2, content2, &result); - return result; -} - -#undef EMBUNIT_ERROR_RETURN -#define EMBUNIT_ERROR_RETURN - -static void test_ubjson_empty_object_receiver(void) -{ - test_ubjson_empty_object_receiver_cookie_t state; - state.state = BEFORE_ARRAY_1; - - TEST_ASSERT_EQUAL_INT(UBJSON_OKAY, - ubjson_read(&state.cookie, test_ubjson_read_fun, - test_ubjson_empty_object_receiver_callback)); - TEST_ASSERT_EQUAL_INT(BEFORE_ARRAY_2, state.state); - - TEST_ASSERT_EQUAL_INT(UBJSON_OKAY, - ubjson_read(&state.cookie, test_ubjson_read_fun, - test_ubjson_empty_object_receiver_callback)); - TEST_ASSERT_EQUAL_INT(BEFORE_END, state.state); -} - -#undef EMBUNIT_ERROR_RETURN -#define EMBUNIT_ERROR_RETURN - -static void test_ubjson_empty_object_sender(void) -{ - ubjson_cookie_t cookie; - ubjson_write_init(&cookie, test_ubjson_write_fun); - - TEST_ASSERT(ubjson_open_object(&cookie) > 0); - TEST_ASSERT(ubjson_close_object(&cookie) > 0); - TEST_ASSERT(ubjson_open_object_len(&cookie, 0) > 0); -} - -void test_ubjson_empty_object(void) -{ - test_ubjson_test(test_ubjson_empty_object_sender, - test_ubjson_empty_object_receiver); -} diff --git a/tests/unittests/tests-ubjson/tests-ubjson.c b/tests/unittests/tests-ubjson/tests-ubjson.c deleted file mode 100644 index 1c3de4c7d928..000000000000 --- a/tests/unittests/tests-ubjson/tests-ubjson.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2014 René Kijewski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "tests-ubjson.h" - -#include "thread.h" -#include "sched.h" -#include "msg.h" -#include "mutex.h" -#include "pipe.h" -#include "irq.h" - -static pipe_t communication_pipe; -static ringbuffer_t pipe_rb; -static char pipe_buffer[16]; - -static char receiver_stack[THREAD_STACKSIZE_DEFAULT]; - -typedef struct { - void (*run)(void); - thread_t *main_thread; - mutex_t mutexes[2]; -} test_ubjson_receiver_data_t; - -static void ubjson_set_up(void) -{ - ringbuffer_init(&pipe_rb, pipe_buffer, sizeof(pipe_buffer)); - pipe_init(&communication_pipe, &pipe_rb, NULL); -} - -ssize_t test_ubjson_write_fun(ubjson_cookie_t *restrict cookie, const void *buf, size_t len) -{ - (void) cookie; - ssize_t total = 0; - while (total < (ssize_t) len) { - ssize_t subtotal = pipe_write(&communication_pipe, buf, len); - if (subtotal < 0) { - return subtotal; - } - total += subtotal; - } - return total; -} - -ssize_t test_ubjson_read_fun(ubjson_cookie_t *restrict cookie, void *buf, size_t len) -{ - (void) cookie; - return pipe_read(&communication_pipe, buf, len); -} - -static void *test_ubjson_receiver_trampoline(void *arg) -{ - test_ubjson_receiver_data_t *data = arg; - data->run(); - - mutex_unlock(&data->mutexes[0]); - mutex_lock(&data->mutexes[1]); - - irq_disable(); - sched_set_status(data->main_thread, STATUS_PENDING); - return NULL; -} - -void test_ubjson_test(void (*sender_fun)(void), void (*receiver_fun)(void)) -{ - test_ubjson_receiver_data_t data = { - .run = receiver_fun, - .main_thread = (thread_t *) sched_active_thread, - .mutexes = { MUTEX_INIT, MUTEX_INIT }, - }; - mutex_lock(&data.mutexes[0]); - mutex_lock(&data.mutexes[1]); - - kernel_pid_t receiver_pid = thread_create(receiver_stack, sizeof(receiver_stack), - THREAD_PRIORITY_MAIN, - THREAD_CREATE_WOUT_YIELD, - test_ubjson_receiver_trampoline, &data, "receiver"); - TEST_ASSERT(pid_is_valid(receiver_pid)); - - sender_fun(); - - mutex_lock(&data.mutexes[0]); - mutex_unlock_and_sleep(&data.mutexes[1]); -} - -static Test *tests_ubjson_tests(void) -{ - EMB_UNIT_TESTFIXTURES(fixtures) { - new_TestFixture(test_ubjson_empty_array), - new_TestFixture(test_ubjson_empty_object), - }; - - EMB_UNIT_TESTCALLER(ubjson_tests, ubjson_set_up, NULL, fixtures); - - return (Test *) &ubjson_tests; -} - -void tests_ubjson(void) -{ - TESTS_RUN(tests_ubjson_tests()); -} diff --git a/tests/unittests/tests-ubjson/tests-ubjson.h b/tests/unittests/tests-ubjson/tests-ubjson.h deleted file mode 100644 index 2087ab4a0a33..000000000000 --- a/tests/unittests/tests-ubjson/tests-ubjson.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2014 René Kijewski - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @addtogroup unittests - * @{ - * - * @file - * @brief Unittests for the ``ubjson`` module - * - * @author René Kijewski - */ - -#ifndef TESTS_UBJSON_H -#define TESTS_UBJSON_H - -#include "embUnit.h" -#include "kernel_defines.h" - -#include "ubjson.h" - -#ifdef __cplusplus -extern "C" { -#endif - -ssize_t test_ubjson_write_fun(ubjson_cookie_t *__restrict cookie, const void *buf, size_t len); -ssize_t test_ubjson_read_fun(ubjson_cookie_t *__restrict cookie, void *buf, size_t len); - -void test_ubjson_test(void (*sender_fun)(void), void (*receiver_fun)(void)); - -void test_ubjson_empty_array(void); -void test_ubjson_empty_object(void); - -#ifdef __cplusplus -} -#endif - -#endif /* TESTS_UBJSON_H */ -/** @} */