Skip to content

Commit

Permalink
Add ring to collections
Browse files Browse the repository at this point in the history
  • Loading branch information
Mallets committed Mar 19, 2024
1 parent 235226f commit be9bf0e
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ if(UNIX OR MSVC)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests")

add_executable(z_data_struct_test ${PROJECT_SOURCE_DIR}/tests/z_data_struct_test.c)
add_executable(z_collections_test ${PROJECT_SOURCE_DIR}/tests/z_collections_test.c)
add_executable(z_endpoint_test ${PROJECT_SOURCE_DIR}/tests/z_endpoint_test.c)
add_executable(z_iobuf_test ${PROJECT_SOURCE_DIR}/tests/z_iobuf_test.c)
add_executable(z_msgcodec_test ${PROJECT_SOURCE_DIR}/tests/z_msgcodec_test.c)
Expand All @@ -343,6 +344,7 @@ if(UNIX OR MSVC)
add_executable(z_perf_rx ${PROJECT_SOURCE_DIR}/tests/z_perf_rx.c)

target_link_libraries(z_data_struct_test ${Libname})
target_link_libraries(z_collections_test ${Libname})
target_link_libraries(z_endpoint_test ${Libname})
target_link_libraries(z_iobuf_test ${Libname})
target_link_libraries(z_msgcodec_test ${Libname})
Expand Down
73 changes: 73 additions & 0 deletions include/zenoh-pico/collections/ring.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// Copyright (c) 2022 ZettaScale Technology
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
//
// Contributors:
// ZettaScale Zenoh Team, <[email protected]>
//
#ifndef ZENOH_PICO_COLLECTIONS_RING_H
#define ZENOH_PICO_COLLECTIONS_RING_H

#include <stddef.h>

Check warning

Code scanning / Cppcheck (reported by Codacy)

Include file: <stddef.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning

Include file: <stddef.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <stdint.h>

Check warning

Code scanning / Cppcheck (reported by Codacy)

Include file: <stdint.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning

Include file: <stdint.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include "zenoh-pico/collections/element.h"

/*-------- Ring Queue --------*/
/**
* A ring queue implemented with a single-linked list.
*
* Members:
* struct _z_ring_t *_head: the head of the single-linked list
* size_t _capacity: The capacity of the ring queue
*/
typedef struct {
size_t _capacity;
size_t _len;
size_t _r_idx;
size_t _w_idx;
void **_val;
} _z_ring_t;

_z_ring_t _z_ring_make(size_t capacity);

void *_z_ring_push(_z_ring_t *r, void *e);
void *_z_ring_push_force(_z_ring_t *r, void *e);
void *_z_ring_pull(_z_ring_t *r);

size_t _z_ring_capacity(const _z_ring_t *r);
size_t _z_ring_len(const _z_ring_t *r);
_Bool _z_ring_is_empty(const _z_ring_t *r);
_Bool _z_ring_is_full(const _z_ring_t *r);

// _z_ring_t *_z_ring_clone(const _z_ring_t *xs, z_element_clone_f d_f);

void _z_ring_clear(_z_ring_t *v, z_element_free_f f);
void _z_ring_free(_z_ring_t **xs, z_element_free_f f_f);

#define _Z_RING_DEFINE(name, type) \

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 2101 with no text in the supplied rule-texts-file Warning

misra violation 2101 with no text in the supplied rule-texts-file

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 20.7 rule Note

MISRA 20.7 rule

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 0.10 rule Note

MISRA 0.10 rule
typedef _z_ring_t name##_ring_t; \
static inline name##_ring_t name##_ring_make(size_t capacity) { return _z_ring_make(capacity); } \
static inline size_t name##_ring_capacity(const name##_ring_t *r) { return _z_ring_capacity(r); } \
static inline size_t name##_ring_len(const name##_ring_t *r) { return _z_ring_len(r); } \
static inline _Bool name##_ring_is_empty(const name##_ring_t *r) { return _z_ring_is_empty(r); } \
static inline _Bool name##_ring_is_full(const name##_ring_t *r) { return _z_ring_is_full(r); } \
static inline type *name##_ring_push(name##_ring_t *r, type *e) { return _z_ring_push(r, (void *)e); } \
static inline type *name##_ring_push_force(name##_ring_t *r, type *e) { return _z_ring_push_force(r, (void *)e); } \
static inline void name##_ring_push_force_drop(name##_ring_t *r, type *e) { \
void *x = _z_ring_push_force(r, (void *)e); \
if (x != NULL) { \
name##_elem_free(&x); \
} \
} \
static inline type *name##_ring_pull(name##_ring_t *r) { return (type *)_z_ring_pull(r); } \
static inline void name##_ring_clear(name##_ring_t *r) { return _z_ring_clear(r, name##_elem_free); } \
static inline void name##_ring_free(name##_ring_t **r) { _z_ring_free(r, name##_elem_free); }

#endif /* ZENOH_PICO_COLLECTIONS_RING_H */
6 changes: 5 additions & 1 deletion include/zenoh-pico/collections/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ size_t _z_str_size(const char *src);
void _z_str_copy(char *dst, const char *src);
void _z_str_n_copy(char *dst, const char *src, size_t size);
_Z_ELEM_DEFINE(_z_str, char, _z_str_size, _z_noop_clear, _z_str_copy)
// _Z_ARRAY_DEFINE(_z_str, char *)

// This is here for reference on why
// the _z_str_array_t was not defined using this macro
// but instead manually as find below
Expand Down Expand Up @@ -73,6 +73,8 @@ typedef struct {
} _z_string_t;

_z_string_t _z_string_make(const char *value);

size_t _z_string_size(const _z_string_t *s);
void _z_string_copy(_z_string_t *dst, const _z_string_t *src);
void _z_string_move(_z_string_t *dst, _z_string_t *src);
void _z_string_move_str(_z_string_t *dst, char *src);
Expand All @@ -81,6 +83,8 @@ void _z_string_free(_z_string_t **s);
void _z_string_reset(_z_string_t *s);
_z_string_t _z_string_from_bytes(const _z_bytes_t *bs);

_Z_ELEM_DEFINE(_z_string, _z_string_t, _z_string_size, _z_string_clear, _z_string_copy)

/*-------- str_array --------*/
/**
* An array of NULL terminated strings.
Expand Down
96 changes: 96 additions & 0 deletions src/collections/ring.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//
// Copyright (c) 2022 ZettaScale Technology
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
//
// Contributors:
// ZettaScale Zenoh Team, <[email protected]>
//
#include "zenoh-pico/collections/ring.h"

#include <assert.h>

Check warning

Code scanning / Cppcheck (reported by Codacy)

Include file: <assert.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning

Include file: <assert.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <stddef.h>

Check warning

Code scanning / Cppcheck (reported by Codacy)

Include file: <stddef.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning

Include file: <stddef.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <string.h>

Check warning

Code scanning / Cppcheck (reported by Codacy)

Include file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning

Include file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

/*-------- ring --------*/
_z_ring_t _z_ring_make(size_t capacity) {

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 804 with no text in the supplied rule-texts-file Warning

misra violation 804 with no text in the supplied rule-texts-file
// We need one more element to differentiate wether the ring is empty or full
capacity += 1;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 10.4 rule Note

MISRA 10.4 rule

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.8 rule Note

MISRA 17.8 rule

_z_ring_t v = {._capacity = capacity, ._r_idx = 0, ._w_idx = 0, ._val = NULL};
if (capacity != 0) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 10.4 rule Note

MISRA 10.4 rule
v._val = (void **)zp_malloc(sizeof(void *) * capacity);
}
if (v._val != NULL) {
memset(v._val, 0, capacity);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.7 rule Note

MISRA 17.7 rule
v._capacity = capacity;
}
return v;
}

size_t _z_ring_capacity(const _z_ring_t *r) { return r->_capacity - 1; }

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 804 with no text in the supplied rule-texts-file Warning

misra violation 804 with no text in the supplied rule-texts-file

size_t _z_ring_len(const _z_ring_t *r) {

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 804 with no text in the supplied rule-texts-file Warning

misra violation 804 with no text in the supplied rule-texts-file
if (r->_w_idx >= r->_r_idx) {
return r->_w_idx - r->_r_idx;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 15.5 rule Note

MISRA 15.5 rule
} else {
return r->_w_idx + (r->_capacity - r->_r_idx);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 15.5 rule Note

MISRA 15.5 rule
}
}

_Bool _z_ring_is_empty(const _z_ring_t *r) { return r->_w_idx == r->_r_idx; }

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 804 with no text in the supplied rule-texts-file Warning

misra violation 804 with no text in the supplied rule-texts-file

_Bool _z_ring_is_full(const _z_ring_t *r) { return _z_ring_len(r) == _z_ring_capacity(r); }

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 804 with no text in the supplied rule-texts-file Warning

misra violation 804 with no text in the supplied rule-texts-file

void *_z_ring_push(_z_ring_t *r, void *e) {

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 804 with no text in the supplied rule-texts-file Warning

misra violation 804 with no text in the supplied rule-texts-file
void *ret = e;
if (!_z_ring_is_full(r)) {
r->_val[r->_w_idx] = e;
r->_w_idx = (r->_w_idx + 1) % r->_capacity;
ret = NULL;
}
return ret;
}

void *_z_ring_push_force(_z_ring_t *r, void *e) {

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 804 with no text in the supplied rule-texts-file Warning

misra violation 804 with no text in the supplied rule-texts-file
void *ret = _z_ring_push(r, e);
if (ret != NULL) {
ret = _z_ring_pull(r);
_z_ring_push(r, e);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.7 rule Note

MISRA 17.7 rule
}
return ret;
}

void *_z_ring_pull(_z_ring_t *r) {

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 804 with no text in the supplied rule-texts-file Warning

misra violation 804 with no text in the supplied rule-texts-file
void *ret = NULL;
if (!_z_ring_is_empty(r)) {
ret = r->_val[r->_r_idx];
r->_val[r->_r_idx] = NULL;
r->_r_idx = (r->_r_idx + 1) % r->_capacity;
}
return ret;
}

void _z_ring_clear(_z_ring_t *r, z_element_free_f free_f) {

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 804 with no text in the supplied rule-texts-file Warning

misra violation 804 with no text in the supplied rule-texts-file
void *e = _z_ring_pull(r);
while (e != NULL) {
free_f(e);
e = _z_ring_pull(r);
}
r->_r_idx = 0;
r->_w_idx = 0;
}

void _z_ring_free(_z_ring_t **r, z_element_free_f free_f) {

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 804 with no text in the supplied rule-texts-file Warning

misra violation 804 with no text in the supplied rule-texts-file
_z_ring_t *ptr = (_z_ring_t *)*r;
if (ptr != NULL) {
_z_ring_clear(ptr, free_f);
zp_free(ptr);
*r = NULL;
}
}
2 changes: 2 additions & 0 deletions src/collections/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ _z_string_t _z_string_make(const char *value) {
return s;
}

size_t _z_string_size(const _z_string_t *s) { return s->len; }

Check warning

Code scanning / Cppcheck (reported by Codacy)

misra violation 804 with no text in the supplied rule-texts-file Warning

misra violation 804 with no text in the supplied rule-texts-file

void _z_string_copy(_z_string_t *dst, const _z_string_t *src) {
if (src->val != NULL) {
dst->val = _z_str_clone(src->val);
Expand Down
115 changes: 115 additions & 0 deletions tests/z_collections_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//
// Copyright (c) 2022 ZettaScale Technology
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
//
// Contributors:
// ZettaScale Zenoh Team, <[email protected]>
//
#include <assert.h>

Check warning

Code scanning / Cppcheck (reported by Codacy)

Include file: <assert.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning test

Include file: <assert.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <stddef.h>

Check warning

Code scanning / Cppcheck (reported by Codacy)

Include file: <stddef.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning test

Include file: <stddef.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <stdio.h>

Check warning

Code scanning / Cppcheck (reported by Codacy)

Include file: <stdio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning test

Include file: <stdio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <stdlib.h>

Check warning

Code scanning / Cppcheck (reported by Codacy)

Include file: <stdlib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning test

Include file: <stdlib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include "zenoh-pico/collections/string.h"
// aa
#include "zenoh-pico/collections/ring.h"

_Z_RING_DEFINE(_z_str, char)

Check warning

Code scanning / Cppcheck (reported by Codacy)

There is an unknown macro here somewhere. Configuration is required. If _Z_RING_DEFINE is a macro then please configure it. Warning test

There is an unknown macro here somewhere. Configuration is required. If _Z_RING_DEFINE is a macro then please configure it.

#undef NDEBUG
#include <assert.h>

Check warning

Code scanning / Cppcheck (reported by Codacy)

Include file: <assert.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. Warning test

Include file: <assert.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

void print_ring(_z_ring_t *r) {
printf("Ring { capacity: %zu, r_idx: %zu, w_idx: %zu, len: %zu }\n", _z_ring_capacity(r), r->_r_idx, r->_w_idx,
_z_ring_len(r));
}

void ring_test(void) {
char *a = "a";
char *b = "b";
char *c = "c";
char *d = "d";

_z_str_ring_t r = _z_str_ring_make(3);
print_ring(&r);
assert(_z_str_ring_is_empty(&r));

// One
_z_str_ring_push(&r, a);
print_ring(&r);
assert(_z_str_ring_len(&r) == 1);

char *s = _z_str_ring_pull(&r);
print_ring(&r);
assert(strcmp(a, s) == 0);
assert(_z_str_ring_is_empty(&r));

s = _z_str_ring_pull(&r);
print_ring(&r);
assert(s == NULL);
assert(_z_str_ring_is_empty(&r));

// Two
s = _z_str_ring_push(&r, a);
print_ring(&r);
assert(s == NULL);
assert(_z_str_ring_len(&r) == 1);

s = _z_str_ring_push(&r, b);
print_ring(&r);
assert(s == NULL);
assert(_z_str_ring_len(&r) == 2);

s = _z_str_ring_push(&r, c);
print_ring(&r);
assert(s == NULL);
assert(_z_str_ring_len(&r) == 3);
assert(_z_str_ring_is_full(&r));

s = _z_str_ring_push(&r, d);
print_ring(&r);
assert(strcmp(d, s) == 0);
assert(_z_str_ring_len(&r) == 3);
assert(_z_str_ring_is_full(&r));

s = _z_str_ring_push_force(&r, d);
print_ring(&r);
assert(strcmp(a, s) == 0);
assert(_z_str_ring_len(&r) == 3);
assert(_z_str_ring_is_full(&r));

s = _z_str_ring_push_force(&r, d);
print_ring(&r);
assert(strcmp(b, s) == 0);
assert(_z_str_ring_len(&r) == 3);
assert(_z_str_ring_is_full(&r));

s = _z_str_ring_push_force(&r, d);
print_ring(&r);
assert(strcmp(c, s) == 0);
assert(_z_str_ring_len(&r) == 3);
assert(_z_str_ring_is_full(&r));

s = _z_str_ring_pull(&r);
print_ring(&r);
assert(strcmp(d, s) == 0);
assert(_z_str_ring_len(&r) == 2);

s = _z_str_ring_pull(&r);
print_ring(&r);
assert(strcmp(d, s) == 0);
assert(_z_str_ring_len(&r) == 1);

s = _z_str_ring_pull(&r);
print_ring(&r);
assert(strcmp(d, s) == 0);
assert(_z_str_ring_is_empty(&r));
}

int main(void) { ring_test(); }

0 comments on commit be9bf0e

Please sign in to comment.