Giter Club home page Giter Club logo

libdict's Introduction

libdict

Build Status

libdict is a C library that provides the following data structures with efficient insert, lookup, and delete routines:

All data structures in this library support insert, search, and remove, and have bidirectional iterators. The sorted data structures (everything but hash tables) support near-search operations: searching for the key greater or equal to, strictly greater than, lesser or equal to, or strictly less than, a given key. The tree data structures also support the selecting the nth element; this takes linear time, except in path-reduction and weight-balanced trees, where it only takes logarithmic time.

The API and code are written with efficiency as a primary concern. For example, an insert call returns a boolean indicating whether or not the key was already present in the dictionary (i.e. whether there was an insertion or a collision), and a pointer to the location of the associated data. Thus, an insert-or-update operation can be supported with a single traversal of the data structure. In addition, almost all recursive algorithms have been rewritten to use iteration instead.

License

libdict is released under the simplified BSD license.

libdict's People

Contributors

ahknight avatar alexbers avatar ashoka-versa avatar farooqg avatar fmela avatar rosysong avatar shiva avatar sorc1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libdict's Issues

Calling dict_free fails in FreeRTOS

Hi :)

I write here because I already run out of ideas about how to solve the issue I am facing. The issue may not be 100% related with the library, but I appreciate any help.

At the moment I am using the library in the crazyflie project (https://github.com/bitcraze/crazyflie-firmware). It is a drone running FreeRTOS.

As far as I tested, everything is working properly, except for the dict_free function.

What I did:

  • Setup the dict_malloc_func and dict_free_func functions, so instead of using malloc and free, the use the ones provided by freeRTOS:
void configure_dict_malloc() {
  dict_malloc_func = pvPortMalloc;
  dict_free_func = vPortFree;
}
  • Call dict_free with the following code:
void key_val_free(void *key, void *value) {
  dict_free_func(key);
  dict_free_func(value);
}

void anyFunction() {
  dict *dct = hashtable2_dict_new(dict_uint_cmp, dict_uint_hash, hash_table_initial_size); 
  
  .... other code inserting/removing keys ....

  dict_free(dct, key_val_free);
}

When calling dict_free, in the execution of key_val_free the application is crashing with the error:

"SYS: Assert failed src/lib/FreeRTOS/portable/MemMang/heap_4.c:317"

The code for heap_4.c is:

captura de pantalla 2018-05-14 a las 21 18 40

After getting all this information, I still did not manage to troubleshoot the issue. Does this error ring any bells?

Thank you very much!

Is it possible to use keys that are not strings, for example uint8_t?

Using uint8_t instead of string will probably improve performance. I tried the following:

static dict *dct = NULL;

int uint8cmp(const uint8_t *left, const uint8_t *right) {
  uint8_t leftValue = *left;
  uint8_t rightValue = *left;

  print("Key: '%d'", leftValue);
  print("Key: '%d'", rightValue);

  if (*left == *right) {
    return 0;
  } else if (*left < *right) {
    return -1;
  } else {
    return 1;
  }
}


static void init() {
  dct = hashtable2_dict_new((dict_compare_func)uint8cmp, dict_str_hash, 10);
}

static void test() {
  uint8_t key = 1;
  dict_insert_result result = dict_insert(dct, &key);

  if (result.inserted) {
    *result.datum_ptr = "example value";
    print("inserted '%d': '%s'\n", key, (char *)*result.datum_ptr);
  } else {
    print("Didnt work!");
  }

  void** search = dict_search(dct, &key);
  if (search) {
    print("found '%d': '%s'\n", key, *(char **)search);
  } else {
    print("'%d' not found!\n", key);
  }
}

When running the test function I got:

inserted '1': 'example value'
'1' not found!

Which means that not even uint8cmp was called.

Also, I tried using int instead of uint_8, and using strcmp instead a custom comparator. This worked (but I guess it was just a coincidence):

static void init() {
  dct = hashtable2_dict_new((dict_compare_func)strcmp, dict_str_hash, 10);
}

static void test() {
  int key = 1;
  dict_insert_result result = dict_insert(dct, &key);

  if (result.inserted) {
    *result.datum_ptr = "example value";
    print("inserted '%d': '%s'\n", key, (char *)*result.datum_ptr);
  } else {
    print("Didnt work!");
  }

  void** search = dict_search(dct, &key);
  if (search) {
    print("found '%d': '%s'\n", key, *(char **)search);
  } else {
    print("'%d' not found!\n", key);
  }
}

TwrSwarmAlgorithm twrSwarmAlgorithm = {
  .init = init,
  .test = test
};

In this case, it worked and I got in the screen:

inserted '1': 'example value'
found '1': 'example value'

Static library build needlessly difficult

I'm trying to use this in a submodule for a project and I can't seem to make just the static library. If I "make bin/libdict.a" then I get errors about certain files not being compiled yet and if I "make all" then it needs CUnit installed (which I cannot guarantee for my own users).

Think unit tests could be less integrated so production builds are possible?

license (2-clause or 4-clause)

2-clause BSD license is written in the top level LICENSE file.
Through 4-clause BSD license is written in the header of src/hb_tree.c.
Could you update the headers?

splay tree crash when adding a number of items higher than 1-e5

Hi Farook,
I am experimenting a Segmentation fault with splay_tree implementation in libdict.

Basically, the memory violation occurs when I attempt to add a high number of items.
With a numer of items up to 1-e5 all my units tests are ok and also valgrind does not give any errors.

If I use 1-e6 number of items the program crashes.

System: Linux nuc 3.2.0-4-amd64 #1 SMP Debian 3.2.96-2 x86_64 GNU/Linux
Compiler: gcc version 7.2.0 (Debian 7.2.0-19)

[0] [email protected] 996> gdb ./splay_glue
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
..............
(gdb) r -i add -6
[1] Running add ...............
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff788e1f6 in _int_free () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) up
#1 0x0000555555557687 in tree_node_free (node=0x55555b30c0b0, delete_func=0x0) at /spool/git/tries/c/fmela/libdict/src/tree_common.c:302
302 FREE(node);
(gdb) up
#2 0x00005555555576a1 in tree_node_free (node=0x55555b30c110, delete_func=0x0) at /spool/git/tries/c/fmela/libdict/src/tree_common.c:304
304 tree_node_free(llink, delete_func);

In attempt to fix the problem I made my test program all inlined and you can find it in the attached tar-ball. Simply compile and run it as:
./splay_glue -i add -6 (that means run only the add test-unit using 1-e6 items)
(I have libdict source in /spool/git/tries/c/fmela/libdict/ so you need to edit Makefile to match your env)

Please do not hesitate to contact me if you need more info

splay-tree-crash.tar.gz

Best Regards
/rocco

Bug in tree_traverse

The 'tree' is passed as argument to tree_node_min() instead
of tree->node. Please apply the following patch.

--- a/usr/lib/libdict/src/tree_common.c
+++ b/usr/lib/libdict/src/tree_common.c
@@ -179,7 +179,7 @@ tree_traverse(void* Tree, dict_visit_func visit)

 size_t count = 0;
 if (tree->root) {
  •   tree_node\* node = tree_node_min(tree);
    
  •   tree_node\* node = tree_node_min(tree->root);
    

Thanks,
Ashoka

Add #ifdef so that using custom malloc() is streamlined

Right now the source must by modified to use a custom malloc. From dict.c:

void* (*dict_malloc_func)(size_t) = malloc;
void (*dict_free_func)(void*) = free;

These functions cannot be changed after compilation, so we must edit dict.c to customize, adding CM complexity.
I propose the simple change:

#ifndef LIBDICT_USE_CUSTOM_MALLOC
void* (*dict_malloc_func)(size_t) = malloc;
void (*dict_free_func)(void*) = free;
#endif

In this way, the object can be compiled without those symbols defined, so that they can be linked in later.
The Makefile must also be changed to support this somehow, to pass the define through on CFLAGS, and also so that tests / pothe binaries built be the Makefile will either get linked with a version of dict.o with those symbols, or their own copies of the symbol definitions if the custom malloc is requested.

Missing 'extern' in dict.h

I have C and C++ files in my project and need to use your lib in both. After compiling each individually to .o-files, I stumbled upon one small bug that prevented me from linking them correctly with the static library of libdict. The error says "multiple definitions of 'dict_free_func'", as well as 'dict_malloc_func'.

I fixed this problem by adding the keyword 'extern' in front of the defs of these functions in include/dict.h (Line 73 and 75)
Cheers!

No mechanism to pass user defined state when traversing

When traversing the dictionary types, there is no way to pass state except by holding it in a global variable. This make thread-safety and concurrency harder to implement.

@fmela As we discussed offline, I am making a ticket so I can submit a pull request against it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.