blob: 4fda76f273fea83dd25383523353e553e85ae83c [file] [log] [blame] [raw]
<!DOCTYPE html><html><head><meta charset="utf-8" /><meta content="IE=edge" http-equiv="X-UA-Compatible" /><meta content="width=device-width, initial-scale=1, maximum-scale=2.0, user-scalable=yes, minimal-ui=yes" name="viewport" /><title>facil.io - Core Dynamic Array Type</title><meta content="facil.io - Core Dynamic Array Type" name="description" /><link href="https://fonts.googleapis.com/css?family=Montserrat|Quicksand|Karla" rel="stylesheet" type="text/css" /><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script><link href="/assets/styles/main.css" rel="stylesheet" type="text/css" /><script type="application/ld+json">{"@context":"http://schema.org","@type":"WebSite","url":"http://facil.io","name":"facil.io","description":"facil.io - a light web application framework in C, with support for HTTP, WebSockets and Pub/Sub out of the box.","keywords":"C, web, framework, websockets, websocket, realtime, real-time, easy","image":"http://facil.io/website/logo/facil-io.svg","author":[{"@type":"Person","name":"Bo (Myst)","url":"http://stackoverflow.com/users/4025095/myst","email":"bo(at)facil.io"}],"sourceOrganization":{"@context":"http://schema.org","@type":"Organization","name":"Plezi","url":"http://facil.io","description":"facil.io - a light web application framework in C, with support for HTTP, WebSockets and Pub/Sub out of the box.","logo":"http://facil.io/website/logo/facil-io.svg","image":"http://facil.io/website/logo/facil-io.svg","email":"bo(at)facil.io","member":[{"@type":"Person","name":"Bo (Myst)","url":"http://stackoverflow.com/users/4025095/myst","email":"bo(at)facil.io"}]}}</script><meta content="facil.io" name="apple-mobile-web-app-title" /><meta content="facil.io - the C Web Application Framework" name="application-name" /><meta content="#b91d47" name="msapplication-TileColor" /><meta content="/mstile-144x144.png" name="msapplication-TileImage" /><meta content="#ffffff" name="theme-color" /></head><body><a href="/" id="logo"></a><input id="show_nav" type="checkbox" /><nav id="top_nav"><ul><li><a href="/0.7.x/index">Latest Docs</a></li><li><a href="https://github.com/boazsegev/facil.io" target="_blank">Source Code</a></li><li><a href="javascript: change_themes();" id="theme">Night Theme</a></li></ul></nav><input id="show_sidebar" type="checkbox" /><nav id="side_bar"><h2 id="version-0-6-x"><a href="/0.6.x/index">Version 0.6.x</a></h2>
<ul>
<li><a href="/0.6.x/api">API Overview</a></li>
<li><a href="/0.6.x/modules">The Modules</a></li>
</ul>
<h3 id="core-api"><a href="/0.6.x/facil">Core API</a></h3>
<ul>
<li><a href="/0.6.x/defer">Event scheduling</a></li>
<li><a href="/0.6.x/evio">Low Level Polling</a></li>
<li><a href="/0.6.x/sock">Low Level Sockets</a></li>
<li><a href="/0.6.x/fio_mem">Memory Allocation</a></li>
</ul>
<h3 id="extensions">Extensions</h3>
<ul>
<li><a href="/0.6.x/http">HTTP</a></li>
<li><a href="/0.6.x/websockets">WebSockets</a></li>
<li><a href="/0.6.x/pubsub">Pub/Sub</a></li>
<li><a href="/0.6.x/fio_cli">CLI (command line)</a></li>
</ul>
<h3 id="the-fiobj-types"><a href="/0.6.x/fiobj">The FIOBJ types</a></h3>
<ul>
<li><a href="/0.6.x/fiobj_primitives">Primitives</a></li>
<li><a href="/0.6.x/fiobj_numbers">Numbers</a></li>
<li><a href="/0.6.x/fiobj_str">Strings</a></li>
<li><a href="/0.6.x/fiobj_ary">Array</a></li>
<li><a href="/0.6.x/fiobj_hash">HashMap</a></li>
<li><a href="/0.6.x/fiobj_json">JSON</a></li>
</ul>
<h3 id="core-types"><a href="/0.6.x/types">Core Types</a></h3>
<ul>
<li><a href="/0.6.x/fio_ary">C Arrays</a></li>
<li><a href="/0.6.x/fio_hashmap">C HashMap</a></li>
<li><a href="/0.6.x/fio_llist">Linked Lists</a></li>
</ul>
</nav><div id="md_container"><div class='toc'><ul>
<li>
<a href="#simple-dynamic-arrays">Simple Dynamic Arrays</a>
<ul>
<li>
<a href="#overview">Overview</a>
</li>
<li>
<a href="#example">Example</a>
</li>
<li>
<a href="#types">Types</a>
</li>
<li>
<a href="#functions">Functions</a>
<ul>
<li>
<a href="#the-fio_ary_new-function">The <code>fio_ary_new</code> function</a>
</li>
<li>
<a href="#the-fio_ary_free-function">the <code>fio_ary_free</code> function</a>
</li>
<li>
<a href="#the-fio_ary_count-function">the <code>fio_ary_count</code> function</a>
</li>
<li>
<a href="#the-fio_ary_capa-function">the <code>fio_ary_capa</code> function</a>
</li>
<li>
<a href="#the-fio_ary_index-function">the <code>fio_ary_index</code> function</a>
</li>
<li>
<a href="#the-fio_ary_set-function">the <code>fio_ary_set</code> function</a>
</li>
<li>
<a href="#the-fio_ary_push-function">the <code>fio_ary_push</code> function</a>
</li>
<li>
<a href="#the-fio_ary_pop-function">the <code>fio_ary_pop</code> function</a>
</li>
<li>
<a href="#the-fio_ary_unshift-function">the <code>fio_ary_unshift</code> function</a>
</li>
<li>
<a href="#the-fio_ary_shift-function">the <code>fio_ary_shift</code> function</a>
</li>
<li>
<a href="#the-fio_ary_compact-function">the <code>fio_ary_compact</code> function</a>
</li>
<li>
<a href="#the-fio_ary_for-macro">the <code>FIO_ARY_FOR</code> macro</a>
</li>
<li>
<a href="#the-fio_ary_each-function">the <code>fio_ary_each</code> function</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div><h1 id="simple-dynamic-arrays">Simple Dynamic Arrays</h1>
<p>The simple dynamic array offers a simple data structure that manages only it&#39;s own memory (but not the memory of any objects placed in the array).</p>
<h2 id="overview">Overview</h2>
<p>The simple dynamic array type is included in a single file library, <code>fio_ary.h</code> that can be used independently as well.</p>
<p>The Core Array is designed to contain <code>void *</code> pointers and doesn&#39;t manage any memory except it&#39;s own.</p>
<p>As a general rule, facil.io doen&#39;s make assumptions about allocation / deallocation except where mentioned. A good example is the <code>sock_write</code> function that copies the data vs. <code>sock_write2</code> which asks about the correct deallocation function to be used (defaults to <code>free</code>) and takes ownership of the data.</p>
<h2 id="example">Example</h2>
<p>Here&#39;s a short example from <a href="types.md">the introduction to the simple core types</a>:</p>
<pre><code class='highlight'><span class="cp">#include "fio_ary.h"
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// The array container.</span>
<span class="n">fio_ary_s</span> <span class="n">ary</span><span class="p">;</span>
<span class="c1">// allocate and initialize internal data</span>
<span class="n">fio_ary_new</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ary</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="c1">// perform some actions</span>
<span class="n">fio_ary_push</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ary</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="mi">1</span><span class="p">);</span>
<span class="n">FIO_ARY_FOR</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ary</span><span class="p">,</span> <span class="n">pos</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"index: %lu == %lu</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="n">pos</span><span class="p">.</span><span class="n">i</span><span class="p">,</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="n">pos</span><span class="p">.</span><span class="n">obj</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// free the array's data to avoid memory leaks (doesn't free the objects)</span>
<span class="n">fio_ary_free</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ary</span><span class="p">);</span>
<span class="p">}</span>
</code></pre>
<p>Note that the Array container can be placed on the stack (as well as allocated using <code>malloc</code>), but the internal data must be allocated and deallocated using <code>fio_ary_new</code> and <code>fio_ary_free</code>.</p>
<h2 id="types">Types</h2>
<p>The Core Array uses the <code>fio_ary_s</code> type.</p>
<p>The data in in the <code>fio_ary_s</code> type shouldn&#39;t be accessed directly. Functional access should be preferred.</p>
<pre><code class='highlight'><span class="k">typedef</span> <span class="k">struct</span> <span class="n">fio_ary_s</span> <span class="p">{</span>
<span class="kt">size_t</span> <span class="n">start</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">end</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">capa</span><span class="p">;</span>
<span class="kt">void</span> <span class="o">**</span><span class="n">arry</span><span class="p">;</span>
<span class="p">}</span> <span class="n">fio_ary_s</span><span class="p">;</span>
</code></pre>
<h2 id="functions">Functions</h2>
<h3 id="the-fio_ary_new-function">The <code>fio_ary_new</code> function</h3>
<pre><code class='highlight'><span class="kt">void</span> <span class="n">fio_ary_new</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">capa</span><span class="p">)</span>
</code></pre>
<p>Initializes the array and allocates memory for it&#39;s internal data.</p>
<p>Note that <code>capa</code> indicates the <strong>initial</strong> (or <em>minimal</em>) capacity for the array, but the array can grow as long as memory allows.</p>
<p>This will assume that <code>ary</code> is uninitialized and overwrite any existing data.</p>
<h3 id="the-fio_ary_free-function">the <code>fio_ary_free</code> function</h3>
<pre><code class='highlight'><span class="kt">void</span> <span class="n">fio_ary_free</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">)</span>
</code></pre>
<p>Frees the array&#39;s internal data.</p>
<p>If the <code>ary</code>&#39;s container (the <code>fio_ary_s</code> object) was allocated using <code>malloc</code>, a subsequent call to <code>free(ary)</code> must be made.</p>
<h3 id="the-fio_ary_count-function">the <code>fio_ary_count</code> function</h3>
<pre><code class='highlight'><span class="kt">size_t</span> <span class="n">fio_ary_count</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">)</span>
</code></pre>
<p>Returns the number of elements in the Array.</p>
<h3 id="the-fio_ary_capa-function">the <code>fio_ary_capa</code> function</h3>
<pre><code class='highlight'><span class="kt">size_t</span> <span class="n">fio_ary_capa</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">)</span>
</code></pre>
<p>Returns the current, temporary, array capacity (it&#39;s dynamic).</p>
<h3 id="the-fio_ary_index-function">the <code>fio_ary_index</code> function</h3>
<pre><code class='highlight'><span class="kt">void</span> <span class="o">*</span><span class="n">fio_ary_index</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">,</span> <span class="kt">int64_t</span> <span class="n">pos</span><span class="p">)</span>
</code></pre>
<p>Returns the object placed in the Array, if any. Returns NULL if no data or if
the index is out of bounds.</p>
<p>Negative values are retrived from the end of the array. i.e., <code>-1</code>
is the last item.</p>
<p><code>fio_ary_entry</code> is an alias for <code>fiobj_ary_index</code>.</p>
<h3 id="the-fio_ary_set-function">the <code>fio_ary_set</code> function</h3>
<pre><code class='highlight'><span class="kt">void</span> <span class="o">*</span><span class="n">fio_ary_set</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">,</span> <span class="kt">int64_t</span> <span class="n">pos</span><span class="p">)</span>
</code></pre>
<p>Sets an object at the requested position.</p>
<p>Returns the old value, if any.</p>
<p>If an error occurs, the same data passed to the function is returned (test using <code>fiobj_ary_index</code>).</p>
<h3 id="the-fio_ary_push-function">the <code>fio_ary_push</code> function</h3>
<pre><code class='highlight'><span class="kt">int</span> <span class="n">fio_ary_push</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">)</span>
</code></pre>
<p>Pushes an object to the end of the Array. Returns -1 on error.</p>
<h3 id="the-fio_ary_pop-function">the <code>fio_ary_pop</code> function</h3>
<pre><code class='highlight'><span class="kt">void</span> <span class="o">*</span><span class="n">fio_ary_pop</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">)</span>
</code></pre>
<p>Pops an object from the end of the Array</p>
<p>Returns NULL if the object was NULL or the Array was empty.</p>
<h3 id="the-fio_ary_unshift-function">the <code>fio_ary_unshift</code> function</h3>
<pre><code class='highlight'><span class="kt">int</span> <span class="n">fio_ary_unshift</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">)</span>
</code></pre>
<p>Unshifts an object to the beginning of the Array. Returns -1 on error.</p>
<p>This could be expensive, causing <code>memmove</code>.</p>
<h3 id="the-fio_ary_shift-function">the <code>fio_ary_shift</code> function</h3>
<pre><code class='highlight'><span class="kt">void</span> <span class="o">*</span><span class="n">fio_ary_shift</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">)</span>
</code></pre>
<p>Shifts an object from the beginning of the Array.</p>
<p>Returns NULL if the object was NULL or the Array was empty.</p>
<h3 id="the-fio_ary_compact-function">the <code>fio_ary_compact</code> function</h3>
<pre><code class='highlight'><span class="kt">void</span> <span class="n">fio_ary_compact</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">)</span>
</code></pre>
<p>Removes any NULL <em>pointers</em> from an Array, keeping all other data in the
array.</p>
<p>This action is O(n) where n in the length of the array.</p>
<h3 id="the-fio_ary_for-macro">the <code>FIO_ARY_FOR</code> macro</h3>
<pre><code class='highlight'><span class="n">FIO_ARY_FOR</span><span class="p">(</span><span class="n">ary</span><span class="p">,</span> <span class="n">pos</span><span class="p">)</span>
</code></pre>
<p>Iterates through the list using a <code>for</code> loop.</p>
<p>Access the data with <code>pos.obj</code> and it&#39;s index with <code>pos.i</code>.</p>
<p>The <code>pos</code> variable can be named however you please (i.e. <code>FIO_ARY_FOR(&amp;bar, foo)</code> for <code>foo.i</code> and <code>foo.obj</code>).</p>
<h3 id="the-fio_ary_each-function">the <code>fio_ary_each</code> function</h3>
<pre><code class='highlight'><span class="kt">size_t</span> <span class="n">fio_ary_each</span><span class="p">(</span><span class="n">fio_ary_s</span> <span class="o">*</span><span class="n">ary</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">start_at</span><span class="p">,</span>
<span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">task</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">pt</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">),</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">arg</span><span class="p">);</span>
</code></pre>
<p>Iteration using a callback for each entry in the array.</p>
<p>The callback task function must accept an the entry data as well as an opaque
user pointer.</p>
<p>If the callback returns -1, the loop is broken. Any other value is ignored.</p>
<p>Returns the relative &quot;stop&quot; position, i.e., the number of items processed +
the starting point.</p>
</div><a href="/" id="sign"></a><div class="hidden" id="notice"><a class="notice_close" onclick="hide_notice()">X</a><div id="notice_text"></div></div><script>function change_themes() {
if(localStorage.getItem("theme") == 'dark') {
localStorage.setItem("theme", "light");
} else {
localStorage.setItem("theme", "dark");
}
$('body')[0].className = localStorage.getItem("theme");
set_theme_link();
$('#show_nav').attr('checked', false);
return false;
};
function sidebar_name() { return window.location.pathname.slice(0, window.location.pathname.lastIndexOf("/")); }
function on_sidebar_link(e) {
sessionStorage.setItem("sidebar.expect", sidebar_name());
sessionStorage.setItem("sidebar.pos", document.getElementById("side_bar").scrollTop);
}
function load_sidebar_pos() {
var e = document.getElementById("side_bar");
if(!e) {
console.warn("No sidebar detected");
return;
}
var expect = sidebar_name();
if(sessionStorage.getItem("sidebar.expect") == expect) {
e.scrollTo(0, parseInt(sessionStorage.getItem("sidebar.pos")));
} else {
sessionStorage.setItem("sidebar.expect", false);
sessionStorage.setItem("sidebar.pos", 0);
}
if(e) {
// add link callbacks
var links = document.links;
var count = links.length;
for (var i = 0; i < count; i++) {
var href = links[i].href;
if(href.startsWith(document.location.origin)) {
href = href.slice(document.location.origin.length);
}
if(href.startsWith(expect)) {
/* add link event */
links[i].addEventListener("click", on_sidebar_link);
}
}
}
};
load_sidebar_pos();
function set_theme_link() {
$("#theme").html( ( (localStorage.getItem("theme") == 'dark') ? "Day" : "Night") + " Theme" );
}
$('body')[0].className = (localStorage.getItem("theme") == 'dark') ? "dark" : "light";
set_theme_link();
function show_notice() { document.getElementById("notice").classList.remove('hidden'); };
function hide_notice() { document.getElementById("notice").classList.add('hidden'); };
$('#toc').on("touchstart", function (e) { return true; } );
$('#toc').on("hover", function (e) { return true; } );
// hljs.initHighlighting();
// Google Analytics
// if(location.hostname != "localhost") {
// (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
// (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
// m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
// })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
// ga('create', 'UA-69931401-1', 'auto');
// ga('send', 'pageview');
// }</script></body></html>