libdev.a

C Helper library
Log | Files | Refs | README | LICENSE | git clone https://git.ne02ptzero.me/git/libdev.a

commit 75c5788b51824331a318159f1856cafc80b3f869
parent 4a3fe6f36d0e2c4a25bf552561dcbd64c76e8c51
Author: Louis <louis@ne02ptzero.me>
Date:   Tue, 11 Oct 2016 18:14:22 +0200

Create master branch via GitHub
Diffstat:
Aindex.html | 551+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aparams.json | 7+++++++
Astylesheets/github-light.css | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astylesheets/normalize.css | 424+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astylesheets/stylesheet.css | 245+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 1351 insertions(+), 0 deletions(-)

diff --git a/index.html b/index.html @@ -0,0 +1,551 @@ +<!DOCTYPE html> +<html lang="en-us"> + <head> + <meta charset="UTF-8"> + <title>Libdev.a by Ne02ptzero</title> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel="stylesheet" type="text/css" href="stylesheets/normalize.css" media="screen"> + <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'> + <link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen"> + <link rel="stylesheet" type="text/css" href="stylesheets/github-light.css" media="screen"> + </head> + <body> + <section class="page-header"> + <h1 class="project-name">Libdev.a</h1> + <h2 class="project-tagline">A small helpers library for C language</h2> + <a href="https://github.com/Ne02ptzero/libdev.a" class="btn">View on GitHub</a> + <a href="https://github.com/Ne02ptzero/libdev.a/zipball/master" class="btn">Download .zip</a> + <a href="https://github.com/Ne02ptzero/libdev.a/tarball/master" class="btn">Download .tar.gz</a> + </section> + + <section class="main-content"> + <p align="center"> +<img src=".pic.png"><br> +<img src="https://img.shields.io/badge/language-C-blue.svg">   +<img src="https://img.shields.io/badge/license-Apache--2.0-yellow.svg">   +<img src="https://travis-ci.com/Ne02ptzero/libdev.a.svg?token=Ljxx7MA94JpJdnRDQunq&amp;branch=master"> +</p> + +<hr> + +<p align="center">A small developer library with some helpers in it</p> + +<p align="center"> + <a href="#linked-lists">Linked Lists</a> • <a href="#type-definitions">Types Definitions</a> • <a href="#singletons">Singletons</a> • <a href="#print-helpers">Print Helpers</a> • <a href="#assertions">Assertions</a> • <a href="#unit-tests">Unit Tests</a> +</p> + +<h2> +<a id="usage--installation" class="anchor" href="#usage--installation" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Usage &amp; Installation</h2> + +<h3> +<a id="clone-the-repository" class="anchor" href="#clone-the-repository" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Clone the repository</h3> + +<pre><code>git clone https://github.com/Ne02ptzero/libdev.a +</code></pre> + +<h3> +<a id="compile" class="anchor" href="#compile" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Compile</h3> + +<pre><code>make +</code></pre> + +<h3> +<a id="use" class="anchor" href="#use" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Use</h3> + +<p>You'll need to include the header file in your project's code</p> + +<div class="highlight highlight-source-c"><pre>#<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">&lt;</span>libdev.h<span class="pl-pds">&gt;</span></span></pre></div> + +<p>Compilation</p> + +<pre><code>gcc myfile.c -L library_directory -ldev +</code></pre> + +<h2 align="center"> +<a id="helpers" class="anchor" href="#helpers" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>HELPERS</h2> + +<h2> +<a id="linked-lists" class="anchor" href="#linked-lists" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Linked Lists</h2> + +<p>In libdev, all the linked lists are from the same struct</p> + +<div class="highlight highlight-source-c"><pre><span class="pl-k">typedef</span> <span class="pl-k">struct</span> s_list { + <span class="pl-k">void</span> *member; <span class="pl-c">// Actual member</span> + <span class="pl-c1">size_t</span> size; <span class="pl-c">// Size of the member</span> + <span class="pl-k">struct</span> s_list *next; <span class="pl-c">// Next in list</span> + <span class="pl-k">struct</span> s_list *prev; <span class="pl-c">// Prev in list</span> + <span class="pl-k">struct</span> s_list *head; <span class="pl-c">// Head of the list</span> +} t_list; +</pre></div> + +<p>In all my examples, I will use the following struct as an example. But you're free to use any type of data you want to. <code>void *</code> Magic !</p> + +<div class="highlight highlight-source-c"><pre><span class="pl-k">typedef</span> <span class="pl-k">struct</span> s_example { + <span class="pl-k">int</span> a; + <span class="pl-k">char</span> b; +} t_example;</pre></div> + +<p>Here's how to use it:</p> + +<h3> +<a id="add-a-member" class="anchor" href="#add-a-member" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Add a member</h3> + +<h4> +<a id="define" class="anchor" href="#define" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Define</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">list_add</span>(t_list *main_list, <span class="pl-k">void</span> *new_member, <span class="pl-c1">size_t</span> size_of_the_new_member); <span class="pl-c">// MACRO</span> +</pre></div> + +<h4> +<a id="example" class="anchor" href="#example" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<div class="highlight highlight-source-c"><pre>t_example member; +t_list *list = <span class="pl-c1">NULL</span>; <span class="pl-c">// Important, on the first creation the list pointer _needs_ to be NULL.</span> + +member.a = <span class="pl-c1">3</span>; +member.b = <span class="pl-s"><span class="pl-pds">'</span>l<span class="pl-pds">'</span></span>; +<span class="pl-en">list_add</span>(list, &amp;member, <span class="pl-k">sizeof</span>(t_example));</pre></div> + +<p>This code will add the <code>t_example member</code> to a new linked list. +Note there is no list initialization, you just need to set the pointer to NULL the first time you create it. +If the list already exist, the member will be added at the end.</p> + +<h3> +<a id="iteration-over-a-list" class="anchor" href="#iteration-over-a-list" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Iteration over a list</h3> + +<h4> +<a id="define-1" class="anchor" href="#define-1" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Define</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">list_for_each</span>(t_list *list_head, t_list *tmp, <span class="pl-k">void</span> *member); <span class="pl-c">// MACRO</span></pre></div> + +<h4> +<a id="example-1" class="anchor" href="#example-1" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<p>Our new struct as already been added in the list, now we want to iterate over it:</p> + +<div class="highlight highlight-source-c"><pre>t_list *tmp; +t_example *ptr; + +<span class="pl-en">list_for_each</span>(list, tmp, ptr) { + <span class="pl-c1">printf</span>(<span class="pl-s"><span class="pl-pds">"</span><span class="pl-c1">%d</span> - <span class="pl-c1">%c</span><span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, ptr-&gt;a, ptr-&gt;b); +}</pre></div> + +<p><code>list</code> is the head of the list pointer, <code>tmp</code> is just a <code>t_list</code> pointer (used to iterate without changing the head pointer), and <code>ptr</code> is your custom pointer. In this example, it's a <code>t_example *</code>, but you can do it with anything.</p> + +<h3> +<a id="reverse-iteration" class="anchor" href="#reverse-iteration" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Reverse Iteration</h3> + +<h4> +<a id="define-2" class="anchor" href="#define-2" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Define</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">list_for_each_rev</span>(t_list *list_head, t_list *tmp, <span class="pl-k">void</span> *member); <span class="pl-c">// MACRO</span></pre></div> + +<h4> +<a id="example-2" class="anchor" href="#example-2" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<p>Working the same way as <code>list_for_each</code>, but instead of beginning at the list head, and follow the members by <code>next</code>, it's beginning from the tail and follow the members by <code>prev</code></p> + +<h3> +<a id="add-after" class="anchor" href="#add-after" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Add After</h3> + +<h4> +<a id="define-3" class="anchor" href="#define-3" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Define</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">list_add_after</span>(t_list *list_head, t_list *list_entry, <span class="pl-k">void</span> *member, <span class="pl-c1">size_t</span> size_of_the_member); <span class="pl-c">// MACRO</span></pre></div> + +<h4> +<a id="example-3" class="anchor" href="#example-3" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<p>Working the same way as <code>list_add</code>, but instead of adding the new member at the end, it's adding the new member after the <code>list_entry</code> member.</p> + +<h3> +<a id="add-before" class="anchor" href="#add-before" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Add Before</h3> + +<h4> +<a id="define-4" class="anchor" href="#define-4" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Define</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">list_add_before</span>(t_list *list_head, t_list *list_entry, <span class="pl-k">void</span> *member, <span class="pl-c1">size_t</span> size_of_the_member); <span class="pl-c">// MACRO</span></pre></div> + +<h4> +<a id="example-4" class="anchor" href="#example-4" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<p>Working the same way as <code>list_add</code>, but instead of adding the new member at the end, it's adding the new member before the <code>list_entry</code> member.</p> + +<h3> +<a id="useful-functions" class="anchor" href="#useful-functions" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Useful functions</h3> + +<div class="highlight highlight-source-c"><pre><span class="pl-c1">size_t</span> <span class="pl-en">list_size</span>(t_list *list); <span class="pl-c">// Function</span></pre></div> + +<p>Get the list size.</p> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">list_tail</span>(t_list *head_list); <span class="pl-c">// MACRO</span></pre></div> + +<p>Return the last <code>t_list *</code> entry in <code>head_list</code>.</p> + +<div class="highlight highlight-source-c"><pre><span class="pl-k">void</span> *<span class="pl-en">list_get</span>(t_list *list_head, <span class="pl-k">void</span> *ptr, <span class="pl-c1">size_t</span> size);</pre></div> + +<p>Search into the <code>list_head</code> linked list, compare each <code>member</code> to <code>ptr</code> with <code>memcmp</code>. Return the <code>member</code> if found, <code>NULL</code> if not. <code>size</code> is for memory comparation.</p> + +<h2> +<a id="type-definitions" class="anchor" href="#type-definitions" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Type definitions</h2> + +<p>Types helpers in order to achieve easy bits / data manipulation</p> + +<table> +<thead> +<tr> +<th>Real Type</th> +<th>Name</th> +<th>Size (bits)</th> +<th>Size (Bytes)</th> +<th>Range</th> +</tr> +</thead> +<tbody> +<tr> +<td>signed char</td> +<td>s8_t</td> +<td>8</td> +<td>1</td> +<td>-128 to 127</td> +</tr> +<tr> +<td>unsigned char</td> +<td>u8_t</td> +<td>8</td> +<td>1</td> +<td>0 to 255</td> +</tr> +<tr> +<td>signed short</td> +<td>s16_t</td> +<td>16</td> +<td>2</td> +<td>-32,768 to 32,767</td> +</tr> +<tr> +<td>unsigned short</td> +<td>u16_t</td> +<td>16</td> +<td>2</td> +<td>0 to 65,535</td> +</tr> +<tr> +<td>signed int</td> +<td>s32_t</td> +<td>32</td> +<td>4</td> +<td>-2,147,483,648 to 2,147,483,647</td> +</tr> +<tr> +<td>unsigned int</td> +<td>u32_t</td> +<td>32</td> +<td>4</td> +<td>0 to 4,294,967,295</td> +</tr> +<tr> +<td>signed long long</td> +<td>s64_t</td> +<td>64</td> +<td>8</td> +<td>-9,223,372,036,854,775,807 to 9,223,372,036,854,775,807</td> +</tr> +<tr> +<td>unsigned long long</td> +<td>u64_t</td> +<td>64</td> +<td>8</td> +<td>0 to 18,446,744,073,709,551,615</td> +</tr> +</tbody> +</table> + +<h2> +<a id="singletons" class="anchor" href="#singletons" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Singletons</h2> + +<h4> +<a id="definition" class="anchor" href="#definition" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Definition</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-k">void</span> *<span class="pl-en">singleton_lists</span>(<span class="pl-c1">u8_t</span> list_type, <span class="pl-k">void</span> *ptr);</pre></div> + +<h4> +<a id="example-5" class="anchor" href="#example-5" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<p>Singletons are a way to avoid global variables. The way it works is quite simple: You set a variable to a function, this function stores it, and you can retrieve the same variable later. Let's see an example:</p> + +<div class="highlight highlight-source-c"><pre><span class="pl-k">enum</span> { + T_LISTS +}; + +<span class="pl-c">// ...</span> + +t_list *list; +<span class="pl-c">// We do some things with this list</span> +<span class="pl-en">singleton_lists</span>(T_LISTS, list); + +<span class="pl-c">// Some function, far far away ...</span> + +list = singleton_lists(T_LISTS, <span class="pl-c1">NULL</span>);</pre></div> + +<p>In order to set / retrieve the list, you need an unique identifier. In this example, an enum is used, but you can actually use what you want. Some notes though: The id used needs to be unique, and in a range of a <code>unsigned char</code>.</p> + +<p>Note: In this example, i use a <code>t_list</code> pointer, but you can pass any data you want to store. <code>void *</code> Magic !</p> + +<h2> +<a id="print-helpers" class="anchor" href="#print-helpers" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Print Helpers</h2> + +<h3> +<a id="info" class="anchor" href="#info" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Info</h3> + +<h4> +<a id="definition-1" class="anchor" href="#definition-1" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Definition</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-k">void</span> <span class="pl-en">info</span>(<span class="pl-k">char</span> *str, ...);</pre></div> + +<p>Print an information</p> + +<h4> +<a id="example-6" class="anchor" href="#example-6" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">info</span>(<span class="pl-s"><span class="pl-pds">"</span>This information is very important: <span class="pl-c1">%s</span><span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>No, not really<span class="pl-pds">"</span></span>);</pre></div> + +<h3> +<a id="warning" class="anchor" href="#warning" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Warning</h3> + +<h4> +<a id="definition-2" class="anchor" href="#definition-2" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Definition</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-k">void</span> <span class="pl-en">warning</span>(<span class="pl-k">char</span> *str, ...);</pre></div> + +<p>Print a warning (stderr output)</p> + +<h4> +<a id="example-7" class="anchor" href="#example-7" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">warning</span>(<span class="pl-s"><span class="pl-pds">"</span>Something bad happened ! Code: <span class="pl-c1">%d</span><span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, <span class="pl-c1">10</span>);</pre></div> + +<h3> +<a id="error" class="anchor" href="#error" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Error</h3> + +<h4> +<a id="definition-3" class="anchor" href="#definition-3" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Definition</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-k">void</span> <span class="pl-en">error</span>(<span class="pl-k">char</span> *str, ...);</pre></div> + +<p>Print an error (stderr output), print a backtrace then quit with code 1</p> + +<h4> +<a id="example-8" class="anchor" href="#example-8" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">error</span>(<span class="pl-s"><span class="pl-pds">"</span>We need to stop for this reason: <span class="pl-c1">%s</span><span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>UNACCEPTABLE CONDITIOOOOONS<span class="pl-pds">"</span></span>);</pre></div> + +<p>As you can see in the examples above, all the print functions use the printf format.</p> + +<h2> +<a id="assertions" class="anchor" href="#assertions" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Assertions</h2> + +<p>An assertion is a simple test on a condition. If the condition is false, the program stop.</p> + +<h4> +<a id="definition-4" class="anchor" href="#definition-4" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Definition</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">L_ASSERT</span>(condition); <span class="pl-c">// MACRO</span></pre></div> + +<h4> +<a id="example-9" class="anchor" href="#example-9" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-k">char</span> *str; + +str = malloc(<span class="pl-c1">10</span>); +<span class="pl-c">// Test the malloc</span> +<span class="pl-en">L_ASSERT</span>(str);</pre></div> + +<p>If the malloc failed, this is what the print look like:</p> + +<pre><code>&gt; Assertion (str) failed at main.c:29 +&gt; Function: function5 +&gt; Backtrace: +&gt; ./a.out(print_trace+0x19) [0x400cac] +&gt; ./a.out(function5+0x6b) [0x400c81] +&gt; ./a.out(function4+0xe) [0x400c14] +&gt; ./a.out(function3+0xe) [0x400c04] +&gt; ./a.out(function2+0xe) [0x400bf4] +&gt; ./a.out(function1+0xe) [0x400be4] +&gt; ./a.out(main+0x9) [0x400c8c] +&gt; /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7f2694011b45] +&gt; ./a.out() [0x400b09] +</code></pre> + +<p>Note that if you want the function names in your backtrace, you <em>must</em> compile your code with the <code>-rdynamic</code> flag.</p> + +<h2> +<a id="unit-tests" class="anchor" href="#unit-tests" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Unit Tests</h2> + +<h3> +<a id="declare-a-test" class="anchor" href="#declare-a-test" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Declare a test</h3> + +<h4> +<a id="definition-5" class="anchor" href="#definition-5" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Definition</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">TEST</span>(name); <span class="pl-c">// MACRO</span></pre></div> + +<h4> +<a id="example-10" class="anchor" href="#example-10" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">TEST</span>(test_name) { + ... +}</pre></div> + +<h4> +<a id="do-the-test" class="anchor" href="#do-the-test" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Do the test</h4> + +<p>Inside the test, you must use the <code>T_ASSERT</code> macro. Here's a simple example</p> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">TEST</span>(test_name) { + <span class="pl-k">int</span> i = <span class="pl-c1">1</span>; + <span class="pl-c1">T_ASSERT</span>(i == <span class="pl-c1">1</span>, <span class="pl-s"><span class="pl-pds">"</span>Bad initialization<span class="pl-pds">"</span></span>); + <span class="pl-k">return</span> TEST_SUCCESS; +}</pre></div> + +<p>In this example, we are testing than <code>i</code> is equal to 1. In order to do that, we call <code>T_ASSERT</code>. Same as <code>L_ASSERT</code>, this macro return an error if the condition is wrong. But rather than quitting the program, it just return the error to the test handler. Here's an example output if the test failed:</p> + +<pre><code>&gt; Testing test_name ... [ FAILED ] +&gt; Bad initialization: Test: 'i == 1', File main.c:33 +</code></pre> + +<p>As you see, the second parameter of the macro is the error returned if the test failed. +The error message max length is 250.</p> + +<p>You <em>must</em> finish all of your tests with the <code>TEST_SUCCESS</code> macro, in order to inform the test handler that all went well.</p> + +<h3> +<a id="register-a-test" class="anchor" href="#register-a-test" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Register a Test</h3> + +<p>Your test is now declared, but you must register it to the test handler. In libdev.a, all the tests are registered in groups.</p> + +<h4> +<a id="definition-6" class="anchor" href="#definition-6" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Definition</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">reg_test</span>(group, name); <span class="pl-c">// MACRO</span></pre></div> + +<h4> +<a id="example-11" class="anchor" href="#example-11" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<p>If you want to register the <code>test_name</code> test, you must write this.</p> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">reg_test</span>(<span class="pl-s"><span class="pl-pds">"</span>Test Group<span class="pl-pds">"</span></span>, test_name);</pre></div> + +<p>Groups are for ... grouped tests.</p> + +<h3> +<a id="launch-a-group-test" class="anchor" href="#launch-a-group-test" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Launch a Group Test</h3> + +<p>Now that all our tests are registered, time to launch them !</p> + +<h4> +<a id="definition-7" class="anchor" href="#definition-7" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Definition</h4> + +<div class="highlight highlight-source-c"><pre>t_test_results <span class="pl-en">test_group</span>(<span class="pl-k">char</span> *group); <span class="pl-c">// FUNCTION</span></pre></div> + +<h4> +<a id="example-12" class="anchor" href="#example-12" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<p>Here's how to launch:</p> + +<div class="highlight highlight-source-c"><pre><span class="pl-en">test_group</span>(<span class="pl-s"><span class="pl-pds">"</span>Test Group<span class="pl-pds">"</span></span>);</pre></div> + +<p>This function will run all the tests registered under the name <code>Test Group</code>, in order of insertion. +As you can see, this function return a structure. Here's the content:</p> + +<div class="highlight highlight-source-c"><pre><span class="pl-k">typedef</span> <span class="pl-k">struct</span> s_test_results { + <span class="pl-c1">size_t</span> success; + <span class="pl-c1">size_t</span> failed; + <span class="pl-c1">size_t</span> total; +} t_test_results;</pre></div> + +<p>Just a quick result of the tests. You can completly ignore it if you want to.</p> + +<p>Example output:</p> + +<pre><code>================================== linked_list =================================== +&gt; Testing list_add_null ... [ OK ] +&gt; Testing list_add_member ... [ OK ] +&gt; Testing list_add_member_head_list ... [ OK ] +&gt; Testing list_add_member_test_multiples ... [ FAILED ] +&gt; Head pointer is not right: Test: '!(ptr-&gt;next-&gt;head == ptr)', File main.c:48 +&gt; Testing list_for_each ... [ OK ] +&gt; Testing list_tail ... [ OK ] +&gt; Testing list_add_after ... [ OK ] +&gt; Testing list_add_before ... [ OK ] +&gt; Testing list_for_each_rev ... [ OK ] +&gt; Testing list_size ... [ OK ] +&gt; Results: Total: 10, Success: 9, Failed: 1. COVERAGE: 90% +</code></pre> + +<h3> +<a id="launch-all-the-tests" class="anchor" href="#launch-all-the-tests" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Launch all the Tests</h3> + +<h4> +<a id="defintion" class="anchor" href="#defintion" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Defintion</h4> + +<div class="highlight highlight-source-c"><pre><span class="pl-k">void</span> <span class="pl-en">test_all</span>(<span class="pl-k">void</span>); <span class="pl-c">// FUNCTION</span></pre></div> + +<h4> +<a id="example-13" class="anchor" href="#example-13" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Example</h4> + +<p>The usage is pretty straightforward:</p> + +<pre><code>test_all(); +</code></pre> + +<p>This will launch all the group test, one by one, then print a result.</p> + +<p>Example output:</p> + +<pre><code>================================== linked_list =================================== +&gt; Testing list_add_null ... [ OK ] +&gt; Testing list_add_member ... [ OK ] +&gt; Testing list_add_member_head_list ... [ OK ] +&gt; Testing list_add_member_test_multiples ... [ FAILED ] +&gt; Head pointer is not right: Test: '!(ptr-&gt;next-&gt;head == ptr)', File main.c:48 +&gt; Testing list_for_each ... [ OK ] +&gt; Testing list_tail ... [ OK ] +&gt; Testing list_add_after ... [ OK ] +&gt; Testing list_add_before ... [ OK ] +&gt; Testing list_for_each_rev ... [ OK ] +&gt; Testing list_size ... [ OK ] +&gt; Results: Total: 10, Success: 9, Failed: 1. COVERAGE: 90% +===================================== types ====================================== +&gt; Testing s8_t ... [ OK ] +&gt; Testing u8_t ... [ OK ] +&gt; Testing s16_t ... [ OK ] +&gt; Testing u16_t ... [ OK ] +&gt; Testing s32_t ... [ OK ] +&gt; Testing u32_t ... [ OK ] +&gt; Testing s64_t ... [ OK ] +&gt; Testing u64_t ... [ OK ] +&gt; Results: Total: 8, Success: 8, Failed: 0. COVERAGE: 100% +=================================== singletons =================================== +&gt; Testing singleton_set ... [ OK ] +&gt; Testing singleton_get ... [ OK ] +&gt; Testing singleton_replace ... [ OK ] +&gt; Results: Total: 3, Success: 3, Failed: 0. COVERAGE: 100% + +==================================== RESULTS ===================================== +&gt; TESTS SUCCESS: 20 +&gt; TESTS FAILED: 1 +&gt; TOTAL COVERAGE: 95% +</code></pre> + + <footer class="site-footer"> + <span class="site-footer-owner"><a href="https://github.com/Ne02ptzero/libdev.a">Libdev.a</a> is maintained by <a href="https://github.com/Ne02ptzero">Ne02ptzero</a>.</span> + + <span class="site-footer-credits">This page was generated by <a href="https://pages.github.com">GitHub Pages</a> using the <a href="https://github.com/jasonlong/cayman-theme">Cayman theme</a> by <a href="https://twitter.com/jasonlong">Jason Long</a>.</span> + </footer> + + </section> + + + </body> +</html> diff --git a/params.json b/params.json @@ -0,0 +1,6 @@ +{ + "name": "Libdev.a", + "tagline": "A small helpers library for C language", + "body": "<p align=\"center\">\r\n<img src=\".pic.png\" /><br />\r\n<img src=\"https://img.shields.io/badge/language-C-blue.svg\"/> &nbsp;\r\n<img src=\"https://img.shields.io/badge/license-Apache--2.0-yellow.svg\" /> &nbsp;\r\n<img src=\"https://travis-ci.com/Ne02ptzero/libdev.a.svg?token=Ljxx7MA94JpJdnRDQunq&branch=master\" />\r\n</p>\r\n\r\n-----------------------------------------------------------------\r\n\r\n<p align=\"center\">A small developer library with some helpers in it</p>\r\n<p align=\"center\"> \r\n <a href=\"#linked-lists\">Linked Lists</a> • <a href=\"#type-definitions\">Types Definitions</a> • <a href=\"#singletons\">Singletons</a> • <a href=\"#print-helpers\">Print Helpers</a> • <a href=\"#assertions\">Assertions</a> • <a href=\"#unit-tests\">Unit Tests</a>\r\n</p>\r\n\r\n\r\n\r\n## Usage & Installation\r\n### Clone the repository\r\n```\r\ngit clone https://github.com/Ne02ptzero/libdev.a\r\n```\r\n### Compile\r\n```\r\nmake\r\n```\r\n### Use\r\nYou'll need to include the header file in your project's code\r\n```C\r\n#include <libdev.h>\r\n```\r\nCompilation\r\n```\r\ngcc myfile.c -L library_directory -ldev\r\n```\r\n<h2 align=\"center\">HELPERS</h2>\r\n## Linked Lists\r\nIn libdev, all the linked lists are from the same struct\r\n```C\r\ntypedef struct\t\ts_list {\r\n\tvoid\t\t\t\t*member;\t// Actual member\r\n\tsize_t\t\t\t\tsize; \t\t// Size of the member\r\n\tstruct s_list\t\t*next;\t\t// Next in list\r\n\tstruct s_list\t\t*prev;\t\t// Prev in list\r\n\tstruct s_list\t\t*head;\t\t// Head of the list\r\n}\t\t\t\t\tt_list;\r\n\r\n```\r\nIn all my examples, I will use the following struct as an example. But you're free to use any type of data you want to. ```void *``` Magic !\r\n```C\r\ntypedef struct s_example {\r\n int a;\r\n char b;\r\n} t_example;\r\n```\r\nHere's how to use it:\r\n### Add a member\r\n#### Define\r\n```C\r\nlist_add(t_list *main_list, void *new_member, size_t size_of_the_new_member); // MACRO\r\n\r\n```\r\n#### Example\r\n```C\r\nt_example\t\tmember;\r\nt_list\t\t\t*list = NULL; // Important, on the first creation the list pointer _needs_ to be NULL.\r\n\r\nmember.a = 3;\r\nmember.b = 'l';\r\nlist_add(list, &member, sizeof(t_example));\r\n```\r\nThis code will add the ```t_example member``` to a new linked list.\r\nNote there is no list initialization, you just need to set the pointer to NULL the first time you create it.\r\nIf the list already exist, the member will be added at the end.\r\n### Iteration over a list\r\n#### Define\r\n```C\r\nlist_for_each(t_list *list_head, t_list *tmp, void *member); // MACRO\r\n```\r\n#### Example\r\nOur new struct as already been added in the list, now we want to iterate over it:\r\n```C\r\nt_list\t\t*tmp;\r\nt_example\t*ptr;\r\n\r\nlist_for_each(list, tmp, ptr) {\r\n\tprintf(\"%d - %c\\n\", ptr->a, ptr->b);\r\n}\r\n```\r\n```list``` is the head of the list pointer, ```tmp``` is just a ```t_list``` pointer (used to iterate without changing the head pointer), and ```ptr``` is your custom pointer. In this example, it's a ```t_example *```, but you can do it with anything.\r\n### Reverse Iteration\r\n#### Define\r\n```C\r\nlist_for_each_rev(t_list *list_head, t_list *tmp, void *member); // MACRO\r\n```\r\n#### Example\r\nWorking the same way as ```list_for_each```, but instead of beginning at the list head, and follow the members by ```next```, it's beginning from the tail and follow the members by ```prev```\r\n### Add After\r\n#### Define\r\n```C\r\nlist_add_after(t_list *list_head, t_list *list_entry, void *member, size_t size_of_the_member); // MACRO\r\n```\r\n#### Example\r\nWorking the same way as ```list_add```, but instead of adding the new member at the end, it's adding the new member after the ```list_entry``` member.\r\n### Add Before\r\n#### Define\r\n```C\r\nlist_add_before(t_list *list_head, t_list *list_entry, void *member, size_t size_of_the_member); // MACRO\r\n```\r\n#### Example\r\nWorking the same way as ```list_add```, but instead of adding the new member at the end, it's adding the new member before the ```list_entry``` member.\r\n### Useful functions\r\n```C\r\nsize_t\t\tlist_size(t_list *list); // Function\r\n```\r\nGet the list size.\r\n```C\r\nlist_tail(t_list *head_list); // MACRO\r\n```\r\nReturn the last ```t_list *``` entry in ```head_list```.\r\n```C\r\nvoid\t*list_get(t_list *list_head, void *ptr, size_t size);\r\n```\r\nSearch into the ```list_head``` linked list, compare each ```member``` to ```ptr``` with ```memcmp```. Return the ```member``` if found, ```NULL``` if not. ```size``` is for memory comparation.\r\n## Type definitions\r\nTypes helpers in order to achieve easy bits / data manipulation\r\n\r\nReal Type | Name | Size (bits) | Size (Bytes) | Range\r\n--------- | ---- | ----------- | ------------ | -----\r\nsigned char | s8_t | 8 | 1 | -128 to 127\r\nunsigned char | u8_t | 8 | 1 | 0 to 255\r\nsigned short | s16_t | 16 | 2 | -32,768 to 32,767\r\nunsigned short | u16_t | 16 | 2 | 0 to 65,535\r\nsigned int | s32_t | 32 | 4 | -2,147,483,648 to 2,147,483,647\r\nunsigned int | u32_t | 32 | 4 | 0 to 4,294,967,295\r\nsigned long long | s64_t | 64 | 8 | -9,223,372,036,854,775,807 to 9,223,372,036,854,775,807\r\nunsigned long long | u64_t | 64 | 8 | 0 to 18,446,744,073,709,551,615\r\n\r\n## Singletons\r\n#### Definition\r\n```C\r\nvoid\t\t*singleton_lists(u8_t list_type, void *ptr);\r\n```\r\n#### Example\r\nSingletons are a way to avoid global variables. The way it works is quite simple: You set a variable to a function, this function stores it, and you can retrieve the same variable later. Let's see an example:\r\n```C\r\nenum {\r\n T_LISTS\r\n};\r\n\r\n// ...\r\n\r\nt_list\t\t*list;\r\n// We do some things with this list\r\nsingleton_lists(T_LISTS, list);\r\n\r\n// Some function, far far away ...\r\n\r\nlist = singleton_lists(T_LISTS, NULL);\r\n```\r\nIn order to set / retrieve the list, you need an unique identifier. In this example, an enum is used, but you can actually use what you want. Some notes though: The id used needs to be unique, and in a range of a ```unsigned char```.\r\n\r\nNote: In this example, i use a ```t_list``` pointer, but you can pass any data you want to store. ```void *``` Magic !\r\n## Print Helpers\r\n### Info\r\n#### Definition\r\n```C\r\nvoid\t\tinfo(char *str, ...);\r\n```\r\nPrint an information\r\n#### Example\r\n```C\r\ninfo(\"This information is very important: %s\\n\", \"No, not really\");\r\n```\r\n### Warning\r\n#### Definition\r\n```C\r\nvoid\t\twarning(char *str, ...);\r\n```\r\nPrint a warning (stderr output)\r\n#### Example\r\n```C\r\nwarning(\"Something bad happened ! Code: %d\\n\", 10);\r\n```\r\n### Error\r\n#### Definition\r\n```C\r\nvoid\t\terror(char *str, ...);\r\n```\r\nPrint an error (stderr output), print a backtrace then quit with code 1\r\n#### Example\r\n```C\r\nerror(\"We need to stop for this reason: %s\\n\", \"UNACCEPTABLE CONDITIOOOOONS\");\r\n```\r\n\r\nAs you can see in the examples above, all the print functions use the printf format.\r\n\r\n## Assertions\r\nAn assertion is a simple test on a condition. If the condition is false, the program stop.\r\n#### Definition\r\n```C\r\nL_ASSERT(condition); // MACRO\r\n```\r\n#### Example\r\n```C\r\nchar\t*str;\r\n\r\nstr = malloc(10);\r\n// Test the malloc\r\nL_ASSERT(str);\r\n```\r\nIf the malloc failed, this is what the print look like:\r\n```\r\n> Assertion (str) failed at main.c:29\r\n> Function: function5\r\n> Backtrace:\r\n> ./a.out(print_trace+0x19) [0x400cac]\r\n> ./a.out(function5+0x6b) [0x400c81]\r\n> ./a.out(function4+0xe) [0x400c14]\r\n> ./a.out(function3+0xe) [0x400c04]\r\n> ./a.out(function2+0xe) [0x400bf4]\r\n> ./a.out(function1+0xe) [0x400be4]\r\n> ./a.out(main+0x9) [0x400c8c]\r\n> /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7f2694011b45]\r\n> ./a.out() [0x400b09]\r\n```\r\nNote that if you want the function names in your backtrace, you _must_ compile your code with the ```-rdynamic``` flag.\r\n\r\n## Unit Tests\r\n### Declare a test\r\n#### Definition\r\n```C\r\nTEST(name); // MACRO\r\n```\r\n#### Example\r\n```C\r\nTEST(test_name) {\r\n\t...\r\n}\r\n```\r\n#### Do the test\r\nInside the test, you must use the ```T_ASSERT``` macro. Here's a simple example\r\n```C\r\nTEST(test_name) {\r\n\tint\ti = 1;\r\n\tT_ASSERT(i == 1, \"Bad initialization\");\r\n\treturn TEST_SUCCESS;\r\n}\r\n```\r\nIn this example, we are testing than ```i``` is equal to 1. In order to do that, we call ```T_ASSERT```. Same as ```L_ASSERT```, this macro return an error if the condition is wrong. But rather than quitting the program, it just return the error to the test handler. Here's an example output if the test failed:\r\n```\r\n> Testing test_name ... [ FAILED ]\r\n> \tBad initialization: Test: 'i == 1', File main.c:33\r\n```\r\nAs you see, the second parameter of the macro is the error returned if the test failed.\r\nThe error message max length is 250.\r\n\r\nYou *must* finish all of your tests with the ```TEST_SUCCESS``` macro, in order to inform the test handler that all went well.\r\n\r\n### Register a Test\r\nYour test is now declared, but you must register it to the test handler. In libdev.a, all the tests are registered in groups.\r\n#### Definition\r\n```C\r\nreg_test(group, name); // MACRO\r\n```\r\n#### Example\r\nIf you want to register the ```test_name``` test, you must write this.\r\n```C\r\nreg_test(\"Test Group\", test_name);\r\n```\r\nGroups are for ... grouped tests.\r\n### Launch a Group Test\r\nNow that all our tests are registered, time to launch them !\r\n#### Definition\r\n```C\r\nt_test_results\ttest_group(char *group); // FUNCTION\r\n```\r\n#### Example\r\nHere's how to launch:\r\n```C\r\ntest_group(\"Test Group\");\r\n```\r\nThis function will run all the tests registered under the name ```Test Group```, in order of insertion.\r\nAs you can see, this function return a structure. Here's the content:\r\n```C\r\ntypedef struct\t\ts_test_results {\r\n\tsize_t\t\t\t\tsuccess;\r\n\tsize_t\t\t\t\tfailed;\r\n\tsize_t\t\t\t\ttotal;\r\n}\t\t\t\t\tt_test_results;\r\n```\r\nJust a quick result of the tests. You can completly ignore it if you want to.\r\n\r\nExample output:\r\n```\r\n================================== linked_list ===================================\r\n> Testing list_add_null ... [ OK ]\r\n> Testing list_add_member ... [ OK ]\r\n> Testing list_add_member_head_list ... [ OK ]\r\n> Testing list_add_member_test_multiples ... [ FAILED ]\r\n> \tHead pointer is not right: Test: '!(ptr->next->head == ptr)', File main.c:48\r\n> Testing list_for_each ... [ OK ]\r\n> Testing list_tail ... [ OK ]\r\n> Testing list_add_after ... [ OK ]\r\n> Testing list_add_before ... [ OK ]\r\n> Testing list_for_each_rev ... [ OK ]\r\n> Testing list_size ... [ OK ]\r\n> Results: Total: 10, Success: 9, Failed: 1. COVERAGE: 90%\r\n```\r\n\r\n### Launch all the Tests\r\n#### Defintion\r\n```C\r\nvoid\t\t\ttest_all(void); // FUNCTION\r\n```\r\n#### Example\r\nThe usage is pretty straightforward:\r\n```\r\ntest_all();\r\n```\r\nThis will launch all the group test, one by one, then print a result.\r\n\r\nExample output:\r\n```\r\n================================== linked_list ===================================\r\n> Testing list_add_null ... [ OK ]\r\n> Testing list_add_member ... [ OK ]\r\n> Testing list_add_member_head_list ... [ OK ]\r\n> Testing list_add_member_test_multiples ... [ FAILED ]\r\n> \tHead pointer is not right: Test: '!(ptr->next->head == ptr)', File main.c:48\r\n> Testing list_for_each ... [ OK ]\r\n> Testing list_tail ... [ OK ]\r\n> Testing list_add_after ... [ OK ]\r\n> Testing list_add_before ... [ OK ]\r\n> Testing list_for_each_rev ... [ OK ]\r\n> Testing list_size ... [ OK ]\r\n> Results: Total: 10, Success: 9, Failed: 1. COVERAGE: 90%\r\n===================================== types ======================================\r\n> Testing s8_t ... [ OK ]\r\n> Testing u8_t ... [ OK ]\r\n> Testing s16_t ... [ OK ]\r\n> Testing u16_t ... [ OK ]\r\n> Testing s32_t ... [ OK ]\r\n> Testing u32_t ... [ OK ]\r\n> Testing s64_t ... [ OK ]\r\n> Testing u64_t ... [ OK ]\r\n> Results: Total: 8, Success: 8, Failed: 0. COVERAGE: 100%\r\n=================================== singletons ===================================\r\n> Testing singleton_set ... [ OK ]\r\n> Testing singleton_get ... [ OK ]\r\n> Testing singleton_replace ... [ OK ]\r\n> Results: Total: 3, Success: 3, Failed: 0. COVERAGE: 100%\r\n\r\n==================================== RESULTS =====================================\r\n> TESTS SUCCESS:\t20\r\n> TESTS FAILED:\t\t1\r\n> TOTAL COVERAGE:\t95%\r\n```", + "note": "Don't delete this file! It's used internally to help with page regeneration." +}+ \ No newline at end of file diff --git a/stylesheets/github-light.css b/stylesheets/github-light.css @@ -0,0 +1,124 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016 GitHub, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +.pl-c /* comment */ { + color: #969896; +} + +.pl-c1 /* constant, variable.other.constant, support, meta.property-name, support.constant, support.variable, meta.module-reference, markup.raw, meta.diff.header */, +.pl-s .pl-v /* string variable */ { + color: #0086b3; +} + +.pl-e /* entity */, +.pl-en /* entity.name */ { + color: #795da3; +} + +.pl-smi /* variable.parameter.function, storage.modifier.package, storage.modifier.import, storage.type.java, variable.other */, +.pl-s .pl-s1 /* string source */ { + color: #333; +} + +.pl-ent /* entity.name.tag */ { + color: #63a35c; +} + +.pl-k /* keyword, storage, storage.type */ { + color: #a71d5d; +} + +.pl-s /* string */, +.pl-pds /* punctuation.definition.string, string.regexp.character-class */, +.pl-s .pl-pse .pl-s1 /* string punctuation.section.embedded source */, +.pl-sr /* string.regexp */, +.pl-sr .pl-cce /* string.regexp constant.character.escape */, +.pl-sr .pl-sre /* string.regexp source.ruby.embedded */, +.pl-sr .pl-sra /* string.regexp string.regexp.arbitrary-repitition */ { + color: #183691; +} + +.pl-v /* variable */ { + color: #ed6a43; +} + +.pl-id /* invalid.deprecated */ { + color: #b52a1d; +} + +.pl-ii /* invalid.illegal */ { + color: #f8f8f8; + background-color: #b52a1d; +} + +.pl-sr .pl-cce /* string.regexp constant.character.escape */ { + font-weight: bold; + color: #63a35c; +} + +.pl-ml /* markup.list */ { + color: #693a17; +} + +.pl-mh /* markup.heading */, +.pl-mh .pl-en /* markup.heading entity.name */, +.pl-ms /* meta.separator */ { + font-weight: bold; + color: #1d3e81; +} + +.pl-mq /* markup.quote */ { + color: #008080; +} + +.pl-mi /* markup.italic */ { + font-style: italic; + color: #333; +} + +.pl-mb /* markup.bold */ { + font-weight: bold; + color: #333; +} + +.pl-md /* markup.deleted, meta.diff.header.from-file */ { + color: #bd2c00; + background-color: #ffecec; +} + +.pl-mi1 /* markup.inserted, meta.diff.header.to-file */ { + color: #55a532; + background-color: #eaffea; +} + +.pl-mdr /* meta.diff.range */ { + font-weight: bold; + color: #795da3; +} + +.pl-mo /* meta.output */ { + color: #1d3e81; +} + diff --git a/stylesheets/normalize.css b/stylesheets/normalize.css @@ -0,0 +1,424 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/** + * Address styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove border when inside `a` element in IE 8/9/10. + */ + +img { + border: 0; +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/stylesheets/stylesheet.css b/stylesheets/stylesheet.css @@ -0,0 +1,245 @@ +* { + box-sizing: border-box; } + +body { + padding: 0; + margin: 0; + font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 1.5; + color: #606c71; } + +a { + color: #1e6bb8; + text-decoration: none; } + a:hover { + text-decoration: underline; } + +.btn { + display: inline-block; + margin-bottom: 1rem; + color: rgba(255, 255, 255, 0.7); + background-color: rgba(255, 255, 255, 0.08); + border-color: rgba(255, 255, 255, 0.2); + border-style: solid; + border-width: 1px; + border-radius: 0.3rem; + transition: color 0.2s, background-color 0.2s, border-color 0.2s; } + .btn + .btn { + margin-left: 1rem; } + +.btn:hover { + color: rgba(255, 255, 255, 0.8); + text-decoration: none; + background-color: rgba(255, 255, 255, 0.2); + border-color: rgba(255, 255, 255, 0.3); } + +@media screen and (min-width: 64em) { + .btn { + padding: 0.75rem 1rem; } } + +@media screen and (min-width: 42em) and (max-width: 64em) { + .btn { + padding: 0.6rem 0.9rem; + font-size: 0.9rem; } } + +@media screen and (max-width: 42em) { + .btn { + display: block; + width: 100%; + padding: 0.75rem; + font-size: 0.9rem; } + .btn + .btn { + margin-top: 1rem; + margin-left: 0; } } + +.page-header { + color: #fff; + text-align: center; + background-color: #159957; + background-image: linear-gradient(120deg, #155799, #159957); } + +@media screen and (min-width: 64em) { + .page-header { + padding: 5rem 6rem; } } + +@media screen and (min-width: 42em) and (max-width: 64em) { + .page-header { + padding: 3rem 4rem; } } + +@media screen and (max-width: 42em) { + .page-header { + padding: 2rem 1rem; } } + +.project-name { + margin-top: 0; + margin-bottom: 0.1rem; } + +@media screen and (min-width: 64em) { + .project-name { + font-size: 3.25rem; } } + +@media screen and (min-width: 42em) and (max-width: 64em) { + .project-name { + font-size: 2.25rem; } } + +@media screen and (max-width: 42em) { + .project-name { + font-size: 1.75rem; } } + +.project-tagline { + margin-bottom: 2rem; + font-weight: normal; + opacity: 0.7; } + +@media screen and (min-width: 64em) { + .project-tagline { + font-size: 1.25rem; } } + +@media screen and (min-width: 42em) and (max-width: 64em) { + .project-tagline { + font-size: 1.15rem; } } + +@media screen and (max-width: 42em) { + .project-tagline { + font-size: 1rem; } } + +.main-content :first-child { + margin-top: 0; } +.main-content img { + max-width: 100%; } +.main-content h1, .main-content h2, .main-content h3, .main-content h4, .main-content h5, .main-content h6 { + margin-top: 2rem; + margin-bottom: 1rem; + font-weight: normal; + color: #159957; } +.main-content p { + margin-bottom: 1em; } +.main-content code { + padding: 2px 4px; + font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 0.9rem; + color: #383e41; + background-color: #f3f6fa; + border-radius: 0.3rem; } +.main-content pre { + padding: 0.8rem; + margin-top: 0; + margin-bottom: 1rem; + font: 1rem Consolas, "Liberation Mono", Menlo, Courier, monospace; + color: #567482; + word-wrap: normal; + background-color: #f3f6fa; + border: solid 1px #dce6f0; + border-radius: 0.3rem; } + .main-content pre > code { + padding: 0; + margin: 0; + font-size: 0.9rem; + color: #567482; + word-break: normal; + white-space: pre; + background: transparent; + border: 0; } +.main-content .highlight { + margin-bottom: 1rem; } + .main-content .highlight pre { + margin-bottom: 0; + word-break: normal; } +.main-content .highlight pre, .main-content pre { + padding: 0.8rem; + overflow: auto; + font-size: 0.9rem; + line-height: 1.45; + border-radius: 0.3rem; } +.main-content pre code, .main-content pre tt { + display: inline; + max-width: initial; + padding: 0; + margin: 0; + overflow: initial; + line-height: inherit; + word-wrap: normal; + background-color: transparent; + border: 0; } + .main-content pre code:before, .main-content pre code:after, .main-content pre tt:before, .main-content pre tt:after { + content: normal; } +.main-content ul, .main-content ol { + margin-top: 0; } +.main-content blockquote { + padding: 0 1rem; + margin-left: 0; + color: #819198; + border-left: 0.3rem solid #dce6f0; } + .main-content blockquote > :first-child { + margin-top: 0; } + .main-content blockquote > :last-child { + margin-bottom: 0; } +.main-content table { + display: block; + width: 100%; + overflow: auto; + word-break: normal; + word-break: keep-all; } + .main-content table th { + font-weight: bold; } + .main-content table th, .main-content table td { + padding: 0.5rem 1rem; + border: 1px solid #e9ebec; } +.main-content dl { + padding: 0; } + .main-content dl dt { + padding: 0; + margin-top: 1rem; + font-size: 1rem; + font-weight: bold; } + .main-content dl dd { + padding: 0; + margin-bottom: 1rem; } +.main-content hr { + height: 2px; + padding: 0; + margin: 1rem 0; + background-color: #eff0f1; + border: 0; } + +@media screen and (min-width: 64em) { + .main-content { + max-width: 64rem; + padding: 2rem 6rem; + margin: 0 auto; + font-size: 1.1rem; } } + +@media screen and (min-width: 42em) and (max-width: 64em) { + .main-content { + padding: 2rem 4rem; + font-size: 1.1rem; } } + +@media screen and (max-width: 42em) { + .main-content { + padding: 2rem 1rem; + font-size: 1rem; } } + +.site-footer { + padding-top: 2rem; + margin-top: 2rem; + border-top: solid 1px #eff0f1; } + +.site-footer-owner { + display: block; + font-weight: bold; } + +.site-footer-credits { + color: #819198; } + +@media screen and (min-width: 64em) { + .site-footer { + font-size: 1rem; } } + +@media screen and (min-width: 42em) and (max-width: 64em) { + .site-footer { + font-size: 1rem; } } + +@media screen and (max-width: 42em) { + .site-footer { + font-size: 0.9rem; } }