515 lines
45 KiB
HTML
515 lines
45 KiB
HTML
<!DOCTYPE HTML>
|
|
<html lang="en" class="sidebar-visible no-js light">
|
|
<head>
|
|
<!-- Book generated using mdBook -->
|
|
<meta charset="UTF-8">
|
|
<title>C Macro Collections</title>
|
|
|
|
<meta name="robots" content="noindex" />
|
|
|
|
|
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
|
<meta name="description" content="">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="theme-color" content="#ffffff" />
|
|
|
|
<link rel="shortcut icon" href="favicon.png">
|
|
<link rel="stylesheet" href="css/variables.css">
|
|
<link rel="stylesheet" href="css/general.css">
|
|
<link rel="stylesheet" href="css/chrome.css">
|
|
<link rel="stylesheet" href="css/print.css" media="print">
|
|
|
|
<!-- Fonts -->
|
|
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
|
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
|
|
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
|
|
|
|
<!-- Highlight.js Stylesheets -->
|
|
<link rel="stylesheet" href="highlight.css">
|
|
<link rel="stylesheet" href="tomorrow-night.css">
|
|
<link rel="stylesheet" href="ayu-highlight.css">
|
|
|
|
<!-- Custom theme stylesheets -->
|
|
|
|
|
|
|
|
</head>
|
|
<body>
|
|
<!-- Provide site root to javascript -->
|
|
<script type="text/javascript">
|
|
var path_to_root = "";
|
|
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
|
|
</script>
|
|
|
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
|
<script type="text/javascript">
|
|
try {
|
|
var theme = localStorage.getItem('mdbook-theme');
|
|
var sidebar = localStorage.getItem('mdbook-sidebar');
|
|
|
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
|
}
|
|
|
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
|
}
|
|
} catch (e) { }
|
|
</script>
|
|
|
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
|
<script type="text/javascript">
|
|
var theme;
|
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
|
var html = document.querySelector('html');
|
|
html.classList.remove('no-js')
|
|
html.classList.remove('light')
|
|
html.classList.add(theme);
|
|
html.classList.add('js');
|
|
</script>
|
|
|
|
<!-- Hide / unhide sidebar before it is displayed -->
|
|
<script type="text/javascript">
|
|
var html = document.querySelector('html');
|
|
var sidebar = 'hidden';
|
|
if (document.body.clientWidth >= 1080) {
|
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
|
sidebar = sidebar || 'visible';
|
|
}
|
|
html.classList.remove('sidebar-visible');
|
|
html.classList.add("sidebar-" + sidebar);
|
|
</script>
|
|
|
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
|
<div id="sidebar-scrollbox" class="sidebar-scrollbox">
|
|
<ol class="chapter"><li class="expanded "><a href="Introduction/introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><ol class="section"><li class="expanded "><a href="Introduction/why_this_library.html"><strong aria-hidden="true">1.1.</strong> Why this library</a></li><li class="expanded "><a href="Introduction/how_to_install.html"><strong aria-hidden="true">1.2.</strong> How to install</a></li><li class="expanded "><a href="Introduction/library_structure.html"><strong aria-hidden="true">1.3.</strong> Library structure</a></li><li class="expanded "><a href="Introduction/understanding_the_library.html"><strong aria-hidden="true">1.4.</strong> Understanding the library</a></li><li class="expanded "><a href="Introduction/how_to_use_the_library.html"><strong aria-hidden="true">1.5.</strong> How to use the library</a></li></ol></li><li class="expanded "><a href="Features/features.html"><strong aria-hidden="true">2.</strong> Features</a></li><li><ol class="section"><li class="expanded "><a href="Features/two_way_iterators.html"><strong aria-hidden="true">2.1.</strong> Two way iterators</a></li><li class="expanded "><a href="Features/custom_allocation.html"><strong aria-hidden="true">2.2.</strong> Custom allocation</a></li><li class="expanded "><a href="Features/callbacks.html"><strong aria-hidden="true">2.3.</strong> Callbacks</a></li><li class="expanded "><a href="Features/functions_table.html"><strong aria-hidden="true">2.4.</strong> Functions Table</a></li></ol></li><li class="expanded "><a href="Overview/overview.html"><strong aria-hidden="true">3.</strong> Collections Overview</a></li><li class="expanded "><a href="Examples/examples.html"><strong aria-hidden="true">4.</strong> Examples</a></li></ol>
|
|
</div>
|
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
|
</nav>
|
|
|
|
<div id="page-wrapper" class="page-wrapper">
|
|
|
|
<div class="page">
|
|
|
|
<div id="menu-bar" class="menu-bar">
|
|
<div id="menu-bar-sticky-container">
|
|
<div class="left-buttons">
|
|
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
|
<i class="fa fa-bars"></i>
|
|
</button>
|
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
|
<i class="fa fa-paint-brush"></i>
|
|
</button>
|
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
|
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
|
</ul>
|
|
|
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
|
<i class="fa fa-search"></i>
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<h1 class="menu-title">C Macro Collections</h1>
|
|
|
|
<div class="right-buttons">
|
|
<a href="print.html" title="Print this book" aria-label="Print this book">
|
|
<i id="print-button" class="fa fa-print"></i>
|
|
</a>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="search-wrapper" class="hidden">
|
|
<form id="searchbar-outer" class="searchbar-outer">
|
|
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
|
</form>
|
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
|
<div id="searchresults-header" class="searchresults-header"></div>
|
|
<ul id="searchresults">
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
|
<script type="text/javascript">
|
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
|
});
|
|
</script>
|
|
|
|
<div id="content" class="content">
|
|
<main>
|
|
<h1><a class="header" href="#introduction" id="introduction">Introduction</a></h1>
|
|
<p align="center">
|
|
<img src="Introduction/img/logo.png" alt="C Macro Collections Logo" width="300"/>
|
|
</p>
|
|
<p align="center">Header only, macro generated, generic and type-safe Collections in C.</p>
|
|
<p align="center">
|
|
<a href="https://github.com/LeoVen/C-Macro-Collections/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License"/></a>
|
|
<a href="https://travis-ci.org/LeoVen/C-Macro-Collections"><img src="https://travis-ci.org/LeoVen/C-Macro-Collections.svg?branch=master" alt="travis-ci"/></a>
|
|
<a href="https://codecov.io/gh/LeoVen/C-Macro-Collections"><img src="https://codecov.io/gh/LeoVen/C-Macro-Collections/branch/master/graph/badge.svg" alt="codecov"/></a>
|
|
</p>
|
|
<p>The C Macro Collections Library is a compilation of macros that can be used to generate common data structures for any desired type. These data structures are <a href="https://en.wikipedia.org/wiki/Type_safety">type safe</a> and are powered with many features (see Features section).</p>
|
|
<p>The documentation is currently being written in hopes that in the future it can be used to help you get to know better this amazing C library.</p>
|
|
<h1><a class="header" href="#why-this-library" id="why-this-library">Why this library</a></h1>
|
|
<p>C is a low level language and lacks all the data structures that we commonly use. Many high level languages already come with these collections so that we don't have to implement everything ourselves. A lot of third party libraries that implement these missing data structures for the C language usually make use of a void pointers and a lot of macros. <strong>This is why the C Macro Collections Library was created.</strong> All you need to do is to write down one macro and which data type you wish to work with. The library currently provides many data structures, such as:</p>
|
|
<ul>
|
|
<li><strong>Linear Collections</strong> : List, LinkedList, Deque, Stack, Queue, SortedList</li>
|
|
<li><strong>Sets</strong> : HashSet, TreeSet, MultiSet</li>
|
|
<li><strong>Maps</strong> : HashMap, TreeMap, MultiMap, BidiMap</li>
|
|
<li><strong>Heaps</strong> : Heap, IntervalHeap</li>
|
|
</ul>
|
|
<p>All with the following features:</p>
|
|
<ul>
|
|
<li><strong>Type-safe</strong> - No <code>void *</code> pointers are used. A collection of type <code>int</code> will only accept integers;</li>
|
|
<li><strong>Customization</strong> - Custom struct name and function namespace;</li>
|
|
<li><strong>Bidirectional Iterators</strong> - Full support for iterators;</li>
|
|
<li><strong>Nesting</strong> - Collections can be nested (List of Lists, HashSet of Stacks, etc);</li>
|
|
<li><strong>One macro to rule them all</strong> - Only one macro to generate everything and that's it.</li>
|
|
</ul>
|
|
<p>and many other powerful features (see <a href="Introduction/../Features/features.html">Features</a>).</p>
|
|
<h1><a class="header" href="#how-to-install" id="how-to-install">How to install</a></h1>
|
|
<p>To start using the library you need first to download the source code. You can either fork the repository or download a zip file containing everything. Either way, after you unzip everything you will end up with the root folder (probably something called <code>C-Macro-Collections</code>) and inside it is the <code>src</code> folder.</p>
|
|
<p>With the <code>src</code> folder you can start including the library headers to your project with <code>-I path/to/library/src</code>.</p>
|
|
<p>The library has no external dependencies other than the C standard library.</p>
|
|
<pre><code class="language-c">// Include header files like this
|
|
#include <cmc/list.h>
|
|
#include <dev/deque.h>
|
|
#include <utl/assert.h>
|
|
</code></pre>
|
|
<pre><code class="language-c">// Not like this
|
|
#include <list.h>
|
|
#include <deque.h> // dev or cmc?
|
|
#include <assert.h> // this will import from the standard library
|
|
</code></pre>
|
|
<h1><a class="header" href="#library-structure" id="library-structure">Library Structure</a></h1>
|
|
<p>The <code>src</code> folder is subdivided in 5 other folders and one file:</p>
|
|
<ul>
|
|
<li><strong>cmc</strong> - The main C Macro Collections Library</li>
|
|
<li><strong>dev</strong> - The main C Macro Collections Library for development</li>
|
|
<li><strong>sac</strong> - Statically Allocated Collections</li>
|
|
<li><strong>utl</strong> - Utility like ForEach macros, logging, etc</li>
|
|
<li><strong>macro_collections.h</strong> - Master header containing all collections and utilities</li>
|
|
</ul>
|
|
<h2><a class="header" href="#cmc" id="cmc">cmc</a></h2>
|
|
<p>This is where the C Macro Collections are hosted.</p>
|
|
<h2><a class="header" href="#dev" id="dev">dev</a></h2>
|
|
<p>In this folder is an exact copy of the <code>cmc</code> Collections with the added logging utility (<code>./utl/log.h</code>). These are useful to debug your code because everything that is happening inside the data structure can be seen.</p>
|
|
<h2><a class="header" href="#sac" id="sac">sac</a></h2>
|
|
<p>This is where the Statically Allocated Collections are hosted. These collections are just like the <code>cmc</code> Collections but they have a constant size, a C array, instead of a dynamically allocated array (yes, even for Linked List).</p>
|
|
<h2><a class="header" href="#utl" id="utl">utl</a></h2>
|
|
<p>Utility. Here you will find things like assert macros, foreach macros, logging utility, unit test and timer.</p>
|
|
<h2><a class="header" href="#macro_collectionsh" id="macro_collectionsh">macro_collections.h</a></h2>
|
|
<p>This is the master header. Include this big boy and all functionalities of the library will be in your hands.</p>
|
|
<h1><a class="header" href="#understanding-the-library" id="understanding-the-library">Understanding the Library</a></h1>
|
|
<p>Every macro within the library is prefixed by <code>CMC</code> or <code>cmc</code>. If you have <a href="https://code.visualstudio.com/docs/editor/intellisense">intellisense</a> you can easily check all the features of the library once you include the necessary headers.</p>
|
|
<p>When you generate code for a certain collection you will need to pass four very important parameters: <code>SNAME</code>, <code>PFX</code>, <code>K</code> and <code>V</code>.</p>
|
|
<h2><a class="header" href="#sname" id="sname">SNAME</a></h2>
|
|
<p><code>SNAME</code> is short for struct name. This parameter will define your collection so that its type name becomes:</p>
|
|
<pre><code class="language-c">struct SNAME;
|
|
</code></pre>
|
|
<p>No <code>typedef</code>s are used within the code that is generated in order to not pollute the global namespace. If you wish to <code>typedef</code> feel free to give your own naming conventions.
|
|
<strong>Every other <code>struct</code> that is generated as part of the implementation will be prefixed by <code>SNAME</code></strong>. So iterators and nodes will become:</p>
|
|
<pre><code class="language-c">struct SNAME##_iter;
|
|
struct SNAME##_node;
|
|
</code></pre>
|
|
<p>Note that the <code>##</code> is a <a href="https://en.wikipedia.org/wiki/C_preprocessor#Token_concatenation">Token Pasting Operator</a>.</p>
|
|
<h2><a class="header" href="#pfx" id="pfx">PFX</a></h2>
|
|
<p><code>PFX</code> is a short for prefix. <strong>Every function generated will be within this namespace</strong>. When using <a href="https://code.visualstudio.com/docs/editor/intellisense">Intellisense</a>, write whichever prefix you gave to your functions and everything will be in there.</p>
|
|
<p>Functions that are part of the implementation and shouldn't be called directly are prefixed by <code>PFX</code> and then by <code>_impl_</code>. Every iterator function will be prefixed by <code>PFX</code> and then by <code>_iter_</code>. For example:</p>
|
|
<pre><code class="language-c">// A function that you shouldn't use directly
|
|
size_t PFX##_impl_quick_sort(struct SNAME *list);
|
|
</code></pre>
|
|
<pre><code class="language-c">// A function that is associated with the iterator
|
|
struct SNAME##_iter *PFX##_iter_new(struct SNAME *target);
|
|
</code></pre>
|
|
<h2><a class="header" href="#k" id="k">K</a></h2>
|
|
<p><code>K</code>, short for Key, is the data type that is only used by associative collections to map a key to a value.</p>
|
|
<h2><a class="header" href="#v" id="v">V</a></h2>
|
|
<p><code>V</code>, short for Value, is the primary data type for most collections.</p>
|
|
<h2><a class="header" href="#summarizing" id="summarizing">Summarizing</a></h2>
|
|
<p>With <code>SNAME</code> and <code>PFX</code> a common function definition looks like:</p>
|
|
<p><code>size_t PFX##_count(struct SNAME *list);</code></p>
|
|
<p>So if input <code>SNAME</code> as <code>i32list</code> and <code>PFX</code> as <code>i32l</code> you will have the following function definition:</p>
|
|
<p><code>size_t i32l_count(struct i32list *list);</code></p>
|
|
<h1><a class="header" href="#how-to-use-the-library" id="how-to-use-the-library">How to Use the Library</a></h1>
|
|
<p>The C Macro Collections Library comes with very powerful data structures and they are only one macro away from you.</p>
|
|
<h1><a class="header" href="#features" id="features">Features</a></h1>
|
|
<p>The C Macro Collections Library comes with powerful collections. In this section you will better understand many features that are common to all data structures.</p>
|
|
<h1><a class="header" href="#two-way-iterators" id="two-way-iterators">Two-Way Iterators</a></h1>
|
|
<p>Every collection comes with an interface of iterators where you can easily access the elements of a collection. These can move at any direction, can start at any 'end' of a collection and can move any amount of steps per iteration. Every collection generated comes with an iterator.</p>
|
|
<p>By design choice these iterators do not support modifications to the collection. If a collection is modified, all iterators that have been initialized will most likely be invalidated and may cause undefined behavior if used afterwards.</p>
|
|
<h1><a class="header" href="#custom-allocation" id="custom-allocation">Custom Allocation</a></h1>
|
|
<p>All collections have an allocation node. This node can be modified so that every allocation and de-allocation can be done with custom functions. The allocation node has pointers to functions that correspond to:</p>
|
|
<ul>
|
|
<li><code>calloc</code></li>
|
|
<li><code>free</code></li>
|
|
<li><code>malloc</code></li>
|
|
<li><code>realloc</code></li>
|
|
</ul>
|
|
<h1><a class="header" href="#callbacks" id="callbacks">Callbacks</a></h1>
|
|
<p>Every collection can have an optional callback node. In this node there are five functions:</p>
|
|
<table><thead><tr><th></th><th></th></tr></thead><tbody>
|
|
<tr><td><code>create</code></td><td>Is called when an element was successfully added to the collection</td></tr>
|
|
<tr><td><code>read</code></td><td>Is called when the collection was successfully queried about an element</td></tr>
|
|
<tr><td><code>update</code></td><td>Is called when an element in the collection was successfully updated</td></tr>
|
|
<tr><td><code>delete</code></td><td>Is called when an element was successfully removed from the collection</td></tr>
|
|
<tr><td><code>resize</code></td><td>Is called when the collection was full and successfully resized</td></tr>
|
|
</tbody></table>
|
|
<p>Check the documentation for each collection to see which functions call which callbacks.</p>
|
|
<h1><a class="header" href="#functions-table" id="functions-table">Functions Table</a></h1>
|
|
<p>Functions table are like a methods table for you custom data type. It is a <code>struct</code> of function pointers that you will need to define in order to some collections to work. Some functions are optional and others are needed in order to a collection to operate.</p>
|
|
<h3><a class="header" href="#cmp" id="cmp">CMP</a></h3>
|
|
<p>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 <code>int</code> with the following definitions:</p>
|
|
<ul>
|
|
<li>Return <code>1</code> if the first argument is greater than the second;</li>
|
|
<li>Return <code>0</code> if the first argument equals the second;</li>
|
|
<li>Return <code>-1</code> if the first argument is less than the second.</li>
|
|
</ul>
|
|
<h3><a class="header" href="#cpy" id="cpy">CPY</a></h3>
|
|
<p>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 (<code>NULL</code>) the data type will be copied by assignment (for pointers this is a shallow copy).</p>
|
|
<h3><a class="header" href="#str" id="str">STR</a></h3>
|
|
<p>A string function is responsible for taking a <code>FILE</code> pointer and a custom data type and outputting the string representation of that data returning a <code>bool</code> indication success or failure. It is useful for debugging.</p>
|
|
<h3><a class="header" href="#free" id="free">FREE</a></h3>
|
|
<p>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.</p>
|
|
<h3><a class="header" href="#hash" id="hash">HASH</a></h3>
|
|
<p>This function receives a custom data type as parameter and returns a <code>size_t</code> hash of that data. Used in hashtables.</p>
|
|
<h3><a class="header" href="#pri" id="pri">PRI</a></h3>
|
|
<p>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.</p>
|
|
<ul>
|
|
<li>Return <code>1</code> if the first argument has a greater priority than the second;</li>
|
|
<li>Return <code>0</code> if the first argument has the same priority as second;</li>
|
|
<li>Return <code>-1</code> if the first argument has a lower priority than the second.</li>
|
|
</ul>
|
|
<p>The following table shows which functions are required, optional or never used for each Collection:</p>
|
|
<table><thead><tr><th>Collection</th><th align="center">CMP</th><th align="center">CPY</th><th align="center">STR</th><th align="center">FREE</th><th align="center">HASH</th><th align="center">PRI</th></tr></thead><tbody>
|
|
<tr><td>BidiMap</td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>Deque</td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>HashMap</td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>HashSet</td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>Heap</td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td></tr>
|
|
<tr><td>IntervalHeap</td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td></tr>
|
|
<tr><td>List</td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>LinkedList</td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>MultiMap</td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>MultiSet</td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>Queue</td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>SortedList</td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>Stack</td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>TreeMap</td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
<tr><td>TreeSet</td><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td></tr>
|
|
</tbody></table>
|
|
<br>
|
|
<table><thead><tr><th align="center">Color</th><th>Label</th></tr></thead><tbody>
|
|
<tr><td align="center"><img src="https://placehold.it/20/b82b28/000000?text=+" alt="#b82b28" /></td><td>Required for basic functionality.</td></tr>
|
|
<tr><td align="center"><img src="https://placehold.it/20/9f3b94/000000?text=+" alt="#9f3b94" /></td><td>Required for specific functions.</td></tr>
|
|
<tr><td align="center"><img src="https://placehold.it/20/497edd/000000?text=+" alt="#497edd" /></td><td>Required for non-core specific functions.</td></tr>
|
|
<tr><td align="center"><img src="https://placehold.it/20/00d3eb/000000?text=+" alt="#00d3eb" /></td><td>Optional.</td></tr>
|
|
<tr><td align="center"><img src="https://placehold.it/20/2ef625/000000?text=+" alt="#2ef625" /></td><td>Not Used.</td></tr>
|
|
</tbody></table>
|
|
<h1><a class="header" href="#collections-overview" id="collections-overview">Collections Overview</a></h1>
|
|
<table><thead><tr><th align="center">Collection</th><th align="center">Abstract Data Type</th><th align="center">Data Structure</th><th align="center">Details</th></tr></thead><tbody>
|
|
<tr><td align="center">BidiMap <br> <em>bidimap.h</em></td><td align="center">Bidirectional Map</td><td align="center">Two Hashtables</td><td align="center">A bijection between two sets of unique keys and unique values <code>K <-> V</code> using two hashtables</td></tr>
|
|
<tr><td align="center">Deque <br> <em>deque.h</em></td><td align="center">Double-Ended Queue</td><td align="center">Dynamic Circular Array</td><td align="center">A circular array that allows <code>push</code> and <code>pop</code> on both ends (only) at constant time</td></tr>
|
|
<tr><td align="center">HashMap <br> <em>hashmap.h</em></td><td align="center">Map</td><td align="center">Hashtable</td><td align="center">A unique set of keys associated with a value <code>K -> V</code> with constant time look up using a hashtable with open addressing and robin hood hashing</td></tr>
|
|
<tr><td align="center">HashSet <br> <em>hashset.h</em></td><td align="center">Set</td><td align="center">Hashtable</td><td align="center">A unique set of values with constant time look up using a hashtable with open addressing and robin hood hashing</td></tr>
|
|
<tr><td align="center">Heap <br> <em>heap.h</em></td><td align="center">Priority Queue</td><td align="center">Dynamic Array</td><td align="center">A binary heap as a dynamic array as an implicit data structure</td></tr>
|
|
<tr><td align="center">IntervalHeap <br> <em>intervalheap.h</em></td><td align="center">Double-Ended Priority Queue</td><td align="center">Custom Dynamic Array</td><td align="center">A dynamic array of nodes, each hosting one value from the MinHeap and one from the MaxHeap</td></tr>
|
|
<tr><td align="center">LinkedList <br> <em>linkedlist.h</em></td><td align="center">List</td><td align="center">Doubly-Linked List</td><td align="center">A default doubly-linked list</td></tr>
|
|
<tr><td align="center">List <br> <em>list.h</em></td><td align="center">List</td><td align="center">Dynamic Array</td><td align="center">A dynamic array with <code>push</code> and <code>pop</code> anywhere on the array</td></tr>
|
|
<tr><td align="center">MultiMap <br> <em>multimap.h</em></td><td align="center">Multimap</td><td align="center">Custom Hashtable</td><td align="center">A mapping of multiple keys with one node per key using a hashtable with separate chaining</td></tr>
|
|
<tr><td align="center">Multiset <br> <em>multiset.h</em></td><td align="center">Multiset</td><td align="center">Hashtable</td><td align="center">A mapping of a value and its multiplicity using a hashtable with open addressing and robin hood hashing</td></tr>
|
|
<tr><td align="center">Queue <br> <em>queue.h</em></td><td align="center">FIFO</td><td align="center">Dynamic Circular Array</td><td align="center">A queue using a circular array with <code>enqueue</code> at the <code>back</code> index and <code>dequeue</code> at the <code>front</code> index</td></tr>
|
|
<tr><td align="center">SortedList <br> <em>sortedlist.h</em></td><td align="center">Sorted List</td><td align="center">Sorted Dynamic Array</td><td align="center">A lazily sorted dynamic array that is sorted only when necessary</td></tr>
|
|
<tr><td align="center">Stack <br> <em>stack.h</em></td><td align="center">FILO</td><td align="center">Dynamic Array</td><td align="center">A stack with push and pop at the end of a dynamic array</td></tr>
|
|
<tr><td align="center">TreeMap <br> <em>treemap.h</em></td><td align="center">Sorted Map</td><td align="center">AVL Tree</td><td align="center">A unique set of keys associated with a value <code>K -> V</code> using an AVL tree with <code>log(n)</code> look up and sorted iteration</td></tr>
|
|
<tr><td align="center">TreeSet <br> <em>treeset.h</em></td><td align="center">Sorted Set</td><td align="center">AVL Tree</td><td align="center">A unique set of keys using an AVL tree with <code>log(n)</code> look up and sorted iteration</td></tr>
|
|
</tbody></table>
|
|
<h1><a class="header" href="#minimal-example" id="minimal-example">Minimal Example</a></h1>
|
|
<p>(TODO this example is currently outdated)</p>
|
|
<p>Lets create a list of type <code>int</code>, add some elements to it and get the sum of all the elements printed on the screen.</p>
|
|
<h3><a class="header" href="#include-headers" id="include-headers">Include headers</a></h3>
|
|
<pre><code class="language-c">#include <cmc/list.h>
|
|
</code></pre>
|
|
<p>First you need to include only the necessary headers. It is not recommended that you include everything with <code>macro_collections.h</code>, only in cases where you might be using almost all features from the library.</p>
|
|
<h3><a class="header" href="#generating-a-list" id="generating-a-list">Generating a list</a></h3>
|
|
<pre><code class="language-c">// CMC_GENERATE_LIST(PFX, SNAME, V)
|
|
CMC_GENERATE_LIST(il, int_list, int)
|
|
</code></pre>
|
|
<p>The List is also known as <code>vector</code>, <code>ArrayList</code> and dynamic array. In fact the latter is the best description for this collection. It is a dynamic array that can grow and shrink as needed. To generate it we can simply call the macro <code>CMC_GENERATE_LIST</code> after our includes. It has three parameters:</p>
|
|
<table><thead><tr><th align="center">Parameter name</th><th>Purpose</th></tr></thead><tbody>
|
|
<tr><td align="center"><strong>PFX</strong></td><td>Functions prefix (namespace)</td></tr>
|
|
<tr><td align="center"><strong>SNAME</strong></td><td>Struct name</td></tr>
|
|
<tr><td align="center"><strong>V</strong></td><td>The list value type (can be any valid data type)</td></tr>
|
|
</tbody></table>
|
|
<aside class="notice">
|
|
All collections can be generated by using the macro CMC_GENERATE_ and then the name of the include (in this case list.h) but in uppercase without the `.h`.
|
|
</aside>
|
|
<h3><a class="header" href="#initializing-and-adding-elements" id="initializing-and-adding-elements">Initializing and adding elements</a></h3>
|
|
<pre><code class="language-c">// Allocate an int_list with an initial capacity of 100
|
|
int_list *list = il_new(100);
|
|
|
|
// Adding elements to the back of the list
|
|
for (int i = 0; i <= 1000; i++)
|
|
{
|
|
if (!il_push_back(list, i))
|
|
{
|
|
// Something went wrong (check out documentation)
|
|
}
|
|
}
|
|
</code></pre>
|
|
<p>To initialize any collection we call a function <code>_new</code>. Since the <code>PFX</code> parameter is set to <code>il</code> all functions related to our list of integer will be prefixed by <code>il</code>, so <code>_new</code> becomes <code>il_new</code>.</p>
|
|
<p>The list name is <code>int_list</code> as defined by <code>SNAME</code>. This type is a typedef like:</p>
|
|
<p><code>typedef struct SNAME##_s SNAME;</code></p>
|
|
<p>Which expands to:</p>
|
|
<p><code>typedef struct int_list_s int_list</code></p>
|
|
<p>To add elements to the back of a list we can use <code>il_push_back</code>. This function will first check if the list has enough space for a new element. If not, reallocate the internal buffer with doubled size and then add the new element.</p>
|
|
<h3><a class="header" href="#iteration" id="iteration">Iteration</a></h3>
|
|
<blockquote>
|
|
<p>It is recommended that the iterator is allocated on the stack</p>
|
|
</blockquote>
|
|
<pre><code class="language-c">// Resulting sum will be stored here
|
|
int sum = 0;
|
|
|
|
// Declare our iterator (allocating it on the stack)
|
|
int_list_iter it;
|
|
|
|
// Loop for each element
|
|
for (il_iter_init(&it, list); !il_iter_end(&it); il_iter_next(&it))
|
|
{
|
|
// Accessing the value
|
|
int elem = il_iter_value(&it);
|
|
|
|
sum += elem;
|
|
}
|
|
|
|
printf("%d\n", sum);
|
|
</code></pre>
|
|
<p>There are 6 (2 optional) steps to iterate over the elements of any collection:</p>
|
|
<table><thead><tr><th align="center">Step</th><th>Description</th><th>Function</th></tr></thead><tbody>
|
|
<tr><td align="center">1</td><td>Allocate the iterator (optional)</td><td><code>il_iter_new</code></td></tr>
|
|
<tr><td align="center">2</td><td>Initialize the iterator given a target list</td><td><code>il_iter_init</code></td></tr>
|
|
<tr><td align="center">3</td><td>Access the iterator's elements (value, index, etc)</td><td><code>il_iter_value</code></td></tr>
|
|
<tr><td align="center">4</td><td>Go to the next element</td><td><code>il_iter_next</code></td></tr>
|
|
<tr><td align="center">5</td><td>Check if we haven't reached the end of the list</td><td><code>il_iter_end</code></td></tr>
|
|
<tr><td align="center">6</td><td>Free the iterator if it was allocated on the heap</td><td><code>il_iter_free</code></td></tr>
|
|
</tbody></table>
|
|
<p>Note that all iterator functions are prefixed by the user defined prefix and then by <code>iter</code> (<code>il + iter = il_iter</code>). Also, the steps <strong>1</strong> and <strong>6</strong> are optional so <code>il_iter_new</code> and <code>il_iter_free</code> are not used in the example.</p>
|
|
<p>By the end of the example we have the variable <code>sum</code> with the sum of all integers inside our list. We can then print it and this example is almost done.</p>
|
|
<h3><a class="header" href="#freeing-resources" id="freeing-resources">Freeing resources</a></h3>
|
|
<pre><code class="language-c">// void il_free(int_list *_list_, void(*deallocator)(int))
|
|
il_free(list, NULL);
|
|
</code></pre>
|
|
<p>The list is currently allocated in memory. To deallocate it we call <code>il_free</code>. This function takes a pointer to the allocated list and a pointer to a <code>deallocator</code> function that will be responsible for deallocating each element in the list. This last parameter is optional and we won't be using it since our data type <code>int</code> is not allocated in the heap. This optional parameter can be set to <code>NULL</code> to be ignored by the <code>il_free</code> function.</p>
|
|
<h3><a class="header" href="#compile-and-run" id="compile-and-run">Compile and run</a></h3>
|
|
<blockquote>
|
|
<p>source.c</p>
|
|
</blockquote>
|
|
<pre><code class="language-c">#include <cmc/list.h>
|
|
|
|
CMC_GENERATE_LIST(il, int_list, int)
|
|
|
|
int main(void)
|
|
{
|
|
int_list *list = il_new(100);
|
|
|
|
for (int i = 0; i <= 1000; i++)
|
|
{
|
|
if (!il_push_back(list, i))
|
|
{
|
|
// Something went wrong (check out documentation)
|
|
}
|
|
}
|
|
|
|
int sum = 0;
|
|
|
|
int_list_iter it;
|
|
|
|
for (il_iter_init(&it, list); !il_iter_end(&it); il_iter_next(&it))
|
|
{
|
|
int elem = il_iter_value(&it);
|
|
sum += elem;
|
|
}
|
|
|
|
printf("%d\n", sum);
|
|
|
|
il_free(list, NULL);
|
|
}
|
|
</code></pre>
|
|
<p>If the source file is <code>source.c</code>, all you have to do is to include the <code>src</code> folder to the include path and compile. The following example uses <code>gcc</code>:</p>
|
|
<p><code>gcc source.c -I path/to/library/src</code></p>
|
|
<h3><a class="header" href="#conclusion" id="conclusion">Conclusion</a></h3>
|
|
<p>The C Macro Collections Library is prepared to accept any data type and is highly customizable. It is also very easy to integrate and no previous compilation is required. The library also comes with many utilities in the <code>utl</code> folder that are designed to work well with all collections.</p>
|
|
|
|
</main>
|
|
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|
<!-- Mobile navigation buttons -->
|
|
|
|
|
|
|
|
|
|
<div style="clear: both"></div>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
|
|
|
|
|
|
|
</nav>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
window.playpen_copyable = true;
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
|
|
|
|
|
|
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="book.js" type="text/javascript" charset="utf-8"></script>
|
|
|
|
<!-- Custom JS scripts -->
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
window.addEventListener('load', function() {
|
|
window.setTimeout(window.print, 100);
|
|
});
|
|
</script>
|
|
|
|
|
|
|
|
</body>
|
|
</html>
|