Giter VIP home page Giter VIP logo

list's Introduction

list

C doubly linked list implementation.

API

Below is the public api currently provided by "list".

list_t *list_new();

Allocate and initialize a list.

list_t *mylist = list_new();

list_node_t *list_node_new(void *val)

Allocate and initialize a list_node_t with the given val.

list_node_t *node = list_node_new("my value");
node->val; // "my value"

list_node_t * list_rpush(list_t *self, list_node_t *node)

Append node to self, returning node.

list_rpush(list, list_node_new("value"));
list->tail->val; // "value"

list_node_t * list_rpop(list_t *self)

Return / detach node from the end of the list, or NULL.

list_node_t *last = list_rpop(names);

list_node_t *list_lpush(list_t *self, list_node_t *node)

Prepend node to self, returning node.

list_lpush(list, list_node_new("value"));
list->head->val; // "value"

list_node_t *list_find(list_t *self, void *val)

Return the list_node_t containing val or NULL.

list_node_t *node = list_find(list, "some value");

list_node_t *list_at(list_t *self, int index)

Return the list_node_t at the given index, where index may also be a negative integer indicating an index from the list tail.

list_at(list, 0);  // first
list_at(list, 1);  // second
list_at(list, -1); // last
list_at(list, -3); // third last

void list_remove(list_t *self, list_node_t *node)

Remove node from the list, freeing it and it's value.

list_remove(list, node);

void list_destroy(list_t *self)

Free the list and all nodes.

list_destroy(list);

list_iterator_t *list_iterator_new(list_t *list, list_direction_t direction)

Allocate and initialize a list_iterator_t with the given direction, where direction may be LIST_HEAD or LIST_TAIL.

list_node_t *node;
list_iterator_t *it = list_iterator_new(list, LIST_HEAD);
while ((node = list_iterator_next(it))) {
  puts(node->val);
}

list_node_t *list_iterator_next(list_iterator_t *self)

Return the next list_node_t or NULL.

void list_iterator_destroy(list_iterator_t *self);

Free the iterator only.

list_iterator_destroy(it);

Examples

list iteration:

list_t *langs = list_new();

list_node_t *c = list_rpush(langs, list_node_new("c"));
list_node_t *js = list_rpush(langs, list_node_new("js"));
list_node_t *ruby = list_rpush(langs, list_node_new("ruby"));

list_node_t *node;
list_iterator_t *it = list_iterator_new(langs, LIST_HEAD);
while ((node = list_iterator_next(it))) {
  puts(node->val);
}

list_iterator_destroy(it);
list_destroy(langs);

stdout:

c
js
ruby

Benchmarks

$ make benchmark

 10,000,000 nodes

              lpush: 0.5000s
              rpush: 0.5000s
               lpop: 0.0312s
               rpop: 0.0312s
   find (last node): 0.0312s
            iterate: 0.0625s
        at(100,000): 0.0000s
      at(1,000,000): 0.0000s
       at(-100,000): 0.0000s

Testing

$ make test

License

(The MIT License)

Copyright (c) 2009-2010 TJ Holowaychuk <[email protected]>

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.

list's People

Contributors

bolasblack avatar fweimer-rh avatar isty001 avatar jwerle avatar marcvs avatar musicinmybrain avatar nouwaarom avatar pascaldierich avatar stephenmathieson avatar tj avatar vpetrigo avatar yorkie 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

list's Issues

Install with less generic names?

Iā€™m looking at packaging this library in Fedora Linux. I see that some work has already been done to make it suitable for Debian.

Since the name of the library (list) is extremely generic, would you consider any of the following adjustments to the Makefile?

  • Install the header as $(PREFIX)/include/clibs/list.h instead of $(PREFIX)/include/list.h. Dependent packages could either #include <clibs/list.h>, or compile with -I/usr/include/clibs.
  • Rename liblist.so to something like libclibs_list.so.
  • Rename liblist.a to something like libclibs_list.a.

If so, Iā€™m happy to provide the necessary PR.

Debian package

We're using this code and want to package our software (deb + rpm).

I'm not sure if we can (should) simply copy your code into our (MIT-Licensed) repo and be done with it, or if we have to get this code here packaged as a deb and rpm, too.

The latter is probably cleaner, but I'm not sure, if there are plans to build packages from the maintainer of list.

Any ideas?

freeing curr-val before curr

@visionmedia,

I am a CS student right now at BMCC. In my data structures class we are writing a circular doubly linked list. The class is C++ but I'm trying to write it in pure ANSI-C. When I told my friend (@jwerle) about the project, he said I HAD to come check out your C repos. I'm so glad I did, your stuff is amazing! Thank you for releasing it here.

I just have a quick question (well, more than one actually) about the list_destroy() function. Why do you free(cure->val) before LIST_FREE(curr)? Does LIST_FREE(curr) not free it's associated value as well?

Thanks again for releasing the C code, I'm looking forward to working through some of your other C projects. hash looks particularly fun. :-)

New release for 0.4.0

Hi There,

could you release the 0.4.0 (or 0.4.1 with PR #43 included) on github?
The packaging scripts for Debian and RPM like to make use of these
releases to access the sources.

Best,
Marcus.

warning: comparison of integers of different signs

Compiling with GYP produces an obnoxious warning:

  CC(target) Release/obj.target/list/deps/list/list.o
../deps/list/list.c:173:13: warning: comparison of integers of different signs: 'int' and 'unsigned int'
      [-Wsign-compare]
  if (index < self->len) {
      ~~~~~ ^ ~~~~~~~~~

Thoughts on changing list_at to take an unsigned int?

Configuration header for list.h

Hello,

First of all I would like to say thank you for your library that is helpful a lot. I have a question/proposal - would you tell if it is worth adding a LIST_CONFIG_H, something like that:

// ...
#ifdef LIST_CONFIG_H
#include LIST_CONFIG_H
#endif

#ifndef LIST_MALLOC
#define LIST_MALLOC malloc
#endif

#ifndef LIST_FREE
#define LIST_FREE free
#endif
// ...

That way we will be able to redefine required macros like LIST_MALLOC or LIST_FREE without dozen warnings:

<command-line>: warning: implicit declaration of function 'sys_free' [-Wimplicit-function-declaration]
list/src/list.c:40:5: note: in expansion of macro 'LIST_FREE'
   40 |     LIST_FREE(curr);
      |     ^~~~~~~~~
list/src/list_iterator.c: In function 'list_iterator_new_from_node':
<command-line>: warning: implicit declaration of function 'sys_malloc'; did you mean 'malloc'? [-Wimplicit-function-declaration]
list/src/list_iterator.c:31:16: note: in expansion of macro 'LIST_MALLOC'
   31 |   if (!(self = LIST_MALLOC(sizeof(list_iterator_t))))
      |                ^~~~~~~~~~~
list/src/list_iterator.c:31:14: warning: assignment to 'list_iterator_t *' {aka 'struct <anonymous> *'} from 'int' makes pointer from integer without a cast [-Wint-conversion]
   31 |   if (!(self = LIST_MALLOC(sizeof(list_iterator_t))))
      |              ^
list/src/list_iterator.c: In function 'list_iterator_destroy':
<command-line>: warning: implicit declaration of function 'sys_free' [-Wimplicit-function-declaration]
list/src/list_iterator.c:60:3: note: in expansion of macro 'LIST_FREE'
   60 |   LIST_FREE(self);
      |   ^~~~~~~~~

If that seems reasonable to you, I'll be able to elaborate on a PR for that change.

Thank you.

Error freeing items with link_remove()

Despite the last commit being 3 years ago, I still want to point out an error I found:

This is the original function to remove a node:

void
list_remove(list_t *self, list_node_t *node) {
node->prev
? (node->prev->next = node->next)
: (self->head = node->next);
node->next
? (node->next->prev = node->prev)
: (self->tail = node->prev);
if (self->free) self->free(node);
LIST_FREE(node);
--self->len;
}

But it should be:

if (self->free) self->free(node->val);

You did that correctly for the list_destroy function and that is probably why the error did not appear for you.

Default free function

Thoughts on list_t->free defaulting to free from stdlib? I often forget to set it and end up having to chase memory leaks.

malloc free

for the iterator, when malloc a ptr to iterator, we should use (list_iterator_t **ptr)to destroy, because
void
list_iterator_destroy(list_iterator_t *self) {
LIST_FREE(self);
self = NULL;
}

this is not save, because the
if (val == node->val) {
list_iterator_destroy(it);
return node;
}
it still ptr the memory of free

we should use list_iterator_destory(&it);

Function pointers

Hey TJ,

Sorry to bother you again, but there's something else I'm having trouble wrapping my head around. It's one question in two parts actually.

In the list_t struct{} in list.h you declare the function pointer members void (*free)(void *val); and int (*match)(void *a, void *b);. Then in list.c in the list_t *list_new() function you initialize them both to NULL.

Question 1:
I understand that free() is declared in the included stdlib header <stdlib.h>. So I assume that somehow the compiler links the function pointer to this stdlib function. Is that correct? If so, where does match() come from? I've looked through different online stdlib references and can't find a declaration for match() anywhere.

Question 2:
The information I've read so far about function pointers explains how to declare a function and a pointer and then assign the address of that function to the pointer:

int my_func(int, int) {do something with the ints};
void (*my_func_ptr)(int, int) = NULL;
my_func_ptr = &myfunc;

I don't see this happening for either function pointer in the list_t struct{}. You call both functions in the destroy(), remove() and find() functions but it seems like they're never initialized to anything other then NULL. How the heck do this work!? :-)

I know this is a long one, if you'd rather just point me to a link I'm totally OK with that. Teach a man to fish, right?

Thanks again.

shared library

Hi There,

a debian package that I maintain depends on on list.

Is there a good reason that you don't compile into a shared library, but just into a static one?

after list_remove item is still available

#include <stdlib.h>
#include "list.h"


int main(){
  list_t *gc = list_new();
  list_node_t *node =  list_append(gc, list_node_new("foo"));
  list_node_t *node_2 =  list_append(gc, list_node_new("bar"));
  printf("node: %s, node_2: %s\n", (char*)node->val, (char*)node_2->val);
  list_remove(gc, node);
  printf("length: %d\n", gc->len);
  printf("node: %s, node_2: %s\n", (char*)node->val, (char*)node_2->val);
  
  return 0;
}

Output:

node: foo, node_2: bar
length: 1
node: foo, node_2: bar

Is this a bug, or it's some compiler caching?

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.