Allow for static initialisation.
[libeze] / ez-blob.c
1 /* ez-blob.h: Serialising description and utils.
2
3    Copyright (C) 2019 Michael Zucchi
4
5    This program is free software: you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public License
7    as published by the Free Software Foundation, either version 3 of
8    the License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this program. If not, see
17    <http://www.gnu.org/licenses/>.
18 */
19
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <string.h>
23
24 #include <assert.h>
25
26 #include "ez-blob.h"
27 #include "ez-list.h"
28
29 void ez_blob_free_raw(const ez_blob_desc *desc, void *p) {
30         for (int i=0, dlen = desc->bd_length; i < dlen; i++) {
31                 const ez_blob_desc *d = &desc[i+1];
32                 void *v = p + d->bd_offset;
33                 int st = d->bd_type & EZ_BLOB_STORAGE;
34                 int dt = d->bd_type & EZ_BLOB_TYPE;
35                 
36                 switch (st) {
37                 case EZ_BLOB_SINGLE:
38                         if (dt == EZ_BLOB_STRUCT)
39                                 ez_blob_free_raw(d->bd_table, v);
40                         break;
41                 case EZ_BLOB_SINGLEP:
42                         v = *(void **)v;
43                         if (v) {
44                                 if (dt == EZ_BLOB_STRUCT)
45                                         ez_blob_free_raw(d->bd_table, v);
46                                 free(v);
47                         }
48                         break;
49                 case EZ_BLOB_CSTRING:
50                         free(((char **)v)[0]);
51                         break;
52                 case EZ_BLOB_VECTOR:
53                         if (dt == EZ_BLOB_STRUCT) {
54                                 // FIXME: free elements
55                         }
56                         free(((struct ez_blob *)v)->eb_data);
57                         break;
58                 case EZ_BLOB_VECTORP:
59                         v = *(void **)v;
60                         if (v) {
61                                 if (dt == EZ_BLOB_STRUCT) {
62                                         // FIXME: free elements
63                                 }
64                                 free(((struct ez_blob *)v)->eb_data);
65                         }
66                         break;
67                 case EZ_BLOB_LIST:
68                         for (ez_node *w = ez_list_head((ez_list *)v), *n = ez_node_succ(w); n; w = n, n=ez_node_succ(n))
69                                 ez_blob_free(d->bd_table, w);
70                         break;
71                 case EZ_BLOB_LISTP:
72                         v = *(void **)v;
73                         if (v) {
74                                 for (ez_node *w = ez_list_head((ez_list *)v), *n = ez_node_succ(w); n; w = n, n=ez_node_succ(n))
75                                         ez_blob_free(d->bd_table, w);
76                                 free(v);
77                         }
78                         break;
79                 default:
80                         break;
81                 }
82         }
83 }
84
85 void ez_blob_free(const ez_blob_desc *d, void *p) {
86         if (p) {
87                 ez_blob_free_raw(d, p);
88                 free(p);
89         }
90 }
91
92 void ez_blob_init(const ez_blob_desc *desc, void *p) {
93         memset(p, 0, desc->bd_offset);
94
95         for (int i=0, dlen = desc->bd_length; i < dlen; i++) {
96                 const ez_blob_desc *d = &desc[i+1];
97                 void *v = p + d->bd_offset;
98                 int st = d->bd_type & EZ_BLOB_STORAGE;
99                 int dt = d->bd_type & EZ_BLOB_TYPE;
100
101                 switch (st) {
102                 case EZ_BLOB_SINGLE:
103                         if (dt == EZ_BLOB_STRUCT)
104                                 ez_blob_init(d->bd_table, v);
105                         break;
106                 case EZ_BLOB_LIST:
107                         ez_list_init((ez_list *)v);
108                         break;
109                 }
110         }
111 }
112
113 void *ez_blob_alloc(const ez_blob_desc *d) {
114         void *p = malloc(d->bd_offset);
115         if (p)
116                 ez_blob_init(d, p);
117         return p;
118 }