1 // ================================================================
2 // Reusable singly linked list of string, with tail for append.
3 //
4 // Unlike slls which frees all memory on the destructor, this rslls class is
5 // designed to be reusable: there is a reset method which doesn't free all node
6 // structures.  The context is the CSV-reader which extends a singly linked
7 // list for every data line. Now, all CSV lines have nominally the same number
8 // of fields (say N), so using slls, the CSV reader would be allocating and
9 // freeing N nodes on every line. Mingled in with other mallocs and frees, this
10 // results in needless heap fragmentation. Here, by contrast, as a performance
11 // optimization, the CSV reader can keep and reuse the nodes of a list, only
12 // changing the value-pointers on each CSV line.
13 //
14 // This means that while an slls iteration looks like
15 //
16 //   for (sllse_t* pe = plist->phead; pe != NULL; pe = pe->pnext) {
17 //     ...
18 //   }
19 //
20 // an rslls iteration must also check length:
21 //
22 //   unsigned long long i = 0;
23 //   for (rsllse_t* pe = plist->phead; i < plist->length && pe != NULL; pe = pe->pnext, i++) {
24 //     ...
25 //   }
26 //
27 // ================================================================
28 
29 #ifndef RSLLS_H
30 #define RSLLS_H
31 
32 #include <stdio.h>
33 #include "lib/free_flags.h"
34 
35 typedef struct _rsllse_t {
36 	char* value;
37 	char  free_flag;
38 	char  quote_flag;
39 	struct _rsllse_t *pnext;
40 } rsllse_t;
41 
42 typedef struct _rslls_t {
43 	rsllse_t *phead;
44 	rsllse_t *ptail;
45 	unsigned long long length;
46 } rslls_t;
47 
48 rslls_t* rslls_alloc();
49 void    rslls_reset(rslls_t* plist);
50 void    rslls_free(rslls_t* plist);
51 void    rslls_append(rslls_t* plist, char* value, char free_flag, char quote_flag);
52 
53 void    rslls_print(rslls_t* plist);
54 
55 #endif // RSLLS_H
56