Octaspire Core Manual

Table of Contents

About
Building the amalgamated source release
Quick tour of library features
Using the development repository

1. About

Octaspire Core is a container, UTF-8 and utility library written in standard *C99*. Core should compile cleanly without any warnings using -Wall -Wextra on any compiler supporting a subset of C99. Currently it is tested with gcc, clang, Tiny C Compiler (tcc), Portable C compiler (pcc) and Plan9's 8c.

Octaspire Core is free and open source software, licensed under the Apache License, Version 2.0. See file LICENSE in the source distribution for more information.

Core uses Semantic Versioning 2.0.0 version numbering scheme. As long as the MAJOR version number is zero anything can change at any time, even in backwards incompatible manner.

2. Building the amalgamated source release

The amalgamated source release is the recommended way of using Core, if you don't need to modify Core itself. To use the amalgamated release, you will need only a C compiler and C standard library supporting a subset of C99.

2.1 Linux, FreeBSD, OpenBSD, NetBSD, OpenIndiana, DragonFly BSD, MidnightBSD, MINIX 3, Haiku, macOS, Termux, AROS

curl -O octaspire.com/core.tar.bz2
curl -O https://octaspire.io/core.sha512
sha512sum -c core.sha512
tar jxf core.tar.bz2
cd core
sh how-to-build/YOUR_PLATFORM_NAME_HERE.XX

Replace YOUR_PLATFORM_NAME_HERE.XX with FreeBSD.sh, NetBSD.sh, OpenBSD.sh, OpenIndiana.sh, DragonFlyBSD.sh, MidnightBSD.sh, linux.sh, minix3.sh, haiku.sh, macOS.sh, termux.sh or AROS.sh. More scripts for different platforms will be added later.

2.2 Windows using MinGW and Git

Download and install MinGW into a directory, for example into C:\MinGW. Install the GCC compiler. Add MinGW\bin into the PATH (for example, if you installed into C:\MinGW, add C:\MinGW\bin into the PATH).

Download and install Git for Windows.

Start Git Bash and run the following commands:

git clone https://github.com/octaspire/core.git
cd core/release
how-to-build/windows.sh

Start Windows Command Prompt and change directory to the same release directory, as above. Run examples and programs in the Command Prompt window (NOT in the Git Bash window).

2.3 AmigaOS 4.x

Download and install AmigaOS SDK. Download and extract bzip2 to get bzip2_68k executable. Download the amalgamated Core source release.

Open Shell window and run the following commands:

bzip2_68k -dk core.tar.bz2
tar xf core.tar
cd core
sh how-to-build/AmigaOS41.sh

2.4 Running unit tests

This is all there should be to it; when make finishes, everything should be ready.

To run the unit tests:

test/octaspire-core-test-runner

3. Quick tour of library features

Here we take a quick look at the features of the library.

3.1 Naming

C doesn't have namespaces. To prevent name collisions, all names in the library are prefixed with octaspire_. For example, octaspire_string_t is the string type and octaspire_string_new is one of the functions that create new strings. octaspire_vector_tis the vector type octaspire_map_t is the hash-map type.

3.2 UTF-8 Strings

Strings in Core have full UTF-8 support. Because ASCII strings are, by defininition, valid UTF-8, Core strings can be used to store "old" ASCII text or characters of almost any human script. Below is a short example of strings:

/****************************************************
 To compile this file from the 'examples' directory:
 c99 -Wall -Wextra -pedantic -I ../../include/ \
     string-example.c -lm -L ../../build/      \
     -loctaspire-core -o string-example
****************************************************/
#include <stdio.h>
#define OCTASPIRE_CORE_AMALGAMATED_IMPLEMENTATION
#include "octaspire-core-amalgamated.c"

int main(void)
{
    octaspire_allocator_t *allocator =
        octaspire_allocator_new(0);

    octaspire_string_t *myStr =
        octaspire_string_new(
            "Hello world!",
            allocator);

    printf(
        "String is \"%s\"\n",
        octaspire_string_get_c_string(
            myStr));

    octaspire_string_release(myStr);
    myStr = 0;

    octaspire_allocator_release(allocator);
    allocator = 0;

    return 0;
}

3.3 Vector

Vector is a linear container that stores its elements in continuous blocks of memory. Vector can be used to store any data, including pointers or blocks of memory.

/***************************************************
 To compile this file from the 'examples' directory:
 c99 -Wall -Wextra -pedantic              \
     -I ../../include/ vector-example.c   \
     -lm -L ../../build/ -loctaspire-core \
     -o vector-example
***************************************************/
#include <stdio.h>
#define OCTASPIRE_CORE_AMALGAMATED_IMPLEMENTATION
#include "octaspire-core-amalgamated.c"

int main(void)
{
    octaspire_allocator_t *allocator =
        octaspire_allocator_new(0);

    octaspire_vector_t *v =
        octaspire_vector_new(
            sizeof(octaspire_string_t*),
            true,
            (octaspire_vector_element_callback_t)
                octaspire_string_release,
            allocator);

    for (size_t i = 0; i < 10; ++i)
    {
        octaspire_string_t *s =
            octaspire_string_new_format(
                allocator,
                "Hello %zu world!",
                i);

        if (!octaspire_vector_push_back_element(
                v,
                &s))
        {
            printf("Cannot insert string\n");
        }
    }

    for (size_t i = 0;
         i < octaspire_vector_get_length(v);
         ++i)
    {
        octaspire_string_t const * const s =
            octaspire_vector_get_element_at_const(
                v,
                i);

        printf(
            "String %zu. is: %s\n",
            i,
            octaspire_string_get_c_string(
                s));
    }

    octaspire_vector_release(v);
    v = 0;

    octaspire_allocator_release(allocator);
    allocator = 0;

    return 0;
}

3.4 List

TODO

3.5 Queue

TODO

3.6 Pair

TODO

3.7 Hash map

Hash map allows the retrieval of values in a constant time using a value, like a string, as a key. Hash maps, like all the other Core containers, can store any kind of data as values, including pointers or arbitrary blocks of memory.

/*****************************************************
 To compile this file from the 'examples' directory:
 c99 -Wall -Wextra -pedantic -I ../../include/ \
     hash-map-example.c -lm -L ../../build/    \
     -loctaspire-core -o hash-map-example
 ****************************************************/
#include <stdio.h>
#define OCTASPIRE_CORE_AMALGAMATED_IMPLEMENTATION
#include "octaspire-core-amalgamated.c"

int main(void)
{
    octaspire_allocator_t *allocator =
        octaspire_allocator_new(0);

    octaspire_map_t * h =
        octaspire_map_new_with_octaspire_string_keys(
            sizeof(float),
            false,
            (octaspire_map_element_callback_t)0,
            allocator);


    for (size_t i = 0; i < 10; ++i)
    {
        octaspire_string_t *s =
            octaspire_string_new_format(
                allocator,
                "Item %zu!",
                i);

        float const value = i * 3.14;

        if (!octaspire_map_put(
            h,
            octaspire_string_get_hash(
                s),
            &s,
            &value))
        {
            printf(
                "Cannot insert element\n");
        }
    }

    for (size_t i = 0;
         i < octaspire_map_get_number_of_elements(h);
         ++i)
    {
        octaspire_string_t *s =
            octaspire_string_new_format(
                allocator,
                "Item %zu!",
                i);

        octaspire_map_element_t
            const * const element =
            octaspire_map_get_const(
                h,
                octaspire_string_get_hash(s),
                &s);

        float const value = *(float const * const)
            octaspire_map_element_get_value(
                element);

        printf(
            "%s -> %f\n",
            octaspire_string_get_c_string(s),
            value);

        octaspire_string_release(s);
        s = 0;
    }

    octaspire_map_release(h);
    h = 0;

    octaspire_allocator_release(allocator);
    allocator = 0;

    return 0;
}

3.8 Input streams from memory and files

TODO

3.9 Lower level helpers

TODO

4. Using the development repository

The amalgamated source release can be used without Make or other build tools; only a compiler is needed. It is the recommended way of using Core and is available from the release directory of the git repository and from the core.tar.bz2 archives at octaspire.io and octaspire.com. However, when there is a need to modify Core itself or to build the documentation, then some tools are needed and the Makefile in the git repository should be used. In this case the files to be modified are found from the dev directory.

On different systems the required installation commands can vary. In any case, you should install a C compiler and git. Depending on the system, you might also need to install GNU make. If you want to build the documentation, you should also install GNU source-highlight and python. For code coverage and performance measurement you might need to install additional tools.

Example of using the development repository and the different targets available in the Makefile:

git clone https://github.com/octaspire/core.git
cd core
make submodules-init
make
make test
make codestyle
make cppcheck
make valgrind
make coverage
make coverage-show

make amalgamation

make clean

rm release/octaspire-core-amalgamated.c
make release/octaspire-core-amalgamated.c

rm release/documentation/core-manual.html
make release/documentation/core-manual.html

Running make should run make submodules-init automatically if needed (make submodules-init clones and initializes submodules), but it can be run also manually when cloning the repository for the first time. There is no need to run it again later.

If you want to update the submodules into the latest commits, you can run make submodules-pull. It does a git pull on all the submodules.

Running make amalgamation generates first the amalgamation (only, if the source files are changed). Then it detects the system and runs the correct build script.

make test runs the unit tests, make codestyle runs the C coding style checks, make cppcheck runs the cppcheck static analysis on the code, make valgrind runs the unit tests through Valgrind (dynamic analysis and memory leak detection) and make coverage generates a unit test coverage report that can be used for finding code that is not covered yet by unit tests. make coverage-show generates and shows the coverage report in a web browser. make release/documentation/core-manual.html builds the documentation.

4.1 Raspberry Pi, Debian and Ubuntu

To build Core from the regular source distribution in Raspberry Pi (Raspbian), Debian or Ubuntu (16.04 LTS) system:

sudo apt-get install git
git clone https://github.com/octaspire/core.git
cd core
make submodules-init
make

4.2 Arch Linux

To build on Arch Linux (Arch Linux ARM) system:

sudo pacman -S git gcc make
git clone https://github.com/octaspire/core.git
cd core
make submodules-init
make

4.3 Haiku

To build on Haiku (Version Walter (Revision hrev51127) x86_gcc2):

pkgman install gcc_x86
git clone https://github.com/octaspire/core.git
cd core
make submodules-init
CC=gcc-x86 make

4.4 FreeBSD

To build on FreeBSD (FreeBSD-11.0-RELEASE-arm-armv6-RPI2) system:

sudo pkg install git
git clone https://github.com/octaspire/core.git
cd core
make submodules-init
make

4.5 NetBSD

To build on NetBSD (NetBSD-7.1-i386) system:

sudo pkgin install git
git clone git://github.com/octaspire/core
cd core
perl -pi -e 's/https/git/' .gitmodules
make submodules-init
make

4.6 MINIX 3

To build from the regular source distribution on MINIX 3 (minix_R3.3.0-588a35b) system:

su root
pkgin install clang binutils git-base
exit
git clone git://github.com/octaspire/core
cd core
perl -pi -e 's/https/git/' .gitmodules
make submodules-init
make