Add a sequence container in OAI
Add a sequence container in OAI. Includes for_each algorithm, doxygen odcumentation, and test using ctest.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
add_subdirectory(alg)
|
||||
add_subdirectory(ds)
|
||||
add_boolean_option(ENABLE_TELNETSRV OFF "Whether to build telnet support in modems" OFF)
|
||||
if(ENABLE_TELNETSRV)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
add_library(alg OBJECT
|
||||
find.c
|
||||
foreach.c
|
||||
)
|
||||
|
||||
target_include_directories(alg PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Mikel Irazabal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "find.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
elm_arr_t find_if_arr_it(seq_arr_t* arr, void* start_it, void* end_it, void* value, bool (*f)(const void*, const void*))
|
||||
{
|
||||
assert(arr != NULL);
|
||||
|
||||
while (start_it != end_it) {
|
||||
if (f(value, start_it))
|
||||
return (elm_arr_t){.found = true, .it = start_it};
|
||||
start_it = seq_arr_next(arr, start_it);
|
||||
}
|
||||
// If I trusted the average developer I should return it=start_it, but I don't.
|
||||
return (elm_arr_t){.found = false, .it = NULL};
|
||||
}
|
||||
|
||||
elm_arr_t find_if_arr(seq_arr_t* arr, void* value, bool (*f)(const void*, const void*))
|
||||
{
|
||||
assert(arr != NULL);
|
||||
void* start_it = seq_arr_front(arr);
|
||||
void* end_it = seq_arr_end(arr);
|
||||
return find_if_arr_it(arr, start_it, end_it, value, f);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Mikel Irazabal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef FIND_ALGORITHM
|
||||
#define FIND_ALGORITHM
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "../ds/seq_arr.h"
|
||||
|
||||
typedef struct {
|
||||
void* it;
|
||||
bool found;
|
||||
} elm_arr_t;
|
||||
|
||||
// Sequencial containers
|
||||
|
||||
/**
|
||||
* @brief Find elements in an array if the predicate is true
|
||||
* @param arr The sequence container
|
||||
* @param value Pointer to the value that will be used by the predicate
|
||||
* @param f Function representing the predicate
|
||||
* @return Whether the predicate was fullfilled and the iterator to the element if true
|
||||
*/
|
||||
elm_arr_t find_if_arr(seq_arr_t* arr, void* value, bool (*f)(const void* value, const void* it));
|
||||
|
||||
/**
|
||||
* @brief Find elements in an array in the semi-open range [start_it, end_it)
|
||||
* @param arr The sequence container
|
||||
* @param start_it Iterator to the first element
|
||||
* @param end_it Iterator to the one past last element
|
||||
* @param value Pointer to the value usied in the predicate
|
||||
* @param f Function representing the predicate
|
||||
* @return Whether the predicate was fullfilled and the iterator to the element if true
|
||||
*/
|
||||
elm_arr_t find_if_arr_it(seq_arr_t* arr, void* start_it, void* end_it, void* value, bool (*f)(const void* value, const void* it));
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Mikel Irazabal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "foreach.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void for_each(seq_arr_t* arr, void* value, void (*f)(void* value, void* it))
|
||||
{
|
||||
assert(arr != NULL);
|
||||
|
||||
void* it = seq_arr_front(arr);
|
||||
void* end = seq_arr_end(arr);
|
||||
while (it != end) {
|
||||
f(value, it);
|
||||
it = seq_arr_next(arr, it);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Mikel Irazabal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef FOR_EACH_ALGORITHM
|
||||
#define FOR_EACH_ALGORITHM
|
||||
|
||||
#include "../ds/seq_arr.h"
|
||||
|
||||
/**
|
||||
* @brief Apply function to each element in the sequence container
|
||||
* @param arr The sequence container
|
||||
* @param value Pointer to the value that will be used by the function applied
|
||||
* @param fn_apply Function called by every element in the sequence container
|
||||
*/
|
||||
void for_each(seq_arr_t* arr, void* value, void (*fn_apply)(void* value, void* it));
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,10 @@
|
||||
add_library(ds OBJECT
|
||||
byte_array.c
|
||||
seq_arr.c
|
||||
)
|
||||
|
||||
target_include_directories(ds PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Mikel Irazabal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "seq_arr.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static const size_t MIN_SIZE = 8;
|
||||
|
||||
static void maybe_expand(seq_arr_t* arr)
|
||||
{
|
||||
if (arr->size + 1 == arr->cap) {
|
||||
arr->data = realloc(arr->data, 2 * arr->cap * arr->elt_size);
|
||||
assert(arr->data != NULL && "realloc failed to allocate memory");
|
||||
arr->cap *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void maybe_shrink(seq_arr_t* arr)
|
||||
{
|
||||
const float occ = (float)arr->size / (float)arr->cap;
|
||||
if (arr->size > MIN_SIZE && occ < 0.25) {
|
||||
assert(arr->cap > MIN_SIZE);
|
||||
seq_arr_t tmp = {.data = NULL, .size = arr->size, .elt_size = arr->elt_size, .cap = arr->cap / 2};
|
||||
tmp.data = calloc(tmp.cap, tmp.cap);
|
||||
assert(tmp.data != NULL && "Memory exhausted");
|
||||
assert(arr->size <= tmp.cap);
|
||||
memcpy(tmp.data, arr->data, arr->size * arr->elt_size);
|
||||
free(arr->data);
|
||||
memcpy(arr, &tmp, sizeof(seq_arr_t));
|
||||
}
|
||||
}
|
||||
|
||||
void seq_arr_init(seq_arr_t* arr, size_t elt_size) //__attribute__(malloc)
|
||||
{
|
||||
assert(arr != NULL);
|
||||
seq_arr_t tmp = {.data = NULL, .size = 0, .elt_size = elt_size, .cap = MIN_SIZE};
|
||||
memcpy(arr, &tmp, sizeof(seq_arr_t));
|
||||
arr->data = calloc(arr->cap, elt_size);
|
||||
assert(arr->data != NULL);
|
||||
}
|
||||
|
||||
void seq_arr_free(seq_arr_t* arr, void (*free_func)(void*))
|
||||
{
|
||||
assert(arr != NULL);
|
||||
assert(arr->data != NULL);
|
||||
|
||||
if (free_func != NULL) {
|
||||
void* start_it = seq_arr_front(arr);
|
||||
void* end_it = seq_arr_end(arr);
|
||||
while (start_it != end_it) {
|
||||
free_func(start_it);
|
||||
start_it = seq_arr_next(arr, start_it);
|
||||
}
|
||||
}
|
||||
|
||||
free(arr->data);
|
||||
}
|
||||
|
||||
void seq_arr_push_back(seq_arr_t* arr, void* data, size_t len)
|
||||
{
|
||||
assert(arr != NULL);
|
||||
assert(arr->data != NULL);
|
||||
// assert(data != NULL);
|
||||
assert(len == arr->elt_size);
|
||||
|
||||
maybe_expand(arr);
|
||||
|
||||
const size_t offset = arr->size * arr->elt_size;
|
||||
memcpy(&arr->data[offset], data, arr->elt_size);
|
||||
arr->size += 1;
|
||||
}
|
||||
|
||||
void seq_arr_erase(seq_arr_t* arr, void* start_it)
|
||||
{
|
||||
// start_it must be in the range of arr->data
|
||||
assert(arr != NULL);
|
||||
assert(start_it != NULL);
|
||||
return seq_arr_erase_deep(arr, start_it, NULL);
|
||||
}
|
||||
|
||||
void seq_arr_erase_deep(seq_arr_t* arr, void* start_it, void (*free_func)(void* it))
|
||||
{
|
||||
// start_it must be in the range of arr->data
|
||||
assert(arr != NULL);
|
||||
assert(start_it != NULL);
|
||||
return seq_arr_erase_it(arr, start_it, seq_arr_next(arr, start_it), free_func);
|
||||
}
|
||||
|
||||
void seq_arr_erase_it(seq_arr_t* arr, void* start_it, void* end_it, void (*free_func)(void* it))
|
||||
{
|
||||
// start_it && end_it must be in the range of arr->data
|
||||
assert(arr != NULL);
|
||||
assert(start_it != NULL);
|
||||
assert(end_it != NULL);
|
||||
assert(end_it >= start_it);
|
||||
|
||||
if (start_it == end_it)
|
||||
return;
|
||||
|
||||
if (free_func != NULL) {
|
||||
void* start_it = seq_arr_front(arr);
|
||||
void* end_it = seq_arr_end(arr);
|
||||
while (start_it != end_it) {
|
||||
free_func(start_it);
|
||||
start_it = seq_arr_next(arr, start_it);
|
||||
}
|
||||
}
|
||||
|
||||
const int num_bytes_move = seq_arr_end(arr) - end_it;
|
||||
assert(num_bytes_move > -1);
|
||||
memmove(start_it, end_it, num_bytes_move);
|
||||
|
||||
const int num_bytes_erase = end_it - start_it;
|
||||
const int32_t num_elm_erase = num_bytes_erase / arr->elt_size;
|
||||
assert(num_elm_erase > 0);
|
||||
arr->size -= num_elm_erase;
|
||||
|
||||
memset(seq_arr_end(arr), 0, num_bytes_erase);
|
||||
|
||||
maybe_shrink(arr);
|
||||
}
|
||||
|
||||
size_t seq_arr_size(seq_arr_t const* arr)
|
||||
{
|
||||
assert(arr != NULL);
|
||||
return arr->size;
|
||||
}
|
||||
|
||||
void* seq_arr_front(seq_arr_t const* arr)
|
||||
{
|
||||
assert(arr != NULL);
|
||||
return arr->data;
|
||||
}
|
||||
|
||||
void* seq_arr_next(seq_arr_t const* arr, void const* it)
|
||||
{
|
||||
assert(arr != NULL);
|
||||
assert(it != NULL);
|
||||
return (uint8_t*)it + arr->elt_size;
|
||||
}
|
||||
|
||||
void* seq_arr_end(seq_arr_t const* arr)
|
||||
{
|
||||
assert(arr != NULL);
|
||||
assert(arr->data != NULL);
|
||||
return &arr->data[arr->size * arr->elt_size];
|
||||
}
|
||||
|
||||
void* seq_arr_at(seq_arr_t const* arr, uint32_t pos)
|
||||
{
|
||||
assert(arr != NULL);
|
||||
assert(arr->data != NULL);
|
||||
assert(pos < arr->size);
|
||||
return arr->data + pos * arr->elt_size;
|
||||
}
|
||||
|
||||
ptrdiff_t seq_arr_dist(seq_arr_t const* arr, void const* first, void const* last)
|
||||
{
|
||||
assert(arr != NULL);
|
||||
assert(first != NULL);
|
||||
assert(last != NULL);
|
||||
const ptrdiff_t pos = (last - first) / arr->elt_size;
|
||||
assert(pos > -1);
|
||||
return pos;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Mikel Irazabal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SEQ_CONTAINER_ARRAY
|
||||
#define SEQ_CONTAINER_ARRAY
|
||||
|
||||
/*
|
||||
* Basic sequence container with a similar API and behaviour to C++ std::vector
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct seq_arr_s {
|
||||
uint8_t* data;
|
||||
size_t size;
|
||||
const size_t elt_size;
|
||||
size_t cap;
|
||||
} seq_arr_t;
|
||||
|
||||
/**
|
||||
* Init a sequence container, similar to a constructor
|
||||
* @brief Constructor.
|
||||
* @param arr The sequence container
|
||||
* @param elm_sz value returned by the sizeof operator of the type that the container will hold e.g., sizeof(int).
|
||||
*/
|
||||
void seq_arr_init(seq_arr_t* arr, size_t elm_sz);
|
||||
|
||||
/**
|
||||
* Free a sequence container, similar to a destructor
|
||||
* @brief Destructor.
|
||||
* @param arr The sequence container
|
||||
* @param free_func Function called for every element while destructing e.g., useful to free memory of deep objects.
|
||||
*/
|
||||
void seq_arr_free(seq_arr_t* arr, void (*free_func)(void* it));
|
||||
|
||||
/**
|
||||
* @brief Push back elements into the sequence container. Value semantic. i.e., the void* data will be shallowly copied in the
|
||||
* array.
|
||||
* @param arr The sequence container
|
||||
* @param data Pointer to the data to be copied
|
||||
* @param elm_sz Size of the element to be copied e.g., sizeof(int)
|
||||
*/
|
||||
void seq_arr_push_back(seq_arr_t* arr, void* data, size_t elm_sz);
|
||||
|
||||
/**
|
||||
* @brief Erase the element pointed by it
|
||||
* @param arr The sequence container
|
||||
* @param it Iterator to the element to erase
|
||||
*/
|
||||
void seq_arr_erase(seq_arr_t*, void* it);
|
||||
|
||||
/**
|
||||
* @brief Erase the element pointed by it and call the f function. Useful to free deep copies
|
||||
* @param arr The sequence container
|
||||
* @param it Iterator to the element to erase
|
||||
* @param free_func Function to call while erasing element
|
||||
*/
|
||||
void seq_arr_erase_deep(seq_arr_t* arr, void* it, void (*free_func)(void* it));
|
||||
|
||||
/**
|
||||
* @brief Erase the elements in the semi-open range [first,last)
|
||||
* @param arr The sequence container
|
||||
* @param first Iterator to the first element to erase
|
||||
* @param last Iterator to the last element. Note that this element will NOT be erased
|
||||
* @param f Function that will be called by every element while erasing. Useful for deep copies. Pass NULL if shallow
|
||||
* erased required
|
||||
*/
|
||||
void seq_arr_erase_it(seq_arr_t* arr, void* first, void* last, void (*free_func)(void* it));
|
||||
|
||||
/**
|
||||
* @brief Elements in the array
|
||||
* @param arr The sequence container
|
||||
* @return The number of elements in the sequence container
|
||||
*/
|
||||
size_t seq_arr_size(seq_arr_t const* arr);
|
||||
|
||||
/////
|
||||
// Iterators
|
||||
/////
|
||||
|
||||
/**
|
||||
* @brief First iterator
|
||||
* @param arr The sequence container
|
||||
* @return The iterator to the first element in the sequence container
|
||||
*/
|
||||
void* seq_arr_front(seq_arr_t const* arr);
|
||||
|
||||
/**
|
||||
* @brief Next iterator
|
||||
* @param arr The sequence container
|
||||
* @param it Iterator to a valid element
|
||||
* @return The iterator to the next element in the sequence container
|
||||
*/
|
||||
void* seq_arr_next(seq_arr_t const* arr, void const* it);
|
||||
|
||||
/**
|
||||
* @brief End iterator
|
||||
* @param arr The sequence container
|
||||
* @return The iterator to one past the last element in the sequence container
|
||||
*/
|
||||
void* seq_arr_end(seq_arr_t const* arr);
|
||||
|
||||
/**
|
||||
* @brief Returns iterator in positions pos
|
||||
* @param arr The sequence container
|
||||
* @param pos The position of the element in the sequence container
|
||||
* @return The iterator to the element
|
||||
*/
|
||||
void* seq_arr_at(seq_arr_t const* arr, uint32_t pos);
|
||||
|
||||
/**
|
||||
* @brief Distance between iterators
|
||||
* @param arr The sequence container
|
||||
* @param first Iterator to first element
|
||||
* @param last Iterator to last element
|
||||
* @return The distance among iterators
|
||||
*/
|
||||
ptrdiff_t seq_arr_dist(seq_arr_t const* arr, void const* first, void const* last);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,4 @@
|
||||
add_executable(test_seq_arr test_seq_array.c)
|
||||
target_link_libraries(test_seq_arr ds alg)
|
||||
add_dependencies(tests test_seq_arr)
|
||||
add_test(NAME test_seq_arr COMMAND test_seq_arr) # no options required
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "../seq_arr.h"
|
||||
#include "../../alg/find.h"
|
||||
#include "../../alg/foreach.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
Example to show seq_arr_t capabilities and usage
|
||||
To compile: gcc test_seq_array.c ../seq_arr.c ../../alg/find.c ../../alg/foreach.c
|
||||
*/
|
||||
|
||||
static bool eq_int(const void* value, const void* it)
|
||||
{
|
||||
const int* v = (const int*)value;
|
||||
const int* i = (const int*)it;
|
||||
return *v == *i;
|
||||
}
|
||||
|
||||
static void sum_elm(void* value, void* it)
|
||||
{
|
||||
int* sum = (int*)value;
|
||||
int* elm = (int*)it;
|
||||
*sum += *elm;
|
||||
}
|
||||
|
||||
static int compar(const void* m0, const void* m1)
|
||||
{
|
||||
int* a = (int*)m0;
|
||||
int* b = (int*)m1;
|
||||
|
||||
if (*a < *b)
|
||||
return -1;
|
||||
|
||||
if (*a == *b)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
seq_arr_t arr = {0};
|
||||
seq_arr_init(&arr, sizeof(int));
|
||||
|
||||
// Insert data and expand
|
||||
for (int i = 0; i < 100; ++i)
|
||||
seq_arr_push_back(&arr, &i, sizeof(int));
|
||||
|
||||
// Check inserted data
|
||||
assert(seq_arr_size(&arr) == 100);
|
||||
assert(*(int*)seq_arr_front(&arr) == 0);
|
||||
assert(*(int*)seq_arr_at(&arr, 25) == 25);
|
||||
|
||||
// Find element in the array
|
||||
int value = 50;
|
||||
elm_arr_t elm = find_if_arr(&arr, &value, eq_int);
|
||||
assert(elm.found == true);
|
||||
// Check
|
||||
assert(*(int*)elm.it == 50);
|
||||
assert(seq_arr_dist(&arr, seq_arr_front(&arr), elm.it) == 50);
|
||||
|
||||
// Apply predicate to all the elements
|
||||
int sum = 0;
|
||||
for_each(&arr, &sum, sum_elm);
|
||||
assert(sum == 4950); // N*(N+1)/2 -> 99*100/2
|
||||
|
||||
// Erase found element in the array
|
||||
seq_arr_erase(&arr, elm.it);
|
||||
// Check
|
||||
assert(seq_arr_size(&arr) == 99);
|
||||
assert(*(int*)seq_arr_at(&arr, 50) == 51);
|
||||
|
||||
// Erase range and force shrink
|
||||
seq_arr_erase_it(&arr, seq_arr_front(&arr), seq_arr_at(&arr, 90), NULL);
|
||||
assert(seq_arr_size(&arr) == 9);
|
||||
assert(*(int*)seq_arr_front(&arr) == 91);
|
||||
|
||||
// Recall that C functions qsort and bsearch, also work
|
||||
int key = 95;
|
||||
void* base = seq_arr_front(&arr);
|
||||
size_t nmemb = seq_arr_size(&arr);
|
||||
size_t size = sizeof(int);
|
||||
|
||||
void* it = bsearch(&key, base, nmemb, size, compar);
|
||||
assert(seq_arr_dist(&arr, seq_arr_front(&arr), it) == 4);
|
||||
|
||||
// Free data structure
|
||||
seq_arr_free(&arr, NULL);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user