An open source library for C

Homo Deus - C Library

Introduction

The Homo Deus C Library (hdelibc) is an open source collection of tools for the C programming language.
The project is in continuous development, with features being added and revised continually over time.

Compiling

If you save the hdelibc directory to your default include location, there is no need to compile anything; however, a makefile is provided to allow the compiling of hdelibc into a static library containing all sub-modules, individual sub-modules, or both. The simplest configuration is to compile both with the command:

make

This will generate a static library for hdelibc as a whole, as well as static libraries for each of the sub-modules individually. If you only wish to compile the top-level static library, use:

make Main

If you wish to compile a static library for only a portion of hdelibc, you will need to use the command specified for that section. You can find the command in that sub-module's README, or in the table of contents below.

Including

The easiest way to import the library is simply to download the project folder and copy it into your project, and then reference the desired header files. You will need to use brackets or quotes according to how you intend to use the library, but documentation is written as if hdelibc is saved in your default include path.

// If in default include path:
#include <hdelibc.h>
// If in the same directory as your project:
#include "hdelibc/hdelibc.h"

If you are using hdelibc as a static library, remember to include the desired .a file in your command:

gcc my_project.c hdelibc/hdelibc.a

If only a section of the library is desired, that section alone may be included, and static libraries are provided for each sub-module.
Again, use the include statement and parameterize the static library (if applicable):

#include <hdelibc/DataStructures/DataStructures.h>
gcc my_project.c hdelibc/DataStructures/DataStructures.a

Since there are numerous sub-modules, this file will simply serve as a table of contents for what is included in the library.

Contents

For specific documentation on components, check the README included in the sub-module directories.

Data Structures

Location:

~/hdelibc/DataStructures

Include:

#include <hdelibc/DataStructures/hdelibc-datastructures.h>

Components

Common

  • Node

Dictionary

  • Entry
  • Dictionary

Lists

  • LinkedList
  • Queue

Trees

  • BinarySearchTree
Comments
  • Documentation and Cleanup

    Documentation and Cleanup

    With the blockchain project about to fork from libeom, it is appropriate to merge the current status of the working branch into main. Before the merge, some documentation and cleanup needs to be done.

  • Memory problem

    Memory problem

    I may be wrong, but I think that in your BinarySearchingTree.c file in binary_search_tree_destructor you should use pointer to the tree as an argument instead of actual tree. It causes the thing, that you are not actually destroying actual tree. Besides that you make a copy of your tree in that function and destroys it, but not the actual tree you wanted. I may be wrong because of pointer copies in that function, but to make sure you are destroying the tree correctly and to make it cleaner, I think that's would be better.

    And thank you for the lib and for videos, sorry if I'm wrong!

  • Interactive Terminal

    Interactive Terminal

    Terminal Applications

    Applications such as Python, MongoDB, and PostgreSQL come with an interactive terminal interface that allows real-time processing of commands one after another. Since these shell interfaces are so common and useful, it would be useful to add a generic one to the library.

    Generic Terminal

    The result would be a terminal function that takes argc and argv from main and passes them off to a user-defined interpreter. Since the command syntax and resulting actions are unknown to the generic function, the purpose of the function is to switch between two activation conditions:

    1. Launching with no arguments:
    > $ ./application
    

    This should open an interactive shell where the user may enter repeated commands to pass to the interpreter.

    1. Launching with arguments:
    > $ ./application arg1 arg2
    

    This should simply pass the two arguments to the interpreter and close.

    Data Pipes

    While designing a terminal application, it is important to remember that commands may come from data pipes rather than direct user input. A robust implementation of an interactive terminal should be capable of receiving input through a pipe rather than user input.

  • Product Design

    Product Design

    Goals

    We are building the base functionality to read, create, share, and collect blocks within a peer-to-peer network. With this application, it will be easy to install client and server based applications that extend its functionality, allowing you to use the blockchain in any way you like.

    Single or Multiple Applications?

    On a given node, how dependent is either the client or server section on the other? If the client utilizes the server to query local storage, then their usage is heavily integrated and every instance of the application will require both client and server functionality; however, these two functionalities could also be designed as stand-alone applications, allowing users to install blockchain-client or blockchain-server depending on their needs. Either way, we may want to allow users to configure the allocation of resources to client and server functionalities.

    Discussion

    How should we implement the raw materials present in the library into a final product? Should we create separate or integrated client and server applications?

  • Contiguous Memory

    Contiguous Memory

    This issue was brought to my attention by @camel-cdr

    Hashes and Raw Bytes

    When transferring blocks over the network, the first test a node will run over a foreign block to validate its integrity will be the network-standard hashing algorithm. Should the resulting hash satisfy the network-prescribed proof-of-work difficulty, we can begin treating the object as a block; however, there may be discrepancies in how a given machine stores the desired data structures. As a result, the raw bytes that one node sends will not fit into the same structure on the recipient node architecture due to a concept called padding. While the hash generated from those raw bytes would satisfy the difficulty requirement, the data would not cast correctly into the expected data type.

    Padding

    The CPU does not read data by the bit, nor by the byte, but by the word. The size of a word is dependent on the architecture, but generally a 32 bit CPU will have a 4 byte word while a 64 bit CPU will have an 8 byte word. When the compiler defines the memory layout of a struct, it does so depending on the architecture's word size. The following struct, for example, would require a total of 8 bytes of memory on a 32 bit machine, despite being only 6 bytes of data:

    struct example 
    {
        char a;
        char b;
        int c;
    };
    

    The problem is that the int data type requires four bytes of memory, and it will save CPU cycles to access that member in a single word. The structure is then padded such that the field begins where the CPU may access it in a single cycle. So instead of storing the struct like this:

    Word:    |_          _            _            _           |_          _            _            _           |
    
    Data:     char     char          int----------------------------------------------- empty-----------------------
    

    The structure is padded so that the int falls at the beginning of a word:

    Word:    |_          _            _            _           |_          _            _            _           |
    
    Data:     char     char          empty-----------------------int-----------------------------
    

    Data Integrity

    While this is a more efficient layout in terms of CPU cycles at a small cost in memory, it makes maintaining the integrity of data when handled by multiple nodes difficult. Fortunately, we may override this behavior to designate that all blocks on the network are to be created, stored, and transferred in an unpadded schema:

    struct BlockHeaders
    {
        unsigned char previous_hash[64];
        unsigned long nonce;
        unsigned char fingerprint[64];
        unsigned char timestamp[20];
        unsigned long size;
    } __attribute__((packed));
    

    The packed attribute designates this struct to be created without padding, which will allow the casting of raw bytes sent across a network between nodes with incompatible architectures.

  • Cleaning up the linked list: I'm doing a bit of code review type stuff

    Cleaning up the linked list: I'm doing a bit of code review type stuff

    So I've done some reading through the source code of the linked list implementation, and I'm laying them out some of my thoughts here.

    One does not simply index a linked list

    It's important to notice, that the complexity of random access to a linked list is O(n), that means that 1 if you need to do a lot of random access you shouldn't be using a linked list and that you should always prefer iteration to indexing. Using iterate_ll to implement sort_ll and search_ll automatically results in very slow code.

    search_ll

    Ok, let's get this out of the way search_ll should be called bsearch_ll or binarysearch_ll, the name search doesn't tell the user that the linked list needs to be sorted to search for elements. Note that using binary search on a linked isn't a good idea in the first place, as you need to traverse almost the entire list anyways (if iterate_ll wasn't used, otherwise it does literally quadratic work). It's only useful if you need to reduce the calls to compare, which is something you might want to do, but this should definitely be done explicitly and not be the default search.

    Also, why are you calling the compare function twice instead of storing the result? I'd also return int instead of short, but that's just nitpicking now.

    sort_ll

    sort_ll also has the problem of using iterate_ll, so I transformed the bubble sort algorithm to work without it:

    void sort_ll(struct LinkedList *linked_list, int (*compare)(void *a, void *b))
    {
        for (struct Node *i = linked_list->head; i; i = i->next)
        {
            for (struct Node *j = i->next; j; j = j->next)
            {
                if (compare(i->data, j->data) > 0)
                {
                    // Swap them.
                    void *temporary = j->data;
                    j->data = i->data;
                    i->data = temporary;
                }
            }
        }
    }
    

    Note that I also changed the comparison from == 0 to > 0, this allows you to e.g. implement the compare function for integers using a - b, which is commonly done.

    Now the complexity has been reduced from O(n^3) to O(n^2). Bubble sort itself isn't the best sorting algorithm, and I'd suggest actually using something like merge sort.

    Getting rid of the indexes

    Generally when working with linked lists you should pass around node pointers instead of indexes. To illustrate that let's say you'd like to remove a node. To delete a node you firstly need to know where the node currently is. The current implementation requires you to iterate over each element of the list with indexes, so you automatically have a complexity of O(n) and then when you've found the correct element iterate over the entire list again (at least this time in O(n)), to find the element at the index. An alternative solution, which is preferable when working with liked lists, is to traverse the linked list using pointers for (Node *i = list; i; i = i->next) and then pass the current node pointer to the delete function.

    On ownership and pointers

    Another thing I've noticed is that you're linked list owns pointers, as in allocates and frees them. This isn't automatically wrong, but I'd say that it isn't a good design decision. For one, how would you only use a shallow copy, so inserting e.g.

    struct Str {
             size_t len;
             char *str;
    };
    

    wouldn't copy str and now you've got two references to str and you'd somehow need to decide who frees str (I'm assuming that str is heap allocated). I suggest that instead of doing the allocation inside insert_ll the user would call it with a pointer allocated from the user, this would also get rid of the problem of constructing a node with data of size zero. Having a node with a null pointer should be totally allowed.

    How I would do it

    This isn't for everyone's taste, but I like to use a Node as a base class for the elements of the list. This allows you to basically do whatever you want to, and you don't have an extra indirection between the node and the data, which is more cache friendly.

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <time.h>
    
    struct Node {
            struct Node *next;
            struct Node *previous;
    };
    
    struct IntNode {
            struct Node node;
            int i;
    };
    
    static struct Node *
    sort_ll_merge(struct Node *a, struct Node *b, int (*cmp)(void *a, void *b));
    
    /* mergesort */
    struct Node *
    sort_ll(struct Node *head, int (*cmp)(void *a, void *b))
    {
    	struct Node *a, *b;
    
    	if (!head || !head->next)
    		return head;
    
    	{
    		struct Node *fast, *slow;
    		slow = head;
    		fast = head->next;
    
    		/* Advance 'fast' two nodes, and advance 'slow' one node */
    		while (fast != NULL) {
    			fast = fast->next;
    			if (fast != NULL) {
    				slow = slow->next;
    				fast = fast->next;
    			}
    		}
    
    		/* 'slow' is before the midpoint in the list, so split it in
    		 * two at that point. */
    		a = head;
    		b = slow->next;
    		slow->next = NULL;
    	}
    
    	a = sort_ll(a, cmp);
    	b = sort_ll(b, cmp);
    	return sort_ll_merge(a, b, cmp);
    }
    
    struct Node *
    sort_ll_merge(struct Node *a, struct Node *b, int (*cmp)(void *a, void *b))
    {
    	struct Node* res = NULL;
    
    	/* Base cases */
    	if (a == NULL)
    		return (b);
    	else if (b == NULL)
    		return (a);
    
    	/* Pick either a or b, and recur */
    	if (cmp(a, b) > 0) {
    		res = a;
    		res->next = sort_ll_merge(a->next, b, cmp);
    	} else {
    		res = b;
    		res->next = sort_ll_merge(a, b->next, cmp);
    	}
    	return res;
    }
    
    
    int
    cmp_intnode(void* a, void* b)
    {
    	struct IntNode *ia = a, *ib = b;
    	return ia->i - ib->i;
    }
    
    int
    main(void)
    {
    	/* just on way to construct an linked list,
    	 * you could use malloc instead. */
    	struct IntNode nodes[30] = {0};
    	for (int i = 0; i < 29; ++i) {
    		nodes[i].node.next = &nodes[i+1];
    		nodes[i+1].node.previous = &nodes[i];
    		nodes[i].i = rand();
    	}
    
    	struct IntNode *newhead = sort_ll(nodes, cmp_intnode);
    
    	for (struct IntNode *i = newhead; i; i = i->node.next) {
    		printf("%d\n", i->i);
    	}
    }
    
JUCE is an open-source cross-platform C++ application framework for desktop and mobile applications, including VST, VST3, AU, AUv3, RTAS and AAX audio plug-ins.
JUCE is an open-source cross-platform C++ application framework for desktop and mobile applications, including VST, VST3, AU, AUv3, RTAS and AAX audio plug-ins.

JUCE is an open-source cross-platform C++ application framework used for rapidly developing high quality desktop and mobile applications, including VS

Dec 1, 2022
Fast, orthogonal, open multi-methods. Supersedes yomm11.

YOMM2 This is a complete rewrite of YOMM11, which is now deprecated. This library is much better, see here to find out why. TL;DR If you are familiar

Nov 30, 2022
EASTL stands for Electronic Arts Standard Template Library. It is an extensive and robust implementation that has an emphasis on high performance.

EA Standard Template Library EASTL stands for Electronic Arts Standard Template Library. It is a C++ template library of containers, algorithms, and i

Dec 1, 2022
Embedded Template Library

Embedded Template Library (ETL) Motivation C++ is a great language to use for embedded applications and templates are a powerful aspect. The standard

Nov 26, 2022
Functional Programming Library for C++. Write concise and readable C++ code.
Functional Programming Library for C++. Write concise and readable C++ code.

FunctionalPlus helps you write concise and readable C++ code. Table of contents Introduction Usage examples Type deduction and useful error messages T

Nov 28, 2022
Nov 27, 2022
? A glib-like multi-platform c library
? A glib-like multi-platform c library

A glib-like cross-platform C library Supporting the project Support this project by becoming a sponsor. Your logo will show up here with a link to you

Nov 27, 2022
NIH Utility Library

libnih is a light-weight "standard library" of C functions to ease the development of other libraries and applications. Its goals are: * despite it

Sep 15, 2022
This is a list of different open-source video games and commercial video games open-source remakes.

This is a list of different open-source video games and commercial video games open-source remakes.

Nov 28, 2022
Open-source and open-hardware scientific RPN calculator
Open-source and open-hardware scientific RPN calculator

OpenRPNCalc Open-source and open-hardware scientific RPN calculator Introduction OpenRPNCalc is a scientific calculator based on STM32 microcontroller

Dec 2, 2022
OpenMW is an open-source open-world RPG game engine that supports playing Morrowind.

OpenMW is an open-source open-world RPG game engine that supports playing Morrowind.

Nov 30, 2022
A fully-functional open source and open hardware mechanical USB computer keyboard with only three keys!
A fully-functional open source and open hardware mechanical USB computer keyboard with only three keys!

threeboard threeboard is a fully-functional open source and open hardware mechanical USB computer keyboard with only three keys. It supports multiple

Nov 15, 2022
Open Source Cheat for Apex Legends, designed for ease of use. Made to understand reversing of Apex Legends and respawn's modified source engine as well as their Easy Anti Cheat Implementation.
Open Source Cheat for Apex Legends, designed for ease of use. Made to understand reversing of Apex Legends and respawn's modified source engine as well as their Easy Anti Cheat Implementation.

Apex-Legends-SDK Open Source Cheat for Apex Legends, designed for ease of use. Made to understand reversing of Apex Legends and respawn's modified sou

Nov 20, 2022
Sourcetrail - free and open-source interactive source explorer
Sourcetrail - free and open-source interactive source explorer

Sourcetrail Important Note: This project was archived by the original autors and maintainers of Sourcetrail by the end of 2021. If you want to know mo

Nov 27, 2022
Single source file ASTC texture decompression in C++ (derived from Google's open source Android project)

astc_dec astc_dec is a single source file ASTC texture decompressor with the Apache 2.0 license, derived from Google's open source Android sources. Th

Oct 22, 2022
MIRACL Cryptographic SDK: Multiprecision Integer and Rational Arithmetic Cryptographic Library is a C software library that is widely regarded by developers as the gold standard open source SDK for elliptic curve cryptography (ECC).

MIRACL What is MIRACL? Multiprecision Integer and Rational Arithmetic Cryptographic Library – the MIRACL Crypto SDK – is a C software library that is

Nov 22, 2022
MIRACL Cryptographic SDK: Multiprecision Integer and Rational Arithmetic Cryptographic Library is a C software library that is widely regarded by developers as the gold standard open source SDK for elliptic curve cryptography (ECC).

MIRACL What is MIRACL? Multiprecision Integer and Rational Arithmetic Cryptographic Library – the MIRACL Crypto SDK – is a C software library that is

Nov 22, 2022
OpenShot Video Library (libopenshot) is a free, open-source C++ library dedicated to delivering high quality video editing, animation, and playback solutions to the world

OpenShot Video Library (libopenshot) is a free, open-source C++ library dedicated to delivering high quality video editing, animation, and playback solutions to the world

Dec 3, 2022
This is a helper library to abstract away interfacing with floppy disk drives in a cross-platform and open source library.
This is a helper library to abstract away interfacing with floppy disk drives in a cross-platform and open source library.

Adafruit Floppy This is a helper library to abstract away interfacing with floppy disk drives in a cross-platform and open source library. Adafruit Fl

Nov 14, 2022
An open-source C++ library developed and used at Facebook.

Folly: Facebook Open-source Library What is folly? Folly (acronymed loosely after Facebook Open Source Library) is a library of C++14 components desig

Dec 3, 2022