{"id":21021575,"url":"https://github.com/klmitch/dbprim","last_synced_at":"2025-03-13T17:44:08.659Z","repository":{"id":141781183,"uuid":"107191584","full_name":"klmitch/dbprim","owner":"klmitch","description":"Database Primitives Library","archived":false,"fork":false,"pushed_at":"2017-12-06T04:11:07.000Z","size":1865,"stargazers_count":0,"open_issues_count":7,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-20T13:20:37.021Z","etag":null,"topics":["c","data-structures","datastructures","library"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/klmitch.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-16T22:55:09.000Z","updated_at":"2017-10-22T10:38:05.000Z","dependencies_parsed_at":null,"dependency_job_id":"f2c35781-c387-4ae3-b594-bf0f6a1ea69e","html_url":"https://github.com/klmitch/dbprim","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klmitch%2Fdbprim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klmitch%2Fdbprim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klmitch%2Fdbprim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klmitch%2Fdbprim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/klmitch","download_url":"https://codeload.github.com/klmitch/dbprim/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243451433,"owners_count":20293129,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","data-structures","datastructures","library"],"created_at":"2024-11-19T10:47:47.391Z","updated_at":"2025-03-13T17:44:08.634Z","avatar_url":"https://github.com/klmitch.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"===========================\nDatabase Primitives Library\n===========================\n\n.. image:: https://travis-ci.org/klmitch/dbprim.svg?branch=master\n    :target: https://travis-ci.org/klmitch/dbprim\n.. image:: https://coveralls.io/repos/github/klmitch/dbprim/badge.svg?branch=master\n    :target: https://coveralls.io/github/klmitch/dbprim?branch=master\n\nMany programs require some basic in-memory data structures.  In many\nlanguages, the language or standard library provide these basic data\nstructures, but C does not have this.  This library fills the gap by\nproviding these database primitives: linked lists, hash tables,\nred-black trees, and sparse matrices.\n\nInstalling the Library\n======================\n\nThe Database Primitives Library uses GNU Autotools for building.  The\nlibrary can be configured for your system using ``./configure``, and\nsubsequently built using ``make``.  Use ``make install`` to install\nthe library into the configured installation location.  For more\ndetails on installation, including how to configure the installation\nlocation, see the text file ``INSTALL`` located in this directory.\n\nSome additional ``Makefile`` targets exist as well; for instance, to\nuse `Doxygen \u003chttp://www.stack.nl/~dimitri/doxygen/\u003e`_ to build the\ndocumentation for the library, use ``make doxygen-doc`` (the `Dot\n\u003chttp://www.graphviz.org/\u003e`_ tool must also be installed).  A test\nsuite may also be built and executed using ``make check``.\n\nData Structure Overview\n=======================\n\nThe following subsections provide an overview of the available data\nstructures and how to use them.  For more details, see the\ndocumentation or the library header files (in the ``include``\ndirectory in the source distribution, or installed in the ``dbprim``\ndirectory in the selected include path).\n\nLinked Lists\n------------\n\nLinked lists are a very basic data structure used in building\ndatabases.  This library provides a simple yet powerful implementation\nof generic linked lists, based on two caller-allocated structures.\nThe ``link_head_t`` structure describes the head of a linked list and\ncontains information regarding the number of elements in the linked\nlist as well as pointers referencing the first and last elements in\nthe list.  The ``link_elem_t`` structure describes a specific element\nin the linked list and contains pointers referencing the next and\nprevious elements in the list, as well as a pointer to the object, a\npointer to the head of the linked list, and a set of user-specified\nflags.\n\nElements may be added at any arbitrary location in the linked list\nwith ``ll_add()``; moved to any other arbitrary location in the linked\nlist with ``ll_move()``; or removed from the list with\n``ll_remove()``.  In addition, the user may search the list using a\nuser-defined comparison function with ``ll_find()``; iterate over\nevery element in the list with ``ll_iter()``; or remove all items from\nthe list with ``ll_flush()``, optionally executing a user-specified\nclean-up function.\n\nHash Tables\n-----------\n\nHash tables are a basic data structure used in building databases.\nHash tables provide a means of storing data such that an arbitrary\nentry may be looked up efficiently.  This library implements a hash\ntable that may optionally grow and shrink to provide maximum\nefficiency.  The implementation is with two kinds of caller-allocated\nstructures--a ``hash_table_t`` structure that describes the table and\na ``hash_entry_t`` structure for each entry in the table.  The library\nallocates a bucket array which must be released with the ``ht_free()``\nfunction when the hash table has been emptied.  Additionally, the hash\ntable may be manually resized with the ``ht_resize()`` function.\n\nEntries may be added to and removed from the table using the\n``ht_add()`` and ``ht_remove()`` functions.  Additionally, the key on\na given entry may be changed using the ``ht_move()`` function.  Of\ncourse, any given entry may be looked up using the ``ht_find()``\nfunction, and ``ht_iter()`` will execute a user-defined function for\neach entry in the hash table (in an unspecified order).  The\n``ht_flush()`` function will remove all entries from the hash table,\noptionally executing a user-specified clean-up function.\n\nSparse Matrices\n---------------\n\nSparse matrices are advanced data structures used to represent\nassociations.  For instance, a manager may have several employees, but\nseveral of those employees may report to more than one manager.  (Yes,\nthis is a contrived example, so sue me.)  The simplest way to\nrepresent such assocations is with a matrix, or a two-dimensional\narray.  However, such an implementation cannot easily be extended\ndynamically--imagine if a manager retires and two more are hired, for\ninstance.  It would also use an enormous amount of memory, as most\nemployees would only report to one or two managers.\n\nA sparse matrix solves this problem by only allocating memory for the\ncells in the full matrix which are actually used.  That is, no memory\nis allocated to represent Alice reporting to Bob unless Alice actually\ndoes report to Bob.  This is a simple concept, but fairly difficult to\nimplement efficiently--how do you tell if Alice reports to Bob?  The\nsolution utilized by this library is to combine the strengths of\nlinked lists and hash tables.  Each cell is in two linked lists,\nrooted at the rows and columns of the matrix, but a hash table is used\nwhen attempting to look up a given cell.  If the cell is allocated,\nthen there will be an entry in the hash table, and finding the given\ncell is as fast as a hash table look-up.\n\nBecause sparse matrices are so complicated, there are three structures\nand a variety of operations used.  Two of the structures,\n``smat_table_t`` and ``smat_head_t``, are caller-allocated.  However,\nthe third structure, ``smat_entry_t``, must be allocated by the\nlibrary.  To avoid too much overhead from ``malloc()``, a free list is\nused.  The free list may be managed with the ``smat_cleanup()`` and\n``smat_freemem()`` calls.\n\nThe ``smat_table_t`` contains the hash table.  Only one of these need\nbe allocated per type of association--for instance, in the above\nexample, only one ``smat_table_t`` needs to be allocated to represent\nthe manager-employee relationship.\n\nThe ``smat_head_t`` contains the linked list.  There are actually two\nkinds of these structures--one is ``SMAT_LOC_FIRST``, which could be\nregarded as a \"row,\" and the other is ``SMAT_LOC_SECOND``, which could\nbe regarded as a \"column.\"  Which one is used for which type of data\nis irrelevant, as long as consistency is maintained.  For the above\nexample, a ``smat_head_t`` for a manager may be ``SMAT_LOC_FIRST``,\nand one for an employee must then be ``SMAT_LOC_SECOND``.  (These\nvalues are set when initializing the ``smat_head_t`` structure.)\n\nAn association may be created with the ``st_add()`` function, which\nallows an arbitrary ordering in the associated linked lists by the\nsame mechanism as for the linked list component of the library.  An\nassociation may be removed with ``st_remove()``, or looked up with\n``st_find()``.  If iteration over all associations is desired, use the\n``st_iter()`` function.  Removing all associations from a table may be\nperformed with ``st_flush()``, which optionally calls a user-defined\nclean-up function.  The associated hash table may be resized with\n``st_resize()``, and the bucket table may be released with\n``st_free()``.\n\nAn association may also be reordered within the linked lists using the\n``sh_move()`` function.  If a particular entry is desired, use the\n``sh_find()`` function with a user-defined comparison function to\nlocate it.  Iteration may be performed with the ``sh_iter()``\nfunction, and all entries in a given linked list may be removed with\nthe ``sh_flush()`` function, which again may optionally call a\nuser-defined clean-up function.\n\nRed-black Trees\n---------------\n\nRed-black trees are a form of binary search tree.  One essential\nfeature of binary search trees is that they need to be balanced in\norder to be efficient.  Many algorithms exist for keeping trees\nbalanced, but among the easiest to implement is the red-black tree.\nIn a red-black tree, every node is given a color--either red or\nblack--and there are various rules for what color nodes can be present\nwhere in the tree.  This library implements these rules, along with\nfunctions for traversing the tree in any desired tree order.\n\nA red-black tree is represented by a caller-allocated ``rb_tree_t``\nstructure.  This structure describes various characteristics of the\ntree, such as the number of nodes in the tree, and includes a pointer\nto the root node of the tree.  Nodes may be added to the tree using\n``rt_add()`` or removed from the tree using ``rt_remove()``.\nAdditionally, the key on a given node may be changed using the\n``rt_move()`` function.  Nodes may be looked up with ``rt_find()``,\nand ``rt_iter()`` will execute a user-defined function for each node\nin the tree in the specified order.  To remove all entries in the\ntree, simply call the ``rt_flush()`` function.  If you must manually\niterate through the tree, you may call the ``rt_next()`` and\n``rt_prev()`` functions to determine the next or previous nodes to\nvisit.\n\nThere are three ways to traverse a binary tree.  The first, known as\n\"preorder,\" visits the root node, then traverses the left subtree in\npreorder, then traverses the right subtree in preorder.  The second,\nknown an \"inorder,\" traverses the left subtree in inorder, then the\nroot node, then the right subtree in inorder.  (This particular\nordering retrieves the nodes in lexical order; thus its name.)  The\nthird ordering is known as \"postorder\"; this ordering traverses the\nleft subtree, the right subtree, then visits the root node.  To\niterate over the tree in one of these orderings, simply call\n``rt_iter()`` (or ``rt_next()`` or ``rt_prev()``) with the\n``RBT_ORDER_PRE``, ``RBT_ORDER_IN``, or ``RBT_ORDER_POST`` flags.  You\nmay OR these flags with ``DB_FLAG_REVERSE`` to reverse the traversal\nordering, if you wish.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fklmitch%2Fdbprim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fklmitch%2Fdbprim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fklmitch%2Fdbprim/lists"}