2 #include <stdlib.h> // for malloc, free, etc
3 #include <string.h> // for strdup()
5 #include "pnd_container.h"
7 // This is implemented in a very vaguely 'class-like' fashion; sure, I could use union's and
8 // void*'s to payload areas and so forth, but this method is pretty convenient instead. We allocate
9 // a buffer of the size of the node PLUS the user requested payload, and then return the payload
10 // part of it. We can go back to the node part with some basic pointer subtraction whenever we
11 // want, and are reasonably assured the user won't monkey with anything in the mechanism.
12 // In short, we can change or replace the container code without impacting the user, and without
13 // boring anyone with void*s or unions or sub-structs and the like.
15 // a Box node is just a key-name and a pointer to the next; the payload is whatever data
16 // follows this. The container itself doesn't care.
17 typedef struct _pnd_box_node_t {
19 struct _pnd_box_node_t *next;
23 char *name; // for when you're using gdb and wondering wtf you're looking at
24 pnd_box_node_t *head; // the first node
27 #define PAYLOAD2NODE(x) ((pnd_box_node_t*)( ((unsigned char *)(x)) - sizeof(pnd_box_node_t) ))
28 #define NODE2PAYLOAD(x) ( ((unsigned char *)(x)) + sizeof(pnd_box_node_t) )
30 pnd_box_handle pnd_box_new ( char *name ) {
32 pnd_box_t *p = malloc ( sizeof(pnd_box_t) );
35 return ( NULL ); // youch!
39 p -> name = strdup ( name );
49 void pnd_box_delete ( pnd_box_handle box ) {
50 pnd_box_t *p = (pnd_box_t*) box;
51 pnd_box_node_t *n, *next;
72 /* free up the box itself
79 p -> head = (void*)123; // if you're looking at a stale pointer in gdb, this might tip you off
86 void *pnd_box_allocinsert ( pnd_box_handle box, char *key, unsigned int size ) {
87 pnd_box_t *p = (pnd_box_t*) box;
89 pnd_box_node_t *n = malloc ( sizeof(pnd_box_node_t) + size );
92 return ( NULL ); // must be getting bloody tight!
95 memset ( n, '\0', sizeof(pnd_box_node_t) + size );
98 n -> key = strdup ( key );
103 n -> next = p -> head;
107 return ( NODE2PAYLOAD(n) );
110 void *pnd_box_find_by_key ( pnd_box_handle box, char *key ) {
111 pnd_box_t *p = (pnd_box_t*) box;
118 if ( strcasecmp ( n -> key, key ) == 0 ) {
119 return ( NODE2PAYLOAD(n) );
128 char *pnd_box_get_name ( pnd_box_handle box ) {
129 pnd_box_t *p = (pnd_box_t*) box;
130 return ( p -> name );
133 void *pnd_box_get_head ( pnd_box_handle box ) {
134 pnd_box_t *p = (pnd_box_t*) box;
136 return ( NULL ); // fubar!
141 return ( NODE2PAYLOAD(p -> head) );
144 void *pnd_box_get_next ( void *node ) {
145 pnd_box_node_t *p = PAYLOAD2NODE(node);
150 return ( NODE2PAYLOAD(p) );
153 char *pnd_box_get_key ( void *node ) {
154 pnd_box_node_t *p = PAYLOAD2NODE(node);
158 unsigned int pnd_box_get_size ( pnd_box_handle box ) {
159 pnd_box_t *p = (pnd_box_t*) box;
161 unsigned int count = 0;
179 unsigned char pnd_box_append ( pnd_box_handle box, pnd_box_handle append ) {
180 pnd_box_t *pbox = (pnd_box_t*) box;
181 pnd_box_t *pappend = (pnd_box_t*) append;
183 if ( pbox -> head ) {
184 pnd_box_node_t *n = pbox -> head;
185 while ( n -> next ) {
188 // by now, n -> next == NULL
189 n -> next = pappend -> head;
191 pbox -> head = pappend -> head;