Git Product home page Git Product logo

micro-cdr's Introduction

eProsima Micro CDR

Releases License Issues Forks Stars

eProsima Micro CDR is a C library implementing the CDR standard serialization methods. This library is focused on embedded and resource-limited systems.

Micro CDR uses a static buffer, and allow to serialize and deserialize in both, big endianness and little endianness.

Usage examples

This is a code example showing the serialization and deserialization of a string. As Micro CDR uses a static buffer, the user has to provide a defined buffer and its size during the ucdrBuffer creation.

    #include <ucdr/microcdr.h>
    #include <stdio.h>

    #define BUFFER_LENGTH 256

    int main(int argc, char** args)
    {
        // Data buffer
        uint8_t buffer[BUFFER_LENGTH];

        // Structs for handle the buffer.
        ucdrBuffer writer;
        ucdrBuffer reader;

        // Initialize the MicroBuffers for working with an user-managed buffer.
        ucdr_init_buffer(&writer, buffer, BUFFER_LENGTH);
        ucdr_init_buffer(&reader, buffer, BUFFER_LENGTH);

        // Serialize data
        char input[16] = "Hello Micro CDR!"; //16 characters
        ucdr_serialize_array_char(&writer, input, 16);

        // Deserialize data
        char output[16];
        ucdr_deserialize_array_char(&reader, output, 16);

        printf("Input: %s\n", input);
        printf("Output: %s\n", output);

        return 0;
    }

API functions

void ucdr_init_buffer                       (ucdrBuffer* ub, uint8_t* data, size_t size);
void ucdr_init_buffer_origin                (ucdrBuffer* ub, uint8_t* data, size_t size, size_t origin);
void ucdr_init_buffer_origin_offset         (ucdrBuffer* ub, uint8_t* data, size_t size, size_t origin, size_t offset);
void ucdr_init_buffer_origin_offset_endian  (ucdrBuffer* ub, uint8_t* data, size_t size, size_t origin, size_t offset, ucdrEndianness endianness);

Initialize a ucdrBuffer structure, the main struct of Micro CDR.

  • ub: the ucdrBuffer struct.
  • data: the buffer that the ucdrBuffer will use.
  • size: the size of the buffer that the ucdrBuffer will use.
  • origin: the origin of the XCDR stream.
  • offset: where the serialization/deserialization will start.
  • endianness: the endianness of the XCDR stream. Initially, the serialization/deserialization starts at the beginning of the buffer.

void ucdr_copy_buffer (ucdrBuffer* ub_dest, const ucdrBuffer* ub_source);

Copy a ucdrBuffer structure data to another ucdrBuffer structure.

  • ub_dest: the destination ucdrBuffer struct.
  • ub_source: the origin initialized ucdrBuffer struct.

void ucdr_set_on_full_buffer_callback (ucdrBuffer* ub, OnFullBuffer on_full_buffer, void* args);

Sets the on_full_buffer callback which will be called each time the buffer arises its end.

  • ub: the ucdrBuffer struct.
  • on_full_buffer: the callcack.
  • args: the argument passes to the callback.

void ucdr_reset_buffer       (ucdrBuffer* ub);
void ucdr_reset_buffer_offset(ucdrBuffer* ub, size_t offset);

Reset the ucdrBuffer as the same state that it was created.

  • ub: the ucdrBuffer struct.
  • offset: where the serialization/deserialization will start. Initially, the serialization/deserialization starts at the beginning of the buffer.

void ucdr_align_to (ucdrBuffer* ub, size_t size);

Align the ucdrBuffer to the size size. After call this function, the serialization pointer will be moved only if the current ucdrBuffer was not alignment to the passed value.

  • ub: the ucdrBuffer struct
  • size: the target size alignment.

size_t ucdr_alignment(size_t buffer_position, size_t data_size);

Returns the alignment necessary to serialize/deserialize a type with data_size size.

  • buffer_position: the current serialization/deserialization position of the ucdrBuffer. (Typically ub->iterator - ub->init).
  • data_size: the bytes of the data that you are asking for.

size_t ucdr_buffer_alignment(const ucdrBuffer* ub, size_t data_size);

Returns the alignment necessary to serialize/deserialize a type with data_size size into the ucdrBuffer given.

  • ub: the ucdrBuffer struct to ask the alignment.
  • data_size: the bytes of the data that you are asking for.

void ucdr_advance_buffer(const ucdrBuffer* ub, size_t size);

Advances the XCDR stream size bytes without de/serialization involved.

  • ub: the ucdrBuffer struct to ask the alignment.
  • size: the bytes to advance.

size_t ucdr_buffer_size(const ucdrBuffer* ub);

Returns the memory size of the buffer.

  • ub: the ucdrBuffer struct

size_t ucdr_buffer_length(const ucdrBuffer* ub);

Returns the size of the serialized/deserialized data.

  • ub: the ucdrBuffer struct

size_t ucdr_buffer_remaining(const ucdrBuffer* ub);

Returns the remaining size for the serializing/deserializing.

  • ub: the ucdrBuffer struct

ucdrEndianness ucdr_buffer_endianness(const ucdrBuffer* ub);

Returns the serialization/deserialization endianness.

  • ub: the ucdrBuffer struct

bool ucdr_buffer_error(const ucdrBuffer* ub);

Returns the status error of the ucdrBuffer.

  • ub: the ucdrBuffer struct

Serialization/deserialization functions

Adding to this, there is a big set of functions for deserialize and deserialize different kind of types:

  • Basics: bool, char, int8_t, uint8_t,int16_t, uint16_t,int32_t, uint32_t,int64_t, uint64_t,float, double.
  • Arrays: Any fixed size of basics types.
  • Sequence: Similar to arrays, but the information about the size is serialized along with the data.
  • String: Wrapper of char sequence.

Endianness

Micro CDR supports little and big endianness. The machine endianness can be set by the cmake variable: CONFIG_BIG_ENDIANNESS. By default, if this varible is OFF which means that the machine endianness is little endianness.

The ucdrBuffer endianness can be set by the endianness parameter of the structure to UCDR_BIG_ENDIANNESS or UCDR_LITTLE_ENDIANNESS. Also, there are a functions that allow to force an endianness independiently of the ucdrBuffer endianness in their serialization/deserialization. These functions contains the name endianness in their signature.

Error

All serialization/deserialization functions return a boolean indicating the result of their operations. When a serialization/deserialization could not be possible (the type can not be serialized, or the capacity of the destination buffer is not enough), an status error is setted into the ucdrBuffer. If a ucdrBuffer has an error state, the next serialization/deserialization operations will not works and will return false in their execution. A buffer marked with an error can be used, but any serialization/deserialization operation over it will not produce any effect.

If is kwown that an operation can fails over a ucdrBuffer, and its necessary to continue with the serialization/deserialization if it happens, the ucdrBuffer state can be saved using the ucdr_copy_buffer function. After the application of the wrong serialization/deserialization, only the ucdrBuffer that performed the operation will have a dirty state.

Serialization/deserialization list

The available modes of serialization/deserializations in Micro CDR are shown in the following table.

Type Endianness
bool
char
int8
uint8
int16
int16 endianness
uint16
uint16 endianness
int32
int32 endianness
uint32
uint32 endianness
int64
int64 endianness
uint64
uint64 endianness
float
float endianness
double
double endianness
string
string endianness
bool array
char array
int8 array
uint8 array
int16 array
int16 array endianness
uint16 array
uint16 array endianness
int32 array
int32 array endianness
uint32 array
uint32 array endianness
int64 array
int64 array endianness
uint64 array
uint64 array endianness
float array
float array endianness
double array
double array endianness
bool sequence
bool sequence endianness
char sequence
char sequence endianness
int8 sequence
int8 sequence endianness
uint8 sequence
uint8 sequence endianness
int16 sequence
int16 sequence endianness
uint16 sequence
uint16 sequence endianness
int32 sequence
int32 sequence endianness
uint32 sequence
uint32 sequence endianness
int64 sequence
int64 sequence endianness
uint64 sequence
uint64 sequence endianness
float sequence
float sequence endianness
double sequence
double sequence endianness

Additional features

Endianness

Micro CDR supports little and big endianness. The configuration can be done by cmake with the cmake __BIG_ENDIAN__ variable. A 0 value implies that the serialization will performed into a little endian machine, and 1 into a big endian machine.

The default endianness serialization can be choosen by setting the endianness parameter of a ucdrBuffer to UCDR_BIG_ENDIANNESS or UCDR_LITTLE_ENDIANNESS. Also, there are a functions that allow to force an endianness in their serialization/deserialization. These functions contains the name endiannness in their signature.

Error

All serialization/deserialization functions return a boolean indicating the result of their operations. When a serialization/deserialization could not be possible (the type can not be serialized, or the capacity of the destination buffer is not enough), an status error is setted into the ucdrBuffer. If a ucdrBuffer has an error state, the next serialization/deserialization operations will not works and will return false in their execution. A buffer marked with an error can be used, but any serialization/deserialization operation over it will not produce any effect.

If is kwown that an operation can fails over a ucdrBuffer, and its necessary to continue with the serialization/deserialization if it happens, the ucdrBuffer state can be saved using the ucdr_copy_buffer function. After the application of the wrong serialization/deserialization, only the ucdrBuffer that performed the operation will have a dirty state.

Full buffer callback

Micro CDR provides a callback that the user can set in order to control the behavior when the ucdrBuffer can not serialize/deserialize anymore because the buffer is full. This allows to create a better management error and/or modify the buffer location of the ucdrBuffer. The last possibility gives the user the capacity to use several small buffers for a big serialization (see the fragmentation example).

Quality Declaration

eProsima Micro CDR claims to be in the Quality Level 1 category based on the guidelines provided by ROS 2. See the Quality Declaration for more details.

micro-cdr's People

Contributors

acuadros95 avatar bkueng avatar borjaouterelo avatar carlosgomezcarrasco avatar dagar avatar gavanderhoorn avatar jamoralp avatar javierih avatar julionce avatar lemunozm avatar pablogs9 avatar peterduerr-sony avatar richiprosima avatar richiware avatar tsc21 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

micro-cdr's Issues

Incomplete comparison of test results with reference data

  1. It looks like in the files ArrayEndianness.cpp, SequenceEndianness.cpp, ArraySerialization.hpp and SequenceSerialization.hpp incorrect use of the std::mecmp() function: the third argument is the number of elements in the array, not the size in bytes (as it should be):
EXPECT_TRUE(0 == std::memcmp(input, output, ARRAY_SIZE)); 
EXPECT_TRUE(0 == std::memcmp(input, output, SEQUENCE_SIZE));
EXPECT_TRUE(0 == std::memcmp(input, output, sequence_size)); 

This incomplete comparison of the actual and reference array may result in missing testing errors.

I propose to change it as follows:

EXPECT_TRUE(0 == std::memcmp(input, output, ARRAY_SIZE * sizeof(input[0]))); 
EXPECT_TRUE(0 == std::memcmp(input, output, SEQUENCE_SIZE * sizeof(input[0])));
EXPECT_TRUE(0 == std::memcmp(input, output, sequence_size * sizeof(input[0]))); 
  1. In test functions, I suggest initializing the elements of the output[] array with the value '0'. This will give determinism to the process of comparing the input[] and output[] arrays.

[feature request] Add 'length' field to MicroBuffer

MicroBuffer constructor/struct doesn't currently have a length field. To copy the buffer content into an interface or streaming protocol, we require the length to be available, in order to fill the payload according to the size. Though the length could be computed using final - init, I consider to be more beneficial to have that available out-of-the-box on the constructor.

set_common_compile_options(..) 'forces' C++ language on

Trying to build Micro-CDR on a platform without (proper) C++ support, I noticed that even though the top-level CMakeLists.txt only enabled C:

project(microcdr VERSION "1.2.0" LANGUAGES C)

it then continues and includes cmake/common/check_configuration.cmake, which does:

function(set_common_compile_options target)
enable_language(C)
enable_language(CXX)

which ends up testing my platform's C++ compiler and fails.

Commenting the enable_language(CXX) makes everything work (the C-side is fine).

Build error: duplicate package names 'Micro-CDR'

Hi! An error occurs when building micro-CDR package.

System

  • Ubuntu 20.04
  • ROS2 Foxy

Steps to reproduce

I am following this tutorial, to install micro_ros_agent on my computer. I am building the micro_CDR package when executing:
ros2 run micro_ros_setup build_agent.sh

Actual behavior

The package micro_CDR is present in both "eProsima" and "eprosima" folders.
I guess than, when following the tutorial and executing ros2 run micro_ros_setup create_agent_ws.sh, the already existing package micro-CDR in folder "eProsima" should be overwritten. But there might be a typo somewhere in the script making a second package micro-CDR being cloned in folder "eprosima".
Complete log is:

[0.237s] ERROR:colcon:colcon build: Duplicate package names not supported:
- microcdr:
  - src/eProsima/Micro-CDR
  - src/eprosima/Micro-CDR

This is a minor issue, I am not sure if it worth its own issue ticket. I am sorry if not.

Temporary fix

In my case, just cutting "eprosima/Micro-CDR" and pasting it in "eProsima" folder solved the problem, and I can run a micro-ROS agent without problem. But I guess it might be a problem for micro-ROS beginners who might want to follow the tutorials.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.