Added to_string methods to cmc, ./utl/cmc_string.h, fixed some variable names and fixed includes

This commit is contained in:
Leonardo committed 2019-07-16 23:55:30 -03:00
1 parent f8f704f432
commit 38620ba457
12 files changed
+523 -175

No files matched your search

+36 -4
View File
@@ -8,16 +8,34 @@
*
*/
/*****************************************************************************/
/********************************************************************* DEQUE */
/*****************************************************************************/
/**
* Deque
*
* A Deque (double-ended queue) is a linear data structure that is able to add
* or remove elements from both ends. It can also be thought of a double-ended
* stack since you can push and pop elements from two ends. The Deque can also
* be used as a Queue.
*
* There is no random access for a Deque. The only elements accessible are the
* front element and the back.
*
* Implementation
*
* This implementation uses a circular buffer (ring buffer or cyclic buffer) in
* order to operate on O(1) for push and pop on either ends (only case where it
* takes longer than O(1) is when the buffer is reallocated). If it was
* implemented as a regular array, adding or removing elements from the front
* would take O(N) due to the need to shift all elements in the deque.
*/
#ifndef CMC_DEQUE_H
#define CMC_DEQUE_H
#include <stdlib.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#define DEQUE_GENERATE(PFX, SNAME, FMOD, V) \
DEQUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -102,6 +120,8 @@
FMOD bool PFX##_full(SNAME *_deque_); \
FMOD size_t PFX##_count(SNAME *_deque_); \
FMOD size_t PFX##_capacity(SNAME *_deque_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_deque_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
@@ -327,6 +347,18 @@
return _deque_->capacity; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_deque_) \
{ \
cmc_string str; \
SNAME *d_ = _deque_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_deque, \
name, d_, d_->buffer, d_->capacity, d_->count, d_->front, d_->back); \
\
return str; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
+19 -1
View File
@@ -9,6 +9,8 @@
*/
/**
* HashMap
*
* A HashMap is an implementation of a Map with unique keys, where every key is
* mapped to a value. The keys are not sorted. It is implemented as a hashtable
* with robin hood hashing.
@@ -17,9 +19,11 @@
#ifndef CMC_HASHMAP_H
#define CMC_HASHMAP_H
#include <stdlib.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#ifndef CMC_HASH_TABLE_SETUP
#define CMC_HASH_TABLE_SETUP
@@ -171,6 +175,8 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
FMOD bool PFX##_empty(SNAME *_map_); \
FMOD size_t PFX##_count(SNAME *_map_); \
FMOD size_t PFX##_capacity(SNAME *_map_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_map_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
@@ -462,6 +468,18 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
return _map_->capacity; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_map_) \
{ \
cmc_string str; \
SNAME *m_ = _map_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_hashmap, \
name, m_, m_->buffer, m_->capacity, m_->count, m_->load, m_->cmp, m_->hash); \
\
return str; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
+19 -1
View File
@@ -9,6 +9,8 @@
*/
/**
* HashSet
*
* A HashSet is an implementation of a Set with unique keys. The keys are not
* sorted. It is implemented as a hashtable with robin hood hashing.
*/
@@ -16,9 +18,11 @@
#ifndef CMC_HASHSET_H
#define CMC_HASHSET_H
#include <stdlib.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#ifndef CMC_HASH_TABLE_SETUP
#define CMC_HASH_TABLE_SETUP
@@ -164,6 +168,8 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
FMOD bool PFX##_empty(SNAME *_set_); \
FMOD size_t PFX##_count(SNAME *_set_); \
FMOD size_t PFX##_capacity(SNAME *_set_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_set_); \
\
/* Set Operations */ \
FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \
@@ -412,6 +418,18 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
return _set_->capacity; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_set_) \
{ \
cmc_string str; \
SNAME *s_ = _set_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_hashset, \
name, s_, s_->buffer, s_->capacity, s_->count, s_->load, s_->cmp, s_->hash); \
\
return str; \
} \
\
FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \
{ \
SNAME *_set_r_ = PFX##_new(_set1_->capacity, _set1_->load, _set1_->cmp, _set1_->hash); \
+36 -4
View File
@@ -8,16 +8,33 @@
*
*/
/*****************************************************************************/
/********************************************************************** HEAP */
/*****************************************************************************/
/**
* Heap
*
* The Heap is a specialized tree-based data structure which is essentially a
* complete tree that satisfies the heap property:
* - MaxHeap:
* - The root node is the greatest element of the unique set of keys.
* - A node key is always greater than or equal to its children keys.
* - Minheap:
* - The root node is the smallest element of the unique set of keys.
* - A node Key is always greater than or equal to its children keys.
*
* The heap is mostly used to implement priority queues. Sometimes it can also
* be used to sort elements. There are three main functions:
* - insert : Adds an element to the heap
* - remove_(min/max): Removes the min/max element from the heap
* - min/max : Accesses the min/max element from the heap
*/
#ifndef CMC_HEAP_H
#define CMC_HEAP_H
#include <stdlib.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
typedef enum cmc_heap_order_e
{
@@ -101,6 +118,8 @@ typedef enum cmc_heap_order_e
FMOD bool PFX##_full(SNAME *_heap_); \
FMOD size_t PFX##_count(SNAME *_heap_); \
FMOD size_t PFX##_capacity(SNAME *_heap_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_heap_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
@@ -289,6 +308,19 @@ typedef enum cmc_heap_order_e
return _heap_->capacity; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_heap_) \
{ \
cmc_string str; \
SNAME *h_ = _heap_; \
const char *name = #SNAME; \
const char *t = h_->HO == 1 ? "MaxHeap" : "MinHeap"; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_heap, \
name, h_, h_->buffer, h_->capacity, h_->count, t, h_->cmp); \
\
return str; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
+33 -4
View File
@@ -8,16 +8,31 @@
*
*/
/*****************************************************************************/
/**************************************************************** LINKEDLIST */
/*****************************************************************************/
/**
* LinkedList
*
* A LinkedList is a linear collection of elements, whose order is not given by
* their physical placement in memory. Instead, each element points to the next
* (singly-linked list) and to a previous one (doubly-linked list). It consists
* of nodes connected by these next or previous pointers. Unlike an array, the
* LinkedList can indefinitely grow.
*
* Implementation
*
* The LinkedList is implemented as a doubly-linked list and allows insertions
* and removals at both ends in O(1) and in a given index in O(N). The list has
* a head and tail pointer. The head points to the first element in the sequence
* and tail points to the last.
*/
#ifndef CMC_LINKEDLIST_H
#define CMC_LINKEDLIST_H
#include <stdlib.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#define LINKEDLIST_GENERATE(PFX, SNAME, FMOD, V) \
LINKEDLIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -110,6 +125,8 @@
FMOD bool PFX##_contains(SNAME *_list_, V element, int (*comparator)(V, V)); \
FMOD bool PFX##_empty(SNAME *_list_); \
FMOD size_t PFX##_count(SNAME *_list_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_list_); \
\
/* Node Related Functions */ \
/* Node Allocation and Deallocation */ \
@@ -443,6 +460,18 @@
return _list_->count; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_list_) \
{ \
cmc_string str; \
SNAME *l_ = _list_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_linkedlist, \
name, l_, l_->count, l_->head, l_->tail); \
\
return str; \
} \
\
FMOD SNAME##_node *PFX##_new_node(V element) \
{ \
SNAME##_node *_node_ = malloc(sizeof(SNAME##_node)); \
+48 -4
View File
@@ -8,16 +8,46 @@
*
*/
/*****************************************************************************/
/********************************************************************** LIST */
/*****************************************************************************/
/**
* List
*
* A List is a Dynamic Array that store its elements contiguously. It has an
* internal buffer that is pre-allocated with a greater capacity than necessary
* in order to foresee new elements being added. The items can be added at both
* ends of the list and at the middle (with a given index).
*
* Insertions at the start are more costly as it is necessary to shift all
* elements one position to the right to give space to a new element being added
* at index 0. Insertions at the end are instantaneous as long as there is
* enough space in the buffer. Insertions at the middle will be based on an
* index. The index represents where the element being added will be located
* once the operation ends. This operation might also need to shift elements. It
* is also possible to add arrays of elements in the list.
*
* When the buffer is filled, it is reallocated with a greater capacity, usually
* being doubled.
*
* Removing elements follows the same principle. Removing the front element will
* require to shift all other elements one position to the left, thus being
* slower than removing from the end in which is done in constant time. Removing
* elements in the middle of the list will also require shifting elements to the
* left. Is is also possible to remove a range of elements or extract them,
* creating a new list with the removed items.
*
* The iterator is a simple structure that is capable of going back and
* forwards. Any modifications to the target list during iteration is considered
* undefined behavior. Its sole purpose is to facilitate navigation through a
* list.
*/
#ifndef CMC_LIST_H
#define CMC_LIST_H
#include <stdlib.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#define LIST_GENERATE(PFX, SNAME, FMOD, V) \
LIST_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -104,6 +134,8 @@
FMOD size_t PFX##_count(SNAME *_list_); \
FMOD bool PFX##_fits(SNAME *_list_, size_t size); \
FMOD size_t PFX##_capacity(SNAME *_list_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_list_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
@@ -520,6 +552,18 @@
return _list_->capacity; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_list_) \
{ \
cmc_string str; \
SNAME *l_ = _list_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_list, \
name, l_, l_->buffer, l_->capacity, l_->count); \
\
return str; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
+55 -11
View File
@@ -8,16 +8,46 @@
*
*/
/*****************************************************************************/
/********************************************************************* QUEUE */
/*****************************************************************************/
/**
* Queue
*
* A Queue is a First-In First-out (or Last-in Last-out) data structure. It is
* a Dynamic Circular Array where elements are added from one end of the array
* and removed from the other end. The circular array here (also known as
* circular buffer or ring buffer) is very important so that both adding and
* removing elements from the Queue are done instantly. The array is linear but
* with the modulo operator it is treated as a circular sequence of elements.
*
* If the Queue was implemented as a regular Dynamic Array, when adding or
* removing an element at the front, it would be necessary to shift all elements
* currently present in the Queue and this would add up a lot of computing time.
* Shifting `100000` elements in memory by one position every time an element is
* added to the Queue is simply not efficient.
*
* The Queue has two ends. The `front` and `back`. In this implementation all
* elements are added to the back of the Queue and removed from the front, which
* is more or less how queues work in real life. Unlike a Stack that only has
* operations at one end of the buffer, the Queue needs to be implemented as a
* circular array in order to quickly add or remove elements.
*
* The Queue has three main functions: `enqueue` which adds an element to the
* Queue; `dequeue` which removes an element from the Queue; and `peek` which
* return the element at the front of the Queue, that is, the next element to
* be removed from it.
*
* The Queue is used in many applications where a resource is shared among
* multiple consumers and the Queue is responsible for scheduling the access to
* the resource.
*/
#ifndef CMC_QUEUE_H
#define CMC_QUEUE_H
#include <stdlib.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#define QUEUE_GENERATE(PFX, SNAME, FMOD, V) \
QUEUE_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -48,7 +78,7 @@
size_t front; \
\
/* Index representing the back of the queue */ \
size_t rear; \
size_t back; \
\
/* Function that returns an iterator to the start of the queue */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
@@ -97,6 +127,8 @@
FMOD bool PFX##_full(SNAME *_queue_); \
FMOD size_t PFX##_count(SNAME *_queue_); \
FMOD size_t PFX##_capacity(SNAME *_queue_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_queue_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
@@ -158,7 +190,7 @@
_queue_->capacity = capacity; \
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->rear = 0; \
_queue_->back = 0; \
\
_queue_->it_start = PFX##_impl_it_start; \
_queue_->it_end = PFX##_impl_it_end; \
@@ -172,7 +204,7 @@
\
_queue_->count = 0; \
_queue_->front = 0; \
_queue_->rear = 0; \
_queue_->back = 0; \
} \
\
FMOD void PFX##_free(SNAME *_queue_) \
@@ -189,9 +221,9 @@
return false; \
} \
\
_queue_->buffer[_queue_->rear] = element; \
_queue_->buffer[_queue_->back] = element; \
\
_queue_->rear = (_queue_->rear == _queue_->capacity - 1) ? 0 : _queue_->rear + 1; \
_queue_->back = (_queue_->back == _queue_->capacity - 1) ? 0 : _queue_->back + 1; \
_queue_->count++; \
\
return true; \
@@ -265,6 +297,18 @@
return _queue_->capacity; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_queue_) \
{ \
cmc_string str; \
SNAME *q_ = _queue_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_queue, \
name, q_, q_->buffer, q_->capacity, q_->count, q_->front, q_->back); \
\
return str; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
@@ -314,7 +358,7 @@
if (PFX##_empty(iter->target)) \
iter->cursor = 0; \
else \
iter->cursor = (iter->target->rear == 0) ? iter->target->capacity - 1 : iter->target->rear - 1; \
iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; \
\
iter->index = iter->target->count - 1; \
iter->start = PFX##_empty(iter->target); \
@@ -398,7 +442,7 @@
_queue_->buffer = new_buffer; \
_queue_->capacity = new_capacity; \
_queue_->front = 0; \
_queue_->rear = _queue_->count; \
_queue_->back = _queue_->count; \
\
return true; \
} \
+33 -4
View File
@@ -8,16 +8,31 @@
*
*/
/*****************************************************************************/
/********************************************************************* STACK */
/*****************************************************************************/
/**
* Stack
*
* A Stack is a Last-in First-out (or First-in Last-out) data structure used in
* a variety of algorithms. It is a Dynamic Array that can only add or remove
* its elements at the end of the buffer, in this case, it represents the top of
* the stack.
*
* It has three main functions: `push` which adds an element at the top of the
* stack; `pop` which removes the top element from the stack; and `top` which
* returns the top element without removing it (it is also sometimes called
* `peek`).
*
* A Stack is used in algorithms like backtracking, depth-first search,
* expression evaluation, syntax parsing and many more.
*/
#ifndef CMC_STACK_H
#define CMC_STACK_H
#include <stdlib.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#define STACK_GENERATE(PFX, SNAME, FMOD, V) \
STACK_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -88,6 +103,8 @@
FMOD bool PFX##_full(SNAME *_stack_); \
FMOD size_t PFX##_count(SNAME *_stack_); \
FMOD size_t PFX##_capacity(SNAME *_stack_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_stack_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
@@ -246,6 +263,18 @@
return _stack_->capacity; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_stack_) \
{ \
cmc_string str; \
SNAME *s_ = _stack_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_stack, \
name, s_, s_->buffer, s_->capacity, s_->count); \
\
return str; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
+19 -1
View File
@@ -9,6 +9,8 @@
*/
/**
* TreeMap
*
* A TreeMap is an implementation of a Map that keeps its keys sorted. Like a
* Map, it has only unique keys. This implementation uses a balanced binary
* tree called AVL Tree that uses the height of nodes to keep its keys balanced.
@@ -17,9 +19,11 @@
#ifndef CMC_TREEMAP_H
#define CMC_TREEMAP_H
#include <stdlib.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#define TREEMAP_GENERATE(PFX, SNAME, FMOD, K, V) \
TREEMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \
@@ -123,6 +127,8 @@
FMOD bool PFX##_contains(SNAME *_map_, K key); \
FMOD bool PFX##_empty(SNAME *_map_); \
FMOD size_t PFX##_count(SNAME *_map_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_map_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
@@ -534,6 +540,18 @@
return _map_->count; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_map_) \
{ \
cmc_string str; \
SNAME *m_ = _map_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_treemap, \
name, m_, m_->root, m_->count, m_->cmp); \
\
return str; \
} \
\
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target) \
{ \
SNAME##_iter *iter = malloc(sizeof(SNAME##_iter)); \
+19 -1
View File
@@ -9,6 +9,8 @@
*/
/**
* TreeSet
*
* A TreeSet is an implementation of a Set that keeps its elements sorted. Like
* a Set it has only unique keys. This implementation uses a balanced binary
* tree called AVL Tree that uses the height of nodes to keep its keys balanced.
@@ -17,9 +19,11 @@
#ifndef CMC_TREESET_H
#define CMC_TREESET_H
#include <stdlib.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../utl/cmc_string.h"
#define TREESET_GENERATE(PFX, SNAME, FMOD, V) \
TREESET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \
@@ -118,6 +122,8 @@
FMOD bool PFX##_contains(SNAME *_set_, V element); \
FMOD bool PFX##_empty(SNAME *_set_); \
FMOD size_t PFX##_count(SNAME *_set_); \
/* Collection Utility */ \
FMOD cmc_string PFX##_to_string(SNAME *_map_); \
\
/* Set Operations */ \
FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \
@@ -502,6 +508,18 @@
return _set_->count; \
} \
\
FMOD cmc_string PFX##_to_string(SNAME *_set_) \
{ \
cmc_string str; \
SNAME *s_ = _set_; \
const char *name = #SNAME; \
\
snprintf(str.s, cmc_string_len, cmc_string_fmt_treeset, \
name, s_, s_->root, s_->count, s_->cmp); \
\
return str; \
} \
\
FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \
{ \
SNAME *_set_r_ = PFX##_new(_set1_->cmp); \
+168 -140
View File
@@ -8,9 +8,37 @@
*
*/
/*****************************************************************************/
/******************************************************************* MULTIMAP */
/*****************************************************************************/
/**
* MultiMap
*
* The MultiMap is a Map that allows for multiple keys. This is a data structure
* that has a very narrow usage. A Map (either TreeMap or HashMap) can also work
* like a MultiMap if a certain key is mapped to another collection.
*
* Map<K = int, V = List<int>> maps an integer to a list of integer.
* MultiMap<K = int, V = int> maps many integer keys to integer values.
*
* The difference is that in a MultiMap you can store keys that are the same but
* might be different instances of the same value. This is also relevant if your
* data type is more complex like a struct where its ID is the same but some
* other members of this data type are different.
*
* Implementation
*
* The map uses separate chaining and robin hood hashing. Its internal buffer
* is made of a pair of pointers to entries that represent a linked list. So
* accessing map->buffer[0] would give the first pair of pointers. Each entry
* has both a pointer to a previous entry and a next entry. This design choice
* was made so that every collection in this library has a two-way iterator
* with a very few exceptions.
*
* Each entry is composed of a Key and a Value. Entries with the same key should
* always hash to the same linked list. Also, keys that hash to the same bucket
* will also be in the same linked list.
*
* The order of inserting and removing the same keys will behave like a FIFO. So
* the first key added will be the first to be removed.
*/
#ifndef CMC_MULTIMAP_H
#define CMC_MULTIMAP_H
@@ -67,143 +95,143 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531,
MULTIMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V)
/* HEADER ********************************************************************/
#define MULTIMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \
\
/* Multimap Structure */ \
typedef struct SNAME##_s \
{ \
/* Array of linked list to entries */ \
struct SNAME##_entry_s *(*buffer)[2]; \
\
/* Current array capacity */ \
size_t capacity; \
\
/* Current amount of keys */ \
size_t count; \
\
/* Load factor in range (0.0, infinity) */ \
double load; \
\
/* Key comparison functions */ \
int (*cmp)(K, K); \
\
/* Key hash function */ \
size_t (*hash)(K); \
\
/* Function that returns an iterator to the start of the multimap */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the multimap */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* Multimap Entry */ \
typedef struct SNAME##_entry_s \
{ \
/* Entry Key */ \
K key; \
\
/* Entry Value */ \
V value; \
\
/* Next entry on the linked list */ \
struct SNAME##_entry_s *next; \
\
/* Previous entry on the linked list */ \
struct SNAME##_entry_s *prev; \
\
} SNAME##_entry, *SNAME##_entry_ptr; \
\
typedef struct SNAME##_iter_s \
{ \
/* Target multimap */ \
struct SNAME##_s *target; \
\
/* Current entry */ \
struct SNAME##_entry_s *curr_entry; \
\
/* Cursor`s position (index) */ \
size_t cursor; \
\
/* Keeps track of relative index to the iteration of elements */ \
size_t index; \
\
/* The index of the first element */ \
size_t first; \
\
/* The index of the last element */ \
size_t last; \
\
/* If the iterator has reached the start of the iteration */ \
bool start; \
\
/* If the iterator has reached the end of the iteration */ \
bool end; \
} SNAME##_iter, *SNAME##_iter_ptr; \
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(K, K), size_t (*hash)(K)); \
FMOD void PFX##_clear(SNAME *_map_); \
FMOD void PFX##_free(SNAME *_map_); \
/* Collection Input and Output */ \
FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \
FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \
FMOD size_t PFX##_remove_all(SNAME *_map_, K key); \
/* Conditional Input and Output */ \
FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \
/* Element Access */ \
FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \
FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \
FMOD V PFX##_get(SNAME *_map_, K key); \
FMOD V *PFX##_get_ref(SNAME *_map_, K key); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_map_, K key); \
FMOD bool PFX##_empty(SNAME *_map_); \
FMOD size_t PFX##_count(SNAME *_map_); \
FMOD size_t PFX##_capacity(SNAME *_map_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \
FMOD void PFX##_iter_free(SNAME##_iter *iter); \
/* Iterator Initialization */ \
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
/* Iterator State */ \
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
/* Iterator Movement */ \
FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \
FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \
/* Iterator Access */ \
FMOD K PFX##_iter_key(SNAME##_iter *iter); \
FMOD V PFX##_iter_value(SNAME##_iter *iter); \
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* Default Key */ \
static inline K PFX##_impl_default_key(void) \
{ \
K _empty_key_; \
\
memset(&_empty_key_, 0, sizeof(K)); \
\
return _empty_key_; \
} \
\
/* Default Value */ \
static inline V PFX##_impl_default_value(void) \
{ \
V _empty_value_; \
\
memset(&_empty_value_, 0, sizeof(V)); \
\
return _empty_value_; \
} \
#define MULTIMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \
\
/* Multimap Structure */ \
typedef struct SNAME##_s \
{ \
/* Array of linked list to entries */ \
struct SNAME##_entry_s *(*buffer)[2]; \
\
/* Current array capacity */ \
size_t capacity; \
\
/* Current amount of keys */ \
size_t count; \
\
/* Load factor in range (0.0, infinity) */ \
double load; \
\
/* Key comparison functions */ \
int (*cmp)(K, K); \
\
/* Key hash function */ \
size_t (*hash)(K); \
\
/* Function that returns an iterator to the start of the multimap */ \
struct SNAME##_iter_s (*it_start)(struct SNAME##_s *); \
\
/* Function that returns an iterator to the end of the multimap */ \
struct SNAME##_iter_s (*it_end)(struct SNAME##_s *); \
\
} SNAME, *SNAME##_ptr; \
\
/* Multimap Entry */ \
typedef struct SNAME##_entry_s \
{ \
/* Entry Key */ \
K key; \
\
/* Entry Value */ \
V value; \
\
/* Next entry on the linked list */ \
struct SNAME##_entry_s *next; \
\
/* Previous entry on the linked list */ \
struct SNAME##_entry_s *prev; \
\
} SNAME##_entry, *SNAME##_entry_ptr; \
\
typedef struct SNAME##_iter_s \
{ \
/* Target multimap */ \
struct SNAME##_s *target; \
\
/* Current entry */ \
struct SNAME##_entry_s *curr_entry; \
\
/* Cursor`s position (index) */ \
size_t cursor; \
\
/* Keeps track of relative index to the iteration of elements */ \
size_t index; \
\
/* The index of the first element */ \
size_t first; \
\
/* The index of the last element */ \
size_t last; \
\
/* If the iterator has reached the start of the iteration */ \
bool start; \
\
/* If the iterator has reached the end of the iteration */ \
bool end; \
} SNAME##_iter, *SNAME##_iter_ptr; \
\
/* Collection Functions */ \
/* Collection Allocation and Deallocation */ \
FMOD SNAME *PFX##_new(size_t capacity, double load, int (*compare)(K, K), size_t (*hash)(K)); \
FMOD void PFX##_clear(SNAME *_map_); \
FMOD void PFX##_free(SNAME *_map_); \
/* Collection Input and Output */ \
FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \
FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \
FMOD size_t PFX##_remove_all(SNAME *_map_, K key); \
/* Conditional Input and Output */ \
FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \
FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \
/* Element Access */ \
FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \
FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \
FMOD V PFX##_get(SNAME *_map_, K key); \
FMOD V *PFX##_get_ref(SNAME *_map_, K key); \
/* Collection State */ \
FMOD bool PFX##_contains(SNAME *_map_, K key); \
FMOD bool PFX##_empty(SNAME *_map_); \
FMOD size_t PFX##_count(SNAME *_map_); \
FMOD size_t PFX##_capacity(SNAME *_map_); \
\
/* Iterator Functions */ \
/* Iterator Allocation and Deallocation */ \
FMOD SNAME##_iter *PFX##_iter_new(SNAME *target); \
FMOD void PFX##_iter_free(SNAME##_iter *iter); \
/* Iterator Initialization */ \
FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target); \
/* Iterator State */ \
FMOD bool PFX##_iter_start(SNAME##_iter *iter); \
FMOD bool PFX##_iter_end(SNAME##_iter *iter); \
/* Iterator Movement */ \
FMOD void PFX##_iter_to_start(SNAME##_iter *iter); \
FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \
FMOD bool PFX##_iter_next(SNAME##_iter *iter); \
FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \
/* Iterator Access */ \
FMOD K PFX##_iter_key(SNAME##_iter *iter); \
FMOD V PFX##_iter_value(SNAME##_iter *iter); \
FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \
FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \
\
/* Default Key */ \
static inline K PFX##_impl_default_key(void) \
{ \
K _empty_key_; \
\
memset(&_empty_key_, 0, sizeof(K)); \
\
return _empty_key_; \
} \
\
/* Default Value */ \
static inline V PFX##_impl_default_value(void) \
{ \
V _empty_value_; \
\
memset(&_empty_value_, 0, sizeof(V)); \
\
return _empty_value_; \
} \
/* SOURCE ********************************************************************/
#define MULTIMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \
\
+38
View File
@@ -0,0 +1,38 @@
/**
* cmc_string.h
*
* Creation Date: 17/07/2019
*
* Authors:
* Leonardo Vencovsky (https://github.com/LeoVen)
*
*/
/* A very simple fixed size string used by all collections' method to_string */
#ifndef CMC_STRING_H
#define CMC_STRING_H
#include <stddef.h>
#include <inttypes.h>
static const size_t cmc_string_len = 200;
typedef struct cmc_string_s
{
char s[200];
} cmc_string;
/* To string formatting */
static const char *cmc_string_fmt_deque = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", front:%" PRIuMAX ", back:%" PRIuMAX " }";
static const char *cmc_string_fmt_hashmap = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", load:%lf, cmp:%p, hash:%p }";
static const char *cmc_string_fmt_hashset = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", load:%lf, cmp:%p, hash:%p }";
static const char *cmc_string_fmt_heap = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", type:%s, cmp:%p }";
static const char *cmc_string_fmt_linkedlist = "%s at %p { count:%" PRIuMAX ", head:%p, tail:%p }";
static const char *cmc_string_fmt_list = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX " }";
static const char *cmc_string_fmt_queue = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX ", front:%" PRIuMAX ", back:%" PRIuMAX " }";
static const char *cmc_string_fmt_stack = "%s at %p { buffer:%p, capacity:%" PRIuMAX ", count:%" PRIuMAX " }";
static const char *cmc_string_fmt_treemap = "%s at %p { root:%p, count:%" PRIuMAX ", cmp:%p, }";
static const char *cmc_string_fmt_treeset = "%s at %p { root:%p, count:%" PRIuMAX ", cmp:%p, }";
#endif /* CMC_STRING_H */