list.c File Reference

Commotion double linked-list implementation. More...

#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "debug.h"
#include "obj.h"
#include "list.h"
#include "tree.h"
#include "extern/halloc.h"

Classes

struct  _listnode_t
 

Macros

#define _LIST_NEXT(J)   (((_listnode_t *)J)->next)
 
#define _LIST_PREV(J)   (((_listnode_t *)J)->prev)
 
#define _DEFINE_LIST(L)
 

Typedefs

typedef _listnode_t *(* _listiter_t )(co_obj_t *data, _listnode_t *current, void *context)
 

Functions

struct _listnode_t __attribute__ ((packed))
 
 _DEFINE_LIST (16)
 
 _DEFINE_LIST (32)
 
co_obj_tco_list_get_first (const co_obj_t *list)
 return first element of given list More...
 
co_obj_tco_list_get_last (const co_obj_t *list)
 return last element of given list More...
 
size_t co_list_length (co_obj_t *list)
 return length (number of objects) of given list More...
 
co_obj_tco_list_parse (co_obj_t *list, co_iter_t iter, void *context)
 process list with given iterator function More...
 
int co_list_contains (co_obj_t *list, co_obj_t *item)
 determine if list contains specified item More...
 
int co_list_insert_before (co_obj_t *list, co_obj_t *new_obj, co_obj_t *this_obj)
 insert new item in list before specified item More...
 
int co_list_insert_before_unsafe (co_obj_t *list, co_obj_t *new_obj, co_obj_t *this_obj)
 insert new item in list before specified item without the list managing the item's memory More...
 
int co_list_insert_after (co_obj_t *list, co_obj_t *new_obj, co_obj_t *this_obj)
 insert new item in list after specified item More...
 
int co_list_insert_after_unsafe (co_obj_t *list, co_obj_t *new_obj, co_obj_t *this_obj)
 insert new item in list after specified item without the list managing the item's memory More...
 
int co_list_prepend (co_obj_t *list, co_obj_t *new_obj)
 insert new item at beginning of list More...
 
int co_list_prepend_unsafe (co_obj_t *list, co_obj_t *new_obj)
 insert new item at beginning of list without the list managing the item's memory More...
 
int co_list_append (co_obj_t *list, co_obj_t *new_obj)
 insert new item at end of list More...
 
int co_list_append_unsafe (co_obj_t *list, co_obj_t *new_obj)
 insert new item at end of list without the list managing the item's memory More...
 
co_obj_tco_list_delete (co_obj_t *list, co_obj_t *item)
 delete specified item from list More...
 
co_obj_tco_list_element (co_obj_t *list, const unsigned int index)
 return item at specified position in list More...
 
size_t co_list_raw (char *output, const size_t olen, const co_obj_t *list)
 dump raw representation of list More...
 
size_t co_list_import (co_obj_t **list, const char *input, const size_t ilen)
 import list from raw representation More...
 
void co_list_print_indent (co_obj_t *list, int indent)
 print list with indent More...
 
int co_list_print (co_obj_t *list)
 print list More...
 

Variables

_listnode_tprev
 
_listnode_tnext
 
co_obj_tvalue
 

Detailed Description

Commotion double linked-list implementation.

Author
Josh King (jheretic), jking.nosp@m.@cha.nosp@m.mbana.nosp@m..net

Macro Definition Documentation

#define _DEFINE_LIST (   L)
Value:
int co_list##L##_alloc(co_obj_t *output) \
{ \
output->_type = _list##L; \
output->_next = NULL; \
output->_prev = NULL; \
output->_flags = 0; \
output->_ref = 0; \
((co_list##L##_t *)output)->_len = 0; \
return 1; \
} \
co_obj_t *co_list##L##_create(void) \
{ \
co_obj_t *output = h_calloc(1, sizeof(co_list##L##_t)); \
CHECK_MEM(output); \
CHECK(co_list##L##_alloc(output), \
"Failed to allocate object."); \
return output; \
error: \
return NULL; \
}
Definition: obj.h:131

Function Documentation

int co_list_append ( co_obj_t list,
co_obj_t new_obj 
)

insert new item at end of list

Parameters
listlist object to process
new_objitem to insert

References co_list_insert_after(), and co_list_length().

Referenced by _schedule(), _watch(), co_cmd_hook(), co_cmd_hook_str(), co_connect(), co_iface_add(), co_list_import(), co_loop_add_process(), co_loop_add_socket(), co_loop_add_timer(), co_profile_add(), co_request_append(), co_request_append_bin(), co_request_append_int(), co_request_append_str(), co_request_append_uint(), co_schema_register(), co_schema_register_global(), and co_socket_receive().

426 {
427  if(co_list_length(list) == 0)
428  {
429  /* First item in list. */
430  _listnode_t *new_node = _listnode_create(new_obj, true);
431  _co_list_set_first(list, new_node);
432  _co_list_set_last(list, new_node);
433  hattach(new_node, list);
434  _co_list_increment(list);
435  return 1;
436  }
437  return co_list_insert_after(list, new_obj, (_co_list_get_last_node(list))->value);
438 }
int co_list_insert_after(co_obj_t *list, co_obj_t *new_obj, co_obj_t *this_obj)
insert new item in list after specified item
Definition: list.c:333
size_t co_list_length(co_obj_t *list)
return length (number of objects) of given list
Definition: list.c:214
Definition: list.c:47
int co_list_append_unsafe ( co_obj_t list,
co_obj_t new_obj 
)

insert new item at end of list without the list managing the item's memory

Parameters
listlist object to process
new_objitem to insert

References co_list_insert_after(), and co_list_length().

442 {
443  if(co_list_length(list) == 0)
444  {
445  /* First item in list. */
446  _listnode_t *new_node = _listnode_create(new_obj, false);
447  _co_list_set_first(list, new_node);
448  _co_list_set_last(list, new_node);
449  hattach(new_node, list);
450  _co_list_increment(list);
451  return 1;
452  }
453  return co_list_insert_after(list, new_obj, (_co_list_get_last_node(list))->value);
454 }
int co_list_insert_after(co_obj_t *list, co_obj_t *new_obj, co_obj_t *this_obj)
insert new item in list after specified item
Definition: list.c:333
size_t co_list_length(co_obj_t *list)
return length (number of objects) of given list
Definition: list.c:214
Definition: list.c:47
int co_list_contains ( co_obj_t list,
co_obj_t item 
)

determine if list contains specified item

Parameters
listlist object to process
itemitem to search for

Referenced by co_list_insert_after(), co_list_insert_after_unsafe(), co_list_insert_before(), co_list_insert_before_unsafe(), co_loop_add_socket(), and co_socket_hangup().

259 {
260  _listnode_t * result = _co_list_parse_node(list, _co_list_contains_i, (void *)item);
261  if(result != NULL) return 1;
262  return 0;
263 }
Definition: list.c:47
co_obj_t* co_list_delete ( co_obj_t list,
co_obj_t item 
)

delete specified item from list

Parameters
listlist object to process
itemitem to delete

Referenced by _unschedule(), co_disconnect(), co_iface_remove(), co_loop_remove_process(), co_loop_remove_socket(), co_loop_remove_timer(), co_profile_remove(), and co_socket_hangup().

458 {
459  co_obj_t *ret = NULL;
460  _listnode_t *current = _co_list_find_node(list, item);
461  if(current != NULL)
462  {
463  if(_LIST_PREV(current) != NULL)
464  _LIST_NEXT(_LIST_PREV(current)) = _LIST_NEXT(current);
465  else
466  _co_list_set_first(list, _LIST_NEXT(current));
467 
468  if(_LIST_NEXT(current) != NULL)
469  _LIST_PREV(_LIST_NEXT(current)) = _LIST_PREV(current);
470  else
471  _co_list_set_last(list, _LIST_PREV(current));
472 
473  ret = current->value;
474  hattach(current->value, NULL);
475  h_free(current);
476  _co_list_decrement(list);
477  return ret;
478  }
479  return NULL;
480 }
Definition: obj.h:131
Definition: list.c:47
co_obj_t* co_list_element ( co_obj_t list,
const unsigned int  index 
)

return item at specified position in list

Parameters
listlist object to process
indexnumber of item to return

Referenced by co_call(), dispatcher_cb(), and olsrd_mdp_sign().

484 {
485  CHECK(IS_LIST(list), "Not a list object.");
486  _listnode_t *next = _co_list_get_first_node(list);
487  unsigned int i = 0;
488  if(next != NULL)
489  {
490  for(i = 0; i < index; i++)
491  {
492  next = _LIST_NEXT(next);
493  if(next == NULL) break;
494  }
495  }
496  CHECK(i == index, "List index not found.");
497  return next->value;
498 error:
499  return NULL;
500 }
Definition: list.c:47
co_obj_t* co_list_get_first ( const co_obj_t list)

return first element of given list

Parameters
listlist object
118 {
119  return (_co_list_get_first_node(list))->value;
120 }
co_obj_t* co_list_get_last ( const co_obj_t list)

return last element of given list

Parameters
listlist object
163 {
164  return (_co_list_get_last_node(list))->value;
165 }
size_t co_list_import ( co_obj_t **  list,
const char *  input,
const size_t  ilen 
)

import list from raw representation

Parameters
listtarget pointer to new list object
inputinput buffer
ilenlength of input buffer

References co_list_append(), co_list_import(), and co_tree_import().

Referenced by co_call(), co_list_import(), co_tree_import(), and dispatcher_cb().

563 {
564  size_t length = 0, olen = 0, read = 0;
565  co_obj_t *obj = NULL;
566  const char *cursor = input;
567  switch((uint8_t)input[0])
568  {
569  case _list16:
570  length = *((uint16_t *)(input + 1));
571  *list = co_list16_create();
572  cursor += sizeof(uint16_t) + 1;
573  read = sizeof(uint16_t) + 1;
574  break;
575  case _list32:
576  length = *((uint32_t *)(input + 1));
577  *list = co_list32_create();
578  cursor += sizeof(uint32_t) + 1;
579  read = sizeof(uint32_t) + 1;
580  break;
581  default:
582  SENTINEL("Not a list.");
583  break;
584  }
585  for(int i = 0; (i < length && read <= ilen); i++)
586  {
587  if(((uint8_t)cursor[0] == _list16) || ((uint8_t)cursor[0] == _list32))
588  {
589  olen = co_list_import(&obj, cursor, ilen - read);
590  }
591  else if(((uint8_t)cursor[0] == _tree16) || ((uint8_t)cursor[0] == _tree32))
592  {
593  olen = co_tree_import(&obj, cursor, ilen - read);
594  }
595  else olen = co_obj_import(&obj, cursor, ilen - read, 0);
596  CHECK(olen > 0, "Failed to import object.");
597  cursor +=olen;
598  read += olen;
599  CHECK(co_list_append(*list, obj), "Failed to add object to list.");
600  }
601  return read;
602 error:
603  return -1;
604 }
int co_list_append(co_obj_t *list, co_obj_t *new_obj)
insert new item at end of list
Definition: list.c:425
Definition: obj.h:131
size_t co_list_import(co_obj_t **list, const char *input, const size_t ilen)
import list from raw representation
Definition: list.c:562
size_t co_tree_import(co_obj_t **tree, const char *input, const size_t ilen)
import raw representation of tree
Definition: tree.c:659
int co_list_insert_after ( co_obj_t list,
co_obj_t new_obj,
co_obj_t this_obj 
)

insert new item in list after specified item

Parameters
listlist object to process
new_objitem to insert
this_objitem to insert after

References co_list_contains().

Referenced by co_list_append(), and co_list_append_unsafe().

334 {
335  CHECK(IS_LIST(list), "Not a list object.");
336  _listnode_t *this_node = _co_list_find_node(list, this_obj);
337  CHECK(this_node != NULL, "Unable to find existing node in \
338 specified list.");
339  CHECK(!co_list_contains(list, new_obj), "New node already in specified \
340 list.");
341  _listnode_t *adjacent = _LIST_NEXT(this_node);
342  _listnode_t *new_node = _listnode_create(new_obj, true);
343  hattach(new_node, list);
344  if(adjacent == NULL)
345  {
346  /* Last in list. */
347  _co_list_set_last(list, new_node);
348  }
349  else
350  {
351  _LIST_PREV(adjacent) = new_node;
352  _LIST_NEXT(new_node) = adjacent;
353  }
354  _LIST_PREV(new_node) = this_node;
355  _LIST_NEXT(this_node) = new_node;
356  _co_list_increment(list);
357  return 1;
358 error:
359  return 0;
360 }
int co_list_contains(co_obj_t *list, co_obj_t *item)
determine if list contains specified item
Definition: list.c:258
Definition: list.c:47
int co_list_insert_after_unsafe ( co_obj_t list,
co_obj_t new_obj,
co_obj_t this_obj 
)

insert new item in list after specified item without the list managing the item's memory

Parameters
listlist object to process
new_objitem to insert
this_objitem to insert after

References co_list_contains().

364 {
365  CHECK(IS_LIST(list), "Not a list object.");
366  _listnode_t *this_node = _co_list_find_node(list, this_obj);
367  CHECK(this_node != NULL, "Unable to find existing node in \
368 specified list.");
369  CHECK(!co_list_contains(list, new_obj), "New node already in specified \
370 list.");
371  _listnode_t *adjacent = _LIST_NEXT(this_node);
372  _listnode_t *new_node = _listnode_create(new_obj, false);
373  hattach(new_node, list);
374  if(adjacent == NULL)
375  {
376  /* Last in list. */
377  _co_list_set_last(list, new_node);
378  }
379  else
380  {
381  _LIST_PREV(adjacent) = new_node;
382  _LIST_NEXT(new_node) = adjacent;
383  }
384  _LIST_PREV(new_node) = this_node;
385  _LIST_NEXT(this_node) = new_node;
386  _co_list_increment(list);
387  return 1;
388 error:
389  return 0;
390 }
int co_list_contains(co_obj_t *list, co_obj_t *item)
determine if list contains specified item
Definition: list.c:258
Definition: list.c:47
int co_list_insert_before ( co_obj_t list,
co_obj_t new_obj,
co_obj_t this_obj 
)

insert new item in list before specified item

Parameters
listlist object to process
new_objitem to insert
this_objitem to insert before

References co_list_contains().

Referenced by co_list_prepend(), co_list_prepend_unsafe(), and co_loop_add_timer().

274 {
275  CHECK(IS_LIST(list), "Not a list object.");
276  _listnode_t *this_node = _co_list_find_node(list, this_obj);
277  CHECK(this_node != NULL, "Unable to find existing node in \
278 specified list.");
279  CHECK(!co_list_contains(list, new_obj), "New node already in specified \
280 list.");
281  _listnode_t *adjacent = _LIST_PREV(this_node);
282  _listnode_t *new_node = _listnode_create(new_obj, true);
283  hattach(new_node, list);
284  if(adjacent == NULL)
285  {
286  /* First in list. */
287  _co_list_set_first(list, new_node);
288  }
289  else
290  {
291  _LIST_NEXT(adjacent) = new_node;
292  _LIST_PREV(new_node) = adjacent;
293  }
294  _LIST_NEXT(new_node) = this_node;
295  _LIST_PREV(this_node) = new_node;
296  _co_list_increment(list);
297  return 1;
298 error:
299  return 0;
300 }
int co_list_contains(co_obj_t *list, co_obj_t *item)
determine if list contains specified item
Definition: list.c:258
Definition: list.c:47
int co_list_insert_before_unsafe ( co_obj_t list,
co_obj_t new_obj,
co_obj_t this_obj 
)

insert new item in list before specified item without the list managing the item's memory

Parameters
listlist object to process
new_objitem to insert
this_objitem to insert before

References co_list_contains().

304 {
305  CHECK(IS_LIST(list), "Not a list object.");
306  _listnode_t *this_node = _co_list_find_node(list, this_obj);
307  CHECK(this_node != NULL, "Unable to find existing node in \
308 specified list.");
309  CHECK(!co_list_contains(list, new_obj), "New node already in specified \
310 list.");
311  _listnode_t *adjacent = _LIST_PREV(this_node);
312  _listnode_t *new_node = _listnode_create(new_obj, false);
313  hattach(new_node, list);
314  if(adjacent == NULL)
315  {
316  /* First in list. */
317  _co_list_set_first(list, new_node);
318  }
319  else
320  {
321  _LIST_NEXT(adjacent) = new_node;
322  _LIST_PREV(new_node) = adjacent;
323  }
324  _LIST_NEXT(new_node) = this_node;
325  _LIST_PREV(this_node) = new_node;
326  _co_list_increment(list);
327  return 1;
328 error:
329  return 0;
330 }
int co_list_contains(co_obj_t *list, co_obj_t *item)
determine if list contains specified item
Definition: list.c:258
Definition: list.c:47
size_t co_list_length ( co_obj_t list)

return length (number of objects) of given list

Parameters
listlist object

Referenced by co_list_append(), co_list_append_unsafe(), co_list_prepend(), co_list_prepend_unsafe(), and co_plugins_shutdown().

215 {
216  return _co_list_change_length(list, 0);
217 }
co_obj_t* co_list_parse ( co_obj_t list,
co_iter_t  iter,
void *  context 
)

process list with given iterator function

Parameters
listlist object to process
iteriterator function
contextadditional arguments to iterator

Referenced by _schedule(), _unschedule(), _watch(), co_iface_get(), co_iface_profile(), co_iface_remove(), co_list_print_indent(), co_loop_add_socket(), co_loop_add_timer(), co_loop_destroy(), co_loop_get_socket(), co_loop_get_timer(), co_loop_remove_process(), co_loop_remove_socket(), co_loop_remove_timer(), co_plugins_shutdown(), co_plugins_start(), co_profile_find(), co_profiles_process(), co_shutdown(), co_socket_destroy(), and serval_socket_cb().

234 {
235  co_obj_t *result = NULL;
236  CHECK_MEM(list);
237  CHECK(IS_LIST(list), "Not a list object.");
238  //co_obj_t *next = _LIST_NEXT(list);
239  _listnode_t *next = _co_list_get_first_node(list);
240  while(next != NULL && result == NULL)
241  {
242  result = iter(list, next->value, context);
243  next = _LIST_NEXT(next);
244  }
245  return result;
246 error:
247  return result;
248 }
Definition: obj.h:131
Definition: list.c:47
int co_list_prepend ( co_obj_t list,
co_obj_t new_obj 
)

insert new item at beginning of list

Parameters
listlist object to process
new_objitem to insert

References co_list_insert_before(), and co_list_length().

394 {
395  if(co_list_length(list) == 0)
396  {
397  /* First item in list. */
398  _listnode_t *new_node = _listnode_create(new_obj, true);
399  _co_list_set_first(list, new_node);
400  _co_list_set_last(list, new_node);
401  hattach(new_node, list);
402  _co_list_increment(list);
403  return 1;
404  }
405  return co_list_insert_before(list, new_obj, (_co_list_get_first_node(list))->value);
406 }
int co_list_insert_before(co_obj_t *list, co_obj_t *new_obj, co_obj_t *this_obj)
insert new item in list before specified item
Definition: list.c:273
size_t co_list_length(co_obj_t *list)
return length (number of objects) of given list
Definition: list.c:214
Definition: list.c:47
int co_list_prepend_unsafe ( co_obj_t list,
co_obj_t new_obj 
)

insert new item at beginning of list without the list managing the item's memory

Parameters
listlist object to process
new_objitem to insert

References co_list_insert_before(), and co_list_length().

410 {
411  if(co_list_length(list) == 0)
412  {
413  /* First item in list. */
414  _listnode_t *new_node = _listnode_create(new_obj, false);
415  _co_list_set_first(list, new_node);
416  _co_list_set_last(list, new_node);
417  hattach(new_node, list);
418  _co_list_increment(list);
419  return 1;
420  }
421  return co_list_insert_before(list, new_obj, (_co_list_get_first_node(list))->value);
422 }
int co_list_insert_before(co_obj_t *list, co_obj_t *new_obj, co_obj_t *this_obj)
insert new item in list before specified item
Definition: list.c:273
size_t co_list_length(co_obj_t *list)
return length (number of objects) of given list
Definition: list.c:214
Definition: list.c:47
int co_list_print ( co_obj_t list)

print list

Parameters
listlist object to print

References co_list_print_indent().

681 {
682  CHECK_MEM(list);
683 
684  co_list_print_indent(list,0);
685 
686  return 1;
687 error:
688  return 0;
689 }
void co_list_print_indent(co_obj_t *list, int indent)
print list with indent
Definition: list.c:667
void co_list_print_indent ( co_obj_t list,
int  indent 
)

print list with indent

Parameters
listlist object to print
indentlevel of indent

References co_list_parse().

Referenced by co_list_print().

668 {
669  for (int i = 0; i < indent; i++) printf(" ");
670  printf("[\n");
671  indent++;
672  co_list_parse(list, _co_list_print_i, &indent);
673  indent--;
674  for (int i = 0; i < indent; i++) printf(" ");
675  printf("]");
676  if (!indent) printf("\n");
677 }
co_obj_t * co_list_parse(co_obj_t *list, co_iter_t iter, void *context)
process list with given iterator function
Definition: list.c:233
size_t co_list_raw ( char *  output,
const size_t  olen,
const co_obj_t list 
)

dump raw representation of list

Parameters
outputoutput buffer
olenlength of output buffer
listlist object to process

References co_list_raw(), and co_tree_raw().

Referenced by co_list_raw(), co_request_alloc(), and co_response_alloc().

504 {
505  size_t written = 0, read = 0;
506  char *in = NULL;
507  char *out = output;
508  switch(CO_TYPE(list))
509  {
510  case _list16:
511  memmove(out, &(list->_type), sizeof(uint8_t));
512  out += sizeof(uint8_t);
513  memmove(out, &(((co_list16_t *)list)->_len), sizeof(uint16_t));
514  out += sizeof(uint16_t);
515  written = sizeof(uint8_t) + sizeof(uint16_t);
516  break;
517  case _list32:
518  memmove(out, &(list->_type), sizeof(uint8_t));
519  out += sizeof(uint8_t);
520  memmove(out, &(((co_list32_t *)list)->_len), sizeof(uint32_t));
521  out += sizeof(uint32_t);
522  written = sizeof(uint8_t) + sizeof(uint32_t);
523  break;
524  default:
525  SENTINEL("Not a list object.");
526  break;
527  }
528  _listnode_t *next = _co_list_get_first_node(list);
529  while(next != NULL && next->value != NULL && written <= olen)
530  {
531  if((CO_TYPE(next->value) == _list16) || (CO_TYPE(next->value) == _list32))
532  {
533  read = co_list_raw(out, olen - written, next->value);
534  CHECK(read >= 0, "Failed to dump object.");
535  CHECK(read + written < olen, "Data too large for buffer.");
536  }
537  else if ((CO_TYPE(next->value) == _tree16) || (CO_TYPE(next->value) == _tree32))
538  {
539  read = co_tree_raw(out, olen - written, next->value);
540  CHECK(read >= 0, "Failed to dump object.");
541  CHECK(read + written < olen, "Data too large for buffer.");
542  }
543  else
544  {
545  read = co_obj_raw(&in, next->value);
546  CHECK(read >= 0, "Failed to dump object.");
547  CHECK(read + written < olen, "Data too large for buffer.");
548  memmove(out, in, read);
549  }
550  DEBUG("List in: %s, read: %d", in, (int)read);
551  written += read;
552  out += read;
553  next = _LIST_NEXT(next);
554  }
555  return written;
556 error:
557  return -1;
558 
559 }
size_t co_list_raw(char *output, const size_t olen, const co_obj_t *list)
dump raw representation of list
Definition: list.c:503
Definition: list.c:47
size_t co_tree_raw(char *output, const size_t olen, const co_obj_t *tree)
dump raw representation of tree
Definition: tree.c:623