Commit afe2594a authored by Beniamino Galvani's avatar Beniamino Galvani

Squashed 'shared/c-list/' content from commit 317aa1c65

git-subtree-dir: shared/c-list
git-subtree-split: 317aa1c65743ff528a27542f6785d29a05cc6e0c
parents
#!/bin/bash
set -e
rm -Rf "./ci-build"
mkdir "./ci-build"
cd "./ci-build"
${CHERRY_LIB_MESONSETUP} . "${CHERRY_LIB_SRCDIR}"
${CHERRY_LIB_NINJABUILD}
${CHERRY_LIB_MESONTEST}
(( ! CHERRY_LIB_VALGRIND )) || ${CHERRY_LIB_MESONTEST} "--wrapper=${CHERRY_LIB_VALGRINDWRAP}"
root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
[*.{c,h}]
indent_style = space
indent_size = 8
os: linux
dist: trusty
language: c
services:
- docker
install:
- curl -O -L "https://raw.githubusercontent.com/cherry-pick/cherry-images/v1/scripts/vmrun"
- curl -O -L "https://raw.githubusercontent.com/cherry-pick/cherry-ci/v1/scripts/cherryci"
- chmod +x "./vmrun" "./cherryci"
jobs:
include:
- stage: test
script:
- ./vmrun -- ../src/cherryci -d ../src/.cherryci -s c-util -m
- script:
- ./vmrun -T armv7hl -- ../src/cherryci -d ../src/.cherryci -s c-util
- script:
- ./vmrun -T i686 -- ../src/cherryci -d ../src/.cherryci -s c-util
LICENSE:
This project is dual-licensed under both the Apache License, Version
2.0, and the GNU Lesser General Public License, Version 2.1+.
LICENSE-APACHE:
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
LICENSE-LGPL
This program 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 program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; If not, see <http://www.gnu.org/licenses/>.
COPYRIGHT: (ordered alphabetically)
Copyright (C) 2015-2018 Red Hat, Inc.
AUTHORS: (ordered alphabetically)
David Herrmann <dh.herrmann@gmail.com>
Thomas Haller <thaller@redhat.com>
Tom Gundersen <teg@jklm.no>
This diff is collapsed.
This diff is collapsed.
c-list - Circular Intrusive Double Linked List Collection in ISO-C11
CHANGES WITH 3:
* API break: The c_list_loop_*() symbols were removed, since we saw
little use for them. No user was known at the time, so
all projects should build with the new API version
unchanged.
Since c-list does not distribute any compiled code, there
is no ABI issue with this change.
* Two new symbols c_list_length() and c_list_contains(). They are meant
for debugging purposes, to easily verify list integrity. Since they
run in O(n) time, they are not recommended for any other use than
debugging.
* New symbol c_list_init() is provided as alternative to the verbose
C_LIST_INIT assignment.
* The c-list API is extended to work well with `const CList` objects.
That is, any read-only accessor function allows constant objects as
input now.
Note that this does not propagate into other members linked in the
list. Using `const` for CList members is of little practical use.
However, it might be of use for its embedding objects, so we now
allow it in the CList API as well.
* The c_list_splice() call now clears the source list, rather than
returning with stale pointers. Technically, this is also an API
break, but unlikely to affect any existing code.
Contributions from: David Herrmann, Thomas Haller
- Berlin, 2017-08-13
CHANGES WITH 2:
* Adjust project-name in build-system to reflect the actual project. The
previous releases incorrectly claimed to be c-rbtree in the build
system.
* Add c_list_swap() that swaps two lists given their head pointers.
* Add c_list_splice() that moves a list.
* Add LGPL2.1+ as license so c-list can be imported into GPL2 projects.
It is now officially dual-licensed.
* As usual a bunch of fixes, additional tests, and documentation
updates.
Contributions from: David Herrmann, Tom Gundersen
- Lund, 2017-05-03
CHANGES WITH 1:
* Initial release of c-list.
* This project provides an implementation of a circular double linked
list in standard ISO-C11. License is ASL-2.0 and the build system
used is `Meson'.
Contributions from: David Herrmann, Tom Gundersen
- Berlin, 2017-03-03
c-list - Circular Intrusive Double Linked List Collection in ISO-C11
ABOUT:
The c-list project implements an intrusive collection based on circular
double linked lists in ISO-C11. It aims for minimal API constraints,
leaving maximum control over the data-structures to the API consumer.
DETAILS:
https://c-util.github.io/c-list
BUG REPORTS:
https://github.com/c-util/c-list/issues
GIT:
git@github.com:c-util/c-list.git
https://github.com/c-util/c-list.git
GITWEB:
https://github.com/c-util/c-list
LICENSE:
Apache Software License 2.0
Lesser General Public License 2.1+
See AUTHORS for details.
REQUIREMENTS:
The requirements for c-list are:
libc (e.g., glibc >= 2.16)
At build-time, the following software is required:
meson >= 0.41
pkg-config >= 0.29
INSTALL:
The meson build-system is used for c-list. Contact upstream
documentation for detailed help. In most situations the following
commands are sufficient to build and install c-list from source:
$ mkdir build
$ cd build
$ meson setup ..
$ ninja
$ meson test
# ninja install
No custom configuration options are available.
project(
'c-list',
'c',
version: '3',
license: 'Apache',
default_options: [
'c_std=c11',
],
)
add_project_arguments('-D_GNU_SOURCE', language: 'c')
mod_pkgconfig = import('pkgconfig')
subdir('src')
This diff is collapsed.
#
# target: libclist.so
# (No .so is built so far, since we are header-only. This might change in the
# future, if we add more complex list helpers.)
#
libclist_dep = declare_dependency(
include_directories: include_directories('.'),
version: meson.project_version(),
)
if not meson.is_subproject()
install_headers('c-list.h')
mod_pkgconfig.generate(
version: meson.project_version(),
name: 'libclist',
filebase: 'libclist',
description: 'Circular Intrusive Double Linked List Collection in ISO-C11',
)
endif
#
# target: test-*
#
test_api = executable('test-api', ['test-api.c'], dependencies: libclist_dep)
test('API Symbol Visibility', test_api)
test_basic = executable('test-basic', ['test-basic.c'], dependencies: libclist_dep)
test('Basic API Behavior', test_basic)
test_embed = executable('test-embed', ['test-embed.c'], dependencies: libclist_dep)
test('Embedded List Nodes', test_embed)
/*
* Tests for Public API
* This test, unlikely the others, is linked against the real, distributed,
* shared library. Its sole purpose is to test for symbol availability.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "c-list.h"
typedef struct {
int id;
CList link;
} Node;
static void test_api(void) {
CList *list_iter, *list_safe, list = C_LIST_INIT(list);
Node *node_iter, *node_safe, node = { .id = 0, .link = C_LIST_INIT(node.link) };
assert(!c_list_entry(NULL, Node, link));
assert(c_list_entry(&node.link, Node, link) == &node);
assert(!c_list_is_linked(&node.link));
assert(c_list_is_empty(&list));
assert(c_list_length(&list) == 0);
assert(c_list_contains(&list, &list));
assert(!c_list_contains(&list, &node.link));
/* basic link / unlink calls */
c_list_link_before(&list, &node.link);
assert(c_list_is_linked(&node.link));
assert(!c_list_is_empty(&list));
assert(c_list_length(&list) == 1);
assert(c_list_contains(&list, &list));
assert(c_list_contains(&list, &node.link));
c_list_unlink_stale(&node.link);
assert(c_list_is_linked(&node.link));
assert(c_list_is_empty(&list));
assert(c_list_length(&list) == 0);
c_list_link_after(&list, &node.link);
assert(c_list_is_linked(&node.link));
assert(!c_list_is_empty(&list));
c_list_unlink(&node.link);
assert(!c_list_is_linked(&node.link));
assert(c_list_is_empty(&list));
/* link / unlink aliases */
c_list_link_front(&list, &node.link);
assert(c_list_is_linked(&node.link));
c_list_unlink(&node.link);
assert(!c_list_is_linked(&node.link));
c_list_link_tail(&list, &node.link);
assert(c_list_is_linked(&node.link));
c_list_unlink(&node.link);
assert(!c_list_is_linked(&node.link));
/* swap / splice list operators */
c_list_swap(&list, &list);
assert(c_list_is_empty(&list));
c_list_splice(&list, &list);
assert(c_list_is_empty(&list));
/* loop macros */
c_list_for_each(list_iter, &list)
assert(list_iter != &list);
c_list_for_each_entry(node_iter, &list, link)
assert(&node_iter->link != &list);
c_list_for_each_safe(list_iter, list_safe, &list)
assert(list_iter != &list);
c_list_for_each_entry_safe(node_iter, node_safe, &list, link)
assert(&node_iter->link != &list);
c_list_for_each_continue(list_iter, &list)
assert(list_iter != &list);
c_list_for_each_entry_continue(node_iter, &list, link)
assert(&node_iter->link != &list);
c_list_for_each_safe_continue(list_iter, list_safe, &list)
assert(list_iter != &list);
c_list_for_each_entry_safe_continue(node_iter, node_safe, &list, link)
assert(&node_iter->link != &list);
c_list_for_each_safe_unlink(list_iter, list_safe, &list)
assert(list_iter != &list);
c_list_for_each_entry_safe_unlink(node_iter, node_safe, &list, link)
assert(&node_iter->link != &list);
/* list accessors */
assert(!c_list_first(&list));
assert(!c_list_last(&list));
assert(!c_list_first_entry(&list, Node, link));
assert(!c_list_last_entry(&list, Node, link));
}
int main(int argc, char **argv) {
test_api();
return 0;
}
/*
* Tests for basic functionality
* This contains basic, deterministic tests for list behavior, API
* functionality, and usage.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "c-list.h"
static void test_iterators(void) {
CList *iter, *safe, a, b, list = C_LIST_INIT(list);
unsigned int i;
assert(!c_list_first(&list));
assert(!c_list_last(&list));
/* link @a and verify iterators see just it */
c_list_link_tail(&list, &a);
assert(c_list_is_linked(&a));
assert(c_list_first(&list) == &a);
assert(c_list_last(&list) == &a);
i = 0;
c_list_for_each(iter, &list) {
assert(iter == &a);
++i;
}
assert(i == 1);
i = 0;
iter = NULL;
c_list_for_each_continue(iter, &list) {
assert(iter == &a);
++i;
}
assert(i == 1);
i = 0;
iter = &a;
c_list_for_each_continue(iter, &list)
++i;
assert(i == 0);
/* link @b as well and verify iterators again */
c_list_link_tail(&list, &b);
assert(c_list_is_linked(&a));
assert(c_list_is_linked(&b));
i = 0;
c_list_for_each(iter, &list) {
assert((i == 0 && iter == &a) ||
(i == 1 && iter == &b));
++i;
}
assert(i == 2);
i = 0;
iter = NULL;
c_list_for_each_continue(iter, &list) {
assert((i == 0 && iter == &a) ||
(i == 1 && iter == &b));
++i;
}
assert(i == 2);
i = 0;
iter = &a;
c_list_for_each_continue(iter, &list) {
assert(iter == &b);
++i;
}
assert(i == 1);
i = 0;
iter = &b;
c_list_for_each_continue(iter, &list)
++i;
assert(i == 0);
/* verify safe-iterator while removing elements */
i = 0;
c_list_for_each_safe(iter, safe, &list) {
assert(iter == &a || iter == &b);
c_list_unlink_stale(iter);
++i;
}
assert(i == 2);
assert(c_list_is_empty(&list));
/* link both and verify *_unlink() iterators */
c_list_link_tail(&list, &a);
c_list_link_tail(&list, &b);
i = 0;
c_list_for_each_safe_unlink(iter, safe, &list) {
assert(iter == &a || iter == &b);
assert(!c_list_is_linked(iter));
++i;
}
assert(i == 2);
assert(c_list_is_empty(&list));
}
static void test_swap(void) {
CList list1 = (CList)C_LIST_INIT(list1);
CList list2 = (CList)C_LIST_INIT(list2);
CList list;
c_list_swap(&list1, &list2);
assert(list1.prev == list1.next && list1.prev == &list1);
assert(list2.prev == list2.next && list2.prev == &list2);
c_list_link_tail(&list1, &list);
assert(c_list_first(&list1) == &list);
assert(c_list_last(&list1) == &list);
assert(list.next = &list1);
assert(list.prev = &list1);
c_list_swap(&list1, &list2);
assert(c_list_first(&list2) == &list);
assert(c_list_last(&list2) == &list);
assert(list.next = &list2);
assert(list.prev = &list2);
assert(list1.prev == list1.next && list1.prev == &list1);
}
static void test_splice(void) {
CList target = (CList)C_LIST_INIT(target);
CList source = (CList)C_LIST_INIT(source);
CList e1, e2;
c_list_link_tail(&source, &e1);
c_list_splice(&target, &source);
assert(c_list_first(&target) == &e1);
assert(c_list_last(&target) == &e1);
source = (CList)C_LIST_INIT(source);
c_list_link_tail(&source, &e2);
c_list_splice(&target, &source);
assert(c_list_first(&target) == &e1);
assert(c_list_last(&target) == &e2);
}
int main(int argc, char **argv) {
test_iterators();
test_swap();
test_splice();
return 0;
}
/*
* Tests for embedded CList members
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "c-list.h"
typedef struct Entry Entry;
struct Entry {
short foo;
CList link;
short bar;
};
static void test_entry(void) {
CList list = C_LIST_INIT(list);
Entry e1 = { .foo = 1 * 7, .bar = 1 * 11 };
Entry e2 = { .foo = 2 * 7, .bar = 2 * 11 };
Entry e3 = { .foo = 3 * 7, .bar = 3 * 11 };
Entry e4 = { .foo = 4 * 7, .bar = 4 * 11 };
Entry *e, *safe;
size_t i;
/* verify c_list_entry() works as expected (even with NULL) */
assert(!c_list_entry(NULL, Entry, link));
assert(&e1 == c_list_entry(&e1.link, Entry, link));
/* verify @list is empty */
assert(!c_list_first_entry(&list, Entry, link));
assert(!c_list_last_entry(&list, Entry, link));
/* link 2 entries and verify list state */
c_list_link_tail(&list, &e1.link);
c_list_link_tail(&list, &e2.link);
assert(c_list_first_entry(&list, Entry, link)->foo == 1 * 7);
assert(c_list_first_entry(&list, Entry, link)->bar == 1 * 11);
assert(c_list_last_entry(&list, Entry, link)->foo == 2 * 7);
assert(c_list_last_entry(&list, Entry, link)->bar == 2 * 11);
i = 0;
c_list_for_each_entry(e, &list, link) {
assert(i != 0 || e == &e1);
assert(i != 1 || e == &e2);
assert(i < 2);
++i;
}
assert(i == 2);
/* link 2 more entries */
c_list_link_tail(&list, &e3.link);
c_list_link_tail(&list, &e4.link);
assert(c_list_first_entry(&list, Entry, link)->foo == 1 * 7);
assert(c_list_first_entry(&list, Entry, link)->bar == 1 * 11);
assert(c_list_last_entry(&list, Entry, link)->foo == 4 * 7);
assert(c_list_last_entry(&list, Entry, link)->bar == 4 * 11);
i = 0;
c_list_for_each_entry(e, &list, link) {
assert(i != 0 || e == &e1);
assert(i != 1 || e == &e2);
assert(i != 2 || e == &e3);
assert(i != 3 || e == &e4);
assert(i < 4);
++i;
}
assert(i == 4);
assert(!c_list_is_empty(&list));
assert(c_list_is_linked(&e1.link));
assert(c_list_is_linked(&e2.link));
assert(c_list_is_linked(&e3.link));
assert(c_list_is_linked(&e4.link));
/* remove via safe iterator */
i = 0;
c_list_for_each_entry_safe(e, safe, &list, link) {
assert(i != 0 || e == &e1);
assert(i != 1 || e == &e2);
assert(i != 2 || e == &e3);
assert(i != 3 || e == &e4);
assert(i < 4);
++i;
c_list_unlink(&e->link);
}
assert(i == 4);
assert(c_list_is_empty(&list));
assert(!c_list_is_linked(&e1.link));
assert(!c_list_is_linked(&e2.link));
assert(!c_list_is_linked(&e3.link));
assert(!c_list_is_linked(&e4.link));
}
int main(int argc, char **argv) {
test_entry();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment