GithubHelp home page GithubHelp logo

leoven / c-macro-collections Goto Github PK

View Code? Open in Web Editor NEW
495.0 16.0 37.0 4.46 MB

Easy to use, modular, header only, macro based, generic and type-safe Data Structures in C

License: MIT License

C 99.75% Makefile 0.20% C++ 0.05%
datastructures datastructure deque hashmap heap linkedlist list queue stack c

c-macro-collections's Introduction

C Macro Collections

C Macro Collections Logo

Easy to use, modular, header only, macro based, generic and type-safe Data Structures in C

LinkToRepo LinkToDocs

License Version travis-ci codecov test_suit

Stars loc loc

Table of Contents

Installation

No installation is required. The entire library is made of header files and can be directly included into your project.

Contributing

There is a lot to be done. You can check the TODO file in the root of the repository or the issues in the github page. Also, tests and documentation are in constant development.

Usage

Below is a minimal example that makes use of some core functionalities. And a lot of explanation too!

// The C Macro Collections takes advantage of headers that can be included
// multiple times. You can check the contents of src/cmc/list.h and there are no
// include guards, meaning they can be included multiple times and this is what
// generates the code.
// Before including it though we need to define a few basic macros. You can
// check the documentation to see which ones are required.
#define V int          // list value data type
#define PFX intl       // list function's prefix
#define SNAME int_list // list struct name (struct int_list)
#define CMC_EXT_STR    // Enables an extra functionality (STR) of the list
#include "cmc/list.h"

// This header file includes a lot of functions that can be used as methods to
// basic data types. In this case, cmc_i32_str is used
#include "cmc/utl/futils.h"

int main(void)
{
    // Our list type is defined by SNAME and all functions are prefixed by PFX
    // (PFX can also be thought as the function's namespace). Also, nodes,
    // entries, iterators and other structures are prefixed by SNAME. So PFX is
    // for functions and SNAME is for structs, where the main one is simply
    // 'struct SNAME'.
    // To initialize a list we need to pass in an initial capacity and something
    // that is called a function table for the V type.
    // This function table is a struct with methods that will extract some
    // (sometimes) necessary behaviour from your custom data type. Things like
    // hash, comparison and printing. A list doesn't require any of these
    // functions. That is, the CORE module doesn't use any of them.
    // But since we are using the STR module, we will need to define the 'str'
    // function. Luckily, for the 'int' type, the library already provides such
    // function (cmc_i32_str), provided by the cmc/utl/futils.h header file.
    struct int_list *list = intl_new(32, &(struct int_list_fval){ .str = cmc_i32_str, NULL });

    // Check if the list was successfully initialized. It could fail if the
    // initial capacity is too big or if 'struct int_list_fval *' is NULL,
    // because every data structure must have a valid function table.
    if (!list)
        return 1;

    // Add some items to the list. The CMC data structures are all dynamically
    // sized. So there can be as many items as you want as long as you have
    // enough memory.
    for (int i = 0; i < 100; i++)
    {
        // Try to add an element to the list. If it fails you can check what
        // caused it by getting its flag.
        if (!intl_push_back(list, i))
        {
            enum cmc_flags flag = intl_flag(list);
            // Use cmc_flags_to_str (global variable) to map the enum error to a
            // string.
            fprintf(stderr, "%s : push_back failed\n", cmc_flags_to_str[flag]);
        }
    }

    // Now we will use the STR module, the _print() function. This is where the
    // '.str' from the function table comes into play. If we haven't defined it,
    // the program would've crashed. We also need to define to which file we
    // will be printing the list's content. In this case, the terminal. Also,
    // some strings need to be defined. They will be printed: before all
    // elements, between each one, and after all elements. This is very useful
    // for debugging.
    intl_print(list, stdout, "[ ", ", ", " ]\n");

    // Free all of its resources
    intl_free(list);
}

Now all you have to do is to compile the source code with -I /path/to/library/src. There is no required installation or pre-compilation.

Features

The C Macro Collections library is organized into many other sub-libraries. The following table is a quick overview.

Library Name Description
CMC Macro Collections The main library with dynamically-sized collections
COR Core Core functionalities used by more than one collection, usually from different sub-libraries
EXT Extensions Extension to collections
SAC Statically Allocated Collections Collections with a fixed sized array that don't use any heap allocation
TSC Thread-Safe Collections Collections that allow multiple operations from multiple threads
UTL Utilities General utilities

Project Structure

  • benchmarks - Where all benchmarks are hosted
  • docs - A folder hosting the generated documentation by mdBook
  • documentation - The markdowns used by mdBook to generate the website
  • examples - Examples using the C Macro Collections Library
  • src - All headers part of the C Macro Collections Library
  • tests - Where all tests are hosted

Available Collections

The following table is an overview of all the currently available or upcoming data structures:

Collection Abstract Data Type Data Structure Details
BitSet
bitset.h
Set Dynamic Array A set of bits that can be individually modified and queried, each identified by a bit index
Deque
deque.h
Double-Ended Queue Dynamic Circular Array A circular array that allows push and pop on both ends (only) at constant time
HashBidiMap
hashbidimap.h
Bidirectional Map Two Hashtables A bijection between two sets of unique keys and unique values K <-> V using two hashtables
HashMap
hashmap.h
Map Flat Hashtable A unique set of keys associated with a value K -> V with constant time look up using a hashtable with open addressing and robin hood hashing
HashMultiMap
hashmultimap.h
Multimap Hashtable A mapping of multiple keys with one node per key using a hashtable with separate chaining
HashMultiSet
hashmultiset.h
Multiset Flat Hashtable A mapping of a value and its multiplicity using a hashtable with open addressing and robin hood hashing
HashSet
hashset.h
Set Flat Hashtable A unique set of values with constant time look up using a hashtable with open addressing and robin hood hashing
Heap
heap.h
Priority Queue Dynamic Array A binary heap as a dynamic array as an implicit data structure
IntervalHeap
intervalheap.h
Double-Ended Priority Queue Custom Dynamic Array A dynamic array of nodes, each hosting one value from the MinHeap and one from the MaxHeap
LinkedList
linkedlist.h
List Doubly-Linked List A default doubly-linked list
List
list.h
List Dynamic Array A dynamic array with push and pop anywhere on the array
Queue
queue.h
FIFO Dynamic Circular Array A queue using a circular array with enqueue at the back index and dequeue at the front index
SkipList
WIP
Sorted List Skip List A sorted Linked List with average O(log n) search, insertion and deletion complexity
SortedList
sortedlist.h
Sorted List Sorted Dynamic Array A lazily sorted dynamic array that is sorted only when necessary
Stack
stack.h
FILO Dynamic Array A stack with push and pop at the end of a dynamic array
TreeBidiMap
WIP
Sorted Bidirectional Map Two AVL Trees A sorted bijection between two sets of unique keys and unique values K <-> V using two AVL trees
TreeMap
treemap.h
Sorted Map AVL Tree A unique set of keys associated with a value K -> V using an AVL tree with log(n) look up and sorted iteration
TreeMultiMap
WIP
Sorted Multimap AVL Tree A sorted mapping of multiple keys with one node per key using an AVL Tree of linked-lists
TreeMultiSet
WIP
Sorted Multiset AVL Tree A sorted mapping of a value and its multiplicity using an AVL tree
TreeSet
treeset.h
Sorted Set AVL Tree A unique set of keys using an AVL tree with log(n) look up and sorted iteration

Other Features

These are some features within the library that are implemented by all collections.

Two-way iterators

All collections come with a two-way iterator. You can go back and forwards in constant time and access elements in constant time.

Custom Allocation

All collections have a cmc_alloc_node which provides pointers to the four dynamic memory allocation functions in C: malloc, calloc, realloc and free. These pointers can be customized for each individual collection created or a default can be used, as specified in cmc_alloc_node_default.

Callbacks

Every function that operates on a collection can be separated in 5 different types. Create, Read, Update, Delete and (an extra one besides CRUD) Resize. You can define one callback function for each operation. Check out the documentation to see when each callback function is called.

Functions Table

Functions table is a struct of function pointers containing 'methods' for a custom data type. Some methods are optional and others are needed in order for a collection to operate. They are:

CMP

A comparator function is used in sorted collections or when an equality is being checked like when trying to find a certain element in a list. It is responsible for taking two arguments of the same data type and comparing them. The return value is an int with the following definitions:

  • Return 1 if the first argument is greater than the second;
  • Return 0 if the first argument equals the second;
  • Return -1 if the first argument is less than the second.

CPY

A copy function is used when a collection is being copied. It can be used to make a deep copy of of your custom data type. It must take a single parameter and return a new copy of that same data type. If this function is absent (NULL) the data type will be copied by assignment (for pointers this is a shallow copy).

STR

A string function is responsible for taking a FILE pointer and a custom data type and outputting the string representation of that data returning a bool indication success or failure. It is useful for debugging.

FREE

The free function is called when a collection is cleared (all elements removed) or freed (all elements removed and freed from memory) and it is responsible for completely freeing all resources that are usually acquired by your data type.

HASH

This function receives a custom data type as parameter and returns a size_t hash of that data. Used in hashtables.

PRI

A priority function works much like the comparator function except that it compares the priority between two elements. It is used in collections whose structure is based on the priority of elements and not in their general comparison.

  • Return 1 if the first argument has a greater priority than the second;
  • Return 0 if the first argument has the same priority as second;
  • Return -1 if the first argument has a lower priority than the second.

The following table shows which functions are required, optional or never used for each Collection:

Collection CMP CPY STR FREE HASH PRI
BitSet #2ef625 #2ef625 #2ef625 #2ef625 #2ef625 #2ef625
Deque #9f3b94 #9f3b94 #497edd #00d3eb #2ef625 #2ef625
HashMap #b82b28 #9f3b94 #497edd #00d3eb #b82b28 #2ef625
HashBidiMap #b82b28 #9f3b94 #497edd #00d3eb #b82b28 #2ef625
HashMultiMap #b82b28 #9f3b94 #497edd #00d3eb #b82b28 #2ef625
HashMultiSet #b82b28 #9f3b94 #497edd #00d3eb #b82b28 #2ef625
HashSet #b82b28 #9f3b94 #497edd #00d3eb #b82b28 #2ef625
Heap #9f3b94 #9f3b94 #497edd #00d3eb #2ef625 #b82b28
IntervalHeap #9f3b94 #9f3b94 #497edd #00d3eb #2ef625 #b82b28
List #9f3b94 #9f3b94 #497edd #00d3eb #2ef625 #2ef625
LinkedList #9f3b94 #9f3b94 #497edd #00d3eb #2ef625 #2ef625
Queue #9f3b94 #9f3b94 #497edd #00d3eb #2ef625 #2ef625
SortedList #b82b28 #9f3b94 #497edd #00d3eb #2ef625 #2ef625
Stack #9f3b94 #9f3b94 #497edd #00d3eb #2ef625 #2ef625
TreeMap #b82b28 #9f3b94 #497edd #00d3eb #2ef625 #2ef625
TreeSet #b82b28 #9f3b94 #497edd #00d3eb #2ef625 #2ef625
Color Label
#b82b28 Required for basic functionality.
#9f3b94 Required for specific functions.
#497edd Required for non-core specific functions.
#00d3eb Optional.
#2ef625 Not Used.

Design Decisions

Stack vs Heap Allocation

Currently all collections need to be allocated on the heap. Iterators have both options but it is encouraged to allocate them on the stack since they don't require dynamic memory.

Some collections overlap others in terms of functionality

Yes, you can use a Deque as a Queue or a List as a Stack without any major cost, but the idea is to have the least amount of code to fulfill the needs of a collection.

Take for example the Stack. It is simple, small and doesn't have many functions. If you generate a List to be used (only) as a Stack (which is one of the bulkiest collections) you'll end up with a lot of code generated and compiled for nothing.

The Deque versus Queue situation is a little less problematic, but again, you need to be careful when generating a lot of code as compilation times might go up to 15 seconds even with modern ultra-fast compilers.

Another example is using a HashMap/TreeMap as a HashSet/TreeSet (with a dummy value that is never used), but I just think that this is a bad thing to do and you would be wasting some memory. Also, the sets generate a lot of code related to set theory, whereas maps don't.

But what about the LinkedList ?

You can use them as Stacks, Queues and Deques, but with modern memory hierarchy models, array-based data structures have a significantly faster runtime due to caching, so I didn't bother to have specific implementations of those aforementioned collections.

You can't structurally modify a collection when iterating over it

Modifying a collection will possibly invalidate all iterators currently initialized by it. Currently, the only collection that allows this is the LinkedList (using the node-based functions, not the iterator).

Special Macros

  • CMC_NO_ALLOC - disables "cor/alloc.h", useful for statically allocated collections (SAC)
  • CMC_NO_IMPORTS - disables all imports from the standard library at "cor/core.h"

c-macro-collections's People

Contributors

leoven avatar pxeger avatar timgates42 avatar tryexceptelse 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  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  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  avatar  avatar  avatar  avatar  avatar

c-macro-collections's Issues

Many examples are outdated

This library is constantly receiving new updates that are disruptive and I believe that by now all examples no longer compile. This will eventually be fixed but only when all collections have the functions in the scope defined by the TODO file and the unit tests are complete.

Export symbols for windows

Feature Request Template

What is the nature of this request?

  • New functionalities

Is your feature request related to a problem? Please describe.

Compiling on windows/mingw requires each symbol to be exported, with something like __declspec(dllexport), libraries usually have something like this, example from PHYSFS

#if defined(PHYSFS_DECL)
/* do nothing. */
#elif defined(PHYSFS_STATIC)
#define PHYSFS_DECL   /**/
#elif defined(_WIN32) || defined(__OS2__)
#define PHYSFS_DECL __declspec(dllexport)
#elif defined(__SUNPRO_C)
#define PHYSFS_DECL __global
#elif ((__GNUC__ >= 3) && (!defined(__EMX__)) && (!defined(sun)))
#define PHYSFS_DECL __attribute__((visibility("default")))
#else
#define PHYSFS_DECL
#endif

or at least expose a LIB_DECL, which can be defined by the consumer

Describe the solution you'd like

prefix every function declaration on header.h with CMC_DECL, and have something like the above example on core.h

Tracking: DEV

  • Bitset
  • Deque
  • HashBidiMap
  • HashMap
  • HashMultiMap
  • HashMultiSet
  • HashSet
  • Heap
  • IntervalHeap
  • LinkedList
  • List
  • Queue
  • SkipList
  • SortedList
  • Stack
  • TreeBidiMap
  • TreeMap
  • TreeMultiMap
  • TreeMultiSet
  • TreeSet

Overflow warnings in utl_futils.h

Overflow warnings in utl_futils.h

Describe the bug

Compiling the utl_futils.h header on a 32bit Cortex M0 ARM gives overflow warnings for hash math, since 64bit integer math is apparently not supported.

How to Reproduce

Steps to reproduce the behavior:

  1. Setup a cross-compiling environment for a ARM M0 Cortex (i.e Raspberry Pi Pico)
  2. compile the main example.c
  3. See the warnings

Expected behavior

Somehow this 64bit math should not be included in this case.

Screenshots

[build] [1/2  50% :: 0.097] Building C object console/CMakeFiles/console.dir/console.c.obj
[build] /home/rafa/repos/own/pico/pico-lipophot4c/src/lib/C-Macro-Collections/include/c_macro_collections/utl_futils.h: In function 'cmc_str_hash_java':
[build] /home/rafa/repos/own/pico/pico-lipophot4c/src/lib/C-Macro-Collections/include/c_macro_collections/utl_futils.h:413:28: warning: conversion from 'long long unsigned int' to 'size_t' {aka 'unsigned int'} changes value from '1125899906842597' to '4294967269' [-Woverflow]
[build]   413 |     size_t hash = UINT64_C(1125899906842597); // prime
[build]       |                            ^~~~~~~~~~~~~~~~
[build] In file included from /home/rafa/repos/own/pico/pico-lipophot4c/src/console/console.c:16:
[build] /home/rafa/repos/own/pico/pico-lipophot4c/src/lib/C-Macro-Collections/include/c_macro_collections/utl_futils.h: In function 'cmc_str_hash_murmur3':
[build] /home/rafa/repos/own/pico/pico-lipophot4c/src/lib/C-Macro-Collections/include/c_macro_collections/utl_futils.h:428:13: warning: right shift count >= width of type [-Wshift-count-overflow]
[build]   428 |     x ^= (x >> 33);
[build]       |             ^~
[build] /home/rafa/repos/own/pico/pico-lipophot4c/src/lib/C-Macro-Collections/include/c_macro_collections/utl_futils.h:430:13: warning: right shift count >= width of type [-Wshift-count-overflow]
[build]   430 |     x ^= (x >> 33);
[build]       |             ^~
[build] /home/rafa/repos/own/pico/pico-lipophot4c/src/lib/C-Macro-Collections/include/c_macro_collections/utl_futils.h:432:13: warning: right shift count >= width of type [-Wshift-count-overflow]
[build]   432 |     x ^= (x >> 33);
[build]       |             ^~
[build] /home/rafa/repos/own/pico/pico-lipophot4c/src/lib/C-Macro-Collections/include/c_macro_collections/utl_futils.h: In function 'cmc_str_hash_murmur3_variant':
[build] /home/rafa/repos/own/pico/pico-lipophot4c/src/lib/C-Macro-Collections/include/c_macro_collections/utl_futils.h:447:13: warning: right shift count >= width of type [-Wshift-count-overflow]
[build]   447 |     x ^= (x >> 33);
[build]       |             ^~
[build] /home/rafa/repos/own/pico/pico-lipophot4c/src/console/console.c: In function 'console_init':
[build] /home/rafa/repos/own/pico/pico-lipophot4c/src/console/console.c:52:80: warning: initialization of '_Bool (*)(FILE *, int)' from incompatible pointer type '_Bool (*)(FILE *, int32_t)' {aka '_Bool (*)(FILE *, long int)'} [-Wincompatible-pointer-types]
[build]    52 |     struct int_list *list = intl_new_custom(32, &(struct int_list_fval){.str = cmc_i32_str, NULL}, &custom_allocator, NULL);

Please complete the following information:

  • Type: [e.g. src, tests, examples, benchmarks]
  • OS: linux, cross development for raspberry pi pico
  • Compiler GCC
  • Compiler Version 10.3.1 arm-none-eabi

Additional context

Tracking: EXT

INIT

  • Bitset
  • Deque
  • HashBidiMap
  • HashMap
  • HashMultiMap
  • HashMultiSet
  • HashSet
  • Heap
  • IntervalHeap
  • LinkedList
  • List
  • Queue
  • SkipList
  • SortedList
  • Stack
  • TreeBidiMap
  • TreeMap
  • TreeMultiMap
  • TreeMultiSet
  • TreeSet

ITER

  • Bitset
  • Deque
  • HashBidiMap
  • HashMap
  • HashMultiMap
  • HashMultiSet
  • HashSet
  • Heap
  • IntervalHeap
  • LinkedList
  • List
  • Queue
  • SkipList
  • SortedList
  • Stack
  • TreeBidiMap
  • TreeMap
  • TreeMultiMap
  • TreeMultiSet
  • TreeSet

STR

  • Bitset
  • Deque
  • HashBidiMap
  • HashMap
  • HashMultiMap
  • HashMultiSet
  • HashSet
  • Heap
  • IntervalHeap
  • LinkedList
  • List
  • Queue
  • SkipList
  • SortedList
  • Stack
  • TreeBidiMap
  • TreeMap
  • TreeMultiMap
  • TreeMultiSet
  • TreeSet

Do something with cmc_string

cmc_string is used by to_string functions and it is currently not ideal. How to replace it?

  • Allocate a char *
  • Print it straight to a FILE *

Function tables shouldn't be required

The library should:

  • Allow fkey and fval parameters to be null
  • Check in _new() for required functions
  • Check if the struct and if the functions are null before every usage and report errors instead of crashing

list.h - a couple of issues

Line 299, I think it should be
memmove(list->buffer, list->buffer + 1, (list->count - 1) * sizeof(V));

Line 311, I think it should be
memmove(list->buffer + index, list->buffer + index + 1, (list->count - index - 1) * sizeof(V));

I also suggest calling PFX##_pop_at(list, 0) inside PFX##_pop_front.
Also, all of the pop functions should be calling deallocators

Do not include code by default

Thanks for working on C-Macro-Collections!

What is the nature of this request?

  • Change in standards

Is your feature request related to a problem? Please describe.

you can easily make a new list with

#define V struct my_struct
#define PFX my_struct
#define SNAME my_struct_list
#include <cmc/ds/list.h>

since cmc/ds/list.h includes the #include "cmc/list/code.h", you can't just place the above snippet on a header, because it would define each function multiple times.

In order to share declarations, you need to do something like this

file.c

#define V struct my_struct
#define PFX my_struct
#define SNAME my_struct_list
#include <ds/cmc/list/code.h>
#include <ds/cor/undef.h>

file.h

#define V struct my_struct
#define PFX my_struct
#define SNAME my_struct_list
#include <ds/cmc/list/struct.h>
#include <ds/cmc/list/header.h>
#include <ds/cor/undef.h>

Describe the solution you'd like

I think it would be much better if we could do this

file.c

#define V struct my_struct
#define PFX my_struct
#define SNAME my_struct_list
#include <ds/cmc/list/code.h>
// code includes undef.h

file.h

#define V struct my_struct
#define PFX my_struct
#define SNAME my_struct_list
#include <ds/cmc/list.h>

What do you think? It would be a breaking change, I can open a PR if you agree it's a good change.

Alternatves

Maybe this? I prefer the above
file.c

#define V struct my_struct
#define PFX my_struct
#define SNAME my_struct_list
#define SOURCE
#include <ds/cmc/list.h>

file.h

#define V struct my_struct
#define PFX my_struct
#define SNAME my_struct_list
#include <ds/cmc/list.h>

CMC_IMPL_XXXX

  • Allows to switch between hash based and tree based data structures (e.g. AVL vs RBT, Round Robin vs Hopscotch, etc)

Callbacks should be more powerfull

  • Called in every function, passing down a few parameters like the first one e.g. self or _list_ and the function name
  • Called at the end and at the start, where both can be toggled separately
  • Continue to be optional to not incur performance overhead

Merge cmc and ext

At this point of the project if feels like the ext collections are growing quite big and the idea of having half of the collections in one folder and the other half in another is quite unnecessary. So eventually merge all collections into the cmc folder and leave dev and sac.

Tracking: CMC

Basic implementation and tests

  • Bitset
  • Deque
  • HashBidiMap
  • HashMap
  • HashMultiMap
  • HashMultiSet
  • HashSet
  • Heap
  • IntervalHeap
  • LinkedList
  • List
  • Queue
  • SkipList
  • SortedList
  • Stack
  • TreeBidiMap
  • TreeMap
  • TreeMultiMap
  • TreeMultiSet
  • TreeSet

cmc_collection base data type

struct cmc_collection {
    enum cmc_collection_type type; // DEQUE, HASHMAP, LIST, STACK, etc
    const char *key_type;
    const char *val_type;
};

A cmc_collection is the common interface to all data structures so that you can differentiate them when storing them on void pointers

Bitset implementation needs used_bits field

Currently, bitset always uses a power of 2 size. If you want to only use 100 bits, all operations are based on 128 and might be incorrect. Operations on the last word must always be checked if all of its bits are being used.

Move everything out of src/cmc folder

Thanks for working on C-Macro-Collections!

What is the nature of this request?

  • Change in source code details (names of variables, functions, parameters, etc)

Is your feature request related to a problem? Please describe.

I think it would be less typing if we moved everything out of cmc folder. We could then avoid adding a bunch of -I flags on our build systems. It's also pointless to have a src/ folder, since there's no include/ folder.

Describe the solution you'd like

Remove the src folder, and remove the cmc/cmc/ folder, moving everything inside of it out one level.
Instead of

src/
   cmc/
       cor/
       cmc/
          list/
            code.h
       list.h

Do something like

cmc/
   cor/
   list/
     code.h
   list.h

We would then do something like -I.

and include like this

#include <cmc/list.h>
#include <cmc/list/code.h>

CMC_EXT_INIT should be there by default

Feature Request Template

What is the nature of this request?

  • Change in standards

Is your feature request related to a problem? Please describe.

CMC_EXT_INIT just adds two new functions, they should be there by default and save everyone the hassle. Unused functions can be easily stripped from release builds.

Describe the solution you'd like

remove CMC_EXT_INIT, have _init functions by default.

Include file with only macro collection declarations

Feature Request Template

What is the nature of this request?

  • Restructure the main library include file to selective include only what you need

Is your feature request related to a problem? Please describe.

Trying to use this library in a 32bit Cortex M0 microcontroller. Including macro_collections.h is overkill and gives compile error for stuff that I don't even need (multithreading, etc.)

Describe the solution you'd like

I have produced a simple header file - for instance, macro_defs.h - where only the global macros are defined. Then it is just a matter of including the needed header files in your code, like:

#include "cmc_list.h"
#include "ext_cmc_list.h"
#include "utl_futils.h"
#include "macro_defs.h"

The existing macro_collections.h can include this file as the very last and we have the same functionality as before

Remove ext/ folder, use macros instead

Feature Request Template

What is the nature of this request?

  • Change in standards

Is your feature request related to a problem? Please describe.

I always use CMC_EXT_INIT. So I generate a collection like this

#define V struct timeline
#define PFX timeline_list
#define SNAME timeline_list
#define CMC_EXT_INIT
#include <lib/ds/list/code.h>
#include <lib/ds/list/ext/code.h>
#include <lib/ds/cor/undef.h>

which is very verbose, I also need a copy of this on the header in order to share declarations.

Describe the solution you'd like

Ditch the ext/ folder, e.gĀ· merge everything inside list/ext/code.h into list/code.h, list/header.h etc... and activate the feature with a macro. Like this

#define V struct timeline
#define PFX timeline_list
#define SNAME timeline_list
#define CMC_EXT_INIT
#include <lib/ds/list/code.h>
#include <lib/ds/cor/undef.h>

What is worth being an extension or included by default is another discussion, but for this particular case of CMC_EXT_INIT #37

Tracking: SAC

  • Bitset
  • Deque
  • HashBidiMap
  • HashMap
  • HashMultiMap
  • HashMultiSet
  • HashSet
  • Heap
  • IntervalHeap
  • LinkedList
  • List
  • Queue
  • SkipList
  • SortedList
  • Stack
  • TreeBidiMap
  • TreeMap
  • TreeMultiMap
  • TreeMultiSet
  • TreeSet

Use const when possible

Thanks for working on CMC!

What is the nature of this request?

  • Change in source code details (names of variables, functions, parameters, etc)

Is your feature request related to a problem? Please describe.

some functions do not modify the collection, like the _count functions, these should have the collection parameter marked as const

Describe the solution you'd like

functions like _count, _get (except for sorted lists), _index_of, _contains should have the collection marked as const

Not a breaking change as C auto casts to const

Pre-hashed key for hashed data structures

Feature Request Template

What is the nature of this request?

  • New functionalities

Is your feature request related to a problem? Please describe.

I have a localization system, I compile a human-readable format into a binary one, and load each string into a hashmap depending on the selected language. Since I know each string key ahead of time, I could hash them offline, and increase performance when loading new strings.

Describe the solution you'd like

A way to insert an already hashed Key into a hashmap/hashset

SAC and allocation shouldn't co-exist

CMC_SAC makes a collection to have a fixed buffer size, possibly avoiding allocations, but the _new() function allocates the struct anyway. This can be good if the buffer size is huge and wouldn't fit on the stack.

  • Find a way to avoid having malloc, free, etc. in the code whe CMC_SAC is defined
  • Decide what to do with _new() and _init()

Look into __VA_OPT__ for C23

Feature Request

What is the nature of this request?

  • Change in source code details (names of variables, functions, parameters, etc)

Is your feature request related to a problem? Please describe.

cmc log functions from log.h, cmc_log_trace for example, are defined as:

#define cmc_log_trace(fmt, ...) cmc_log(CMC_LOG_TRACE, __FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__)

##__VA_ARGS__ is supported by most compilers, but still non-standard, -pedantic issues a warning about it.

C23 solves the problem by introducing the __VA_OPT__ preprocessor. So this is the C23 solution:

#define cmc_log_trace(fmt, ...) cmc_log(CMC_LOG_TRACE, __FILE__, __func__, __LINE__, fmt __VA_OPT__(,)  __VA_ARGS__)

Full C23 support is yet to be available, so not a high priority.

Describe the solution you'd like

Detect the version via __STDC_VERSION__, and use the standard solution if C23 or later.

add function which returns pointer to added element

Feature Request Template

What is the nature of this request?

  • New functionalities

Is your feature request related to a problem? Please describe.

Currently, if you want to add an element then get it's reference, you need to first call _push_back, then _get_ref(_count(list) - 1), _back returns a copy, so we can't use that. This is quite verbose.

Describe the solution you'd like

it would be useful if we had an _push_back_ref, function, which is like _push_back, but it returns the pointer instead of a bool.

Maybe a _back_ref

Not sure if expanding the API surface is worth it, but it might be worth considering.

Compiling without CMC_CALLBACKS support generates warning

Bug Report template

Describe the bug

Compiling without CMC_CALLBACKS support, generates the following warning with -pedantic:

In file included from /cmc/list.h:84:
/cmc/list/struct.h:43:20: warning: extra ';' inside a struct [-Wextra-semi]
        CMC_CALLBACKS_DECL;

Without CMC_CALLBACKS, CMC_CALLBACKS_DECL is expanded to nothing, so CMC_CALLBACKS_DECL; indeed produces a stray semicolon,

Expected behavior

Perhaps suppress the warning somehow with #pragmas, or something like this

struct {
...
#ifdef CMC_CALLBACKS
     cmc_callback callbacks:
#endif
}

If PFX not set, assume PFX=SNAME

Feature Request Template

What is the nature of this request?

  • New functionalities

Is your feature request related to a problem? Please describe.

I think SNAME, the name of the collection, is a reasonable PFX. So maybe if PFX is not set, we could assume SNAME=PFX?

Describe the solution you'd like

#ifndef PFX
#define PFX SNAME
#endif // PFX

HashBidiMap iterators

HashBidiMap iterators are still not implemented properly. Currently you can only iterate over the keys. Decide whether:

  • One iterator containing both IterKey and IterVal
  • Separate iterators for IterKey and IterVal*

See which approach is most compatible with CMC_FOREACH and have a similar look to the other iterators.

list.h should have a sort function

What is the nature of this request?

  • New functionalities

Is your feature request related to a problem? Please describe.

I'm working with sprites on a game. I'll create, destroy and loop the sprites over the frame a bunch of times, and sort them only at the end, before rendering. SortedList is not suited for this since it might sort the list automatically unnecessarily. I would much rather have a list.h and manually sort at the appropriate time.

Describe the solution you'd like

have a sort function for list.h

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.