-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathiobacking.c
173 lines (148 loc) · 3.33 KB
/
iobacking.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include <errno.h>
#include <aul/common.h>
#include <aul/exception.h>
#include <array.h>
#include <buffer.h>
#include <kernel.h>
#include <kernel-priv.h>
static size_t iobacking_size(char sig)
{
switch (sig)
{
case T_VOID: return 0;
case T_BOOLEAN: return sizeof(bool);
case T_INTEGER: return sizeof(int);
case T_DOUBLE: return sizeof(double);
case T_CHAR: return sizeof(char);
case T_STRING: return sizeof(char *) + sizeof(char) * AUL_STRING_MAXLEN;
case T_ARRAY_BOOLEAN:
case T_ARRAY_INTEGER:
case T_ARRAY_DOUBLE: return sizeof(array_t *);
case T_BUFFER: return sizeof(buffer_t *);
default: return -1;
}
}
iobacking_t * iobacking_new(char sig, exception_t ** err)
{
// Sanity check
{
if (exception_check(err))
{
return NULL;
}
}
// Get the payload size
ssize_t memsize = iobacking_size(sig);
if (memsize == -1)
{
exception_set(err, EINVAL, "Could not determine backing size for sig '%c'", sig);
return NULL;
}
iobacking_t * backing = malloc(sizeof(iobacking_t) + memsize);
memset(backing, 0, sizeof(iobacking_t) + memsize);
backing->sig = sig;
backing->isnull = true;
// Handle type-specific initialization
switch (sig)
{
case T_STRING:
{
// Set up the buffer so that it looks like this:
// [ char * | string... ]
// First member points to the rest of the string
// we use this so that when we return the data chunk pointer, its of type pointer to char *
char ** head = (char **)&backing[0];
*head = (char *)&backing->data[sizeof(char *)];
break;
}
default: break;
}
return backing;
}
void iobacking_destroy(iobacking_t * backing)
{
// Sanity check
{
if unlikely(backing == NULL)
{
return;
}
}
free(backing);
}
void iobacking_copy(iobacking_t * backing, const void * data)
{
// Sanity check
{
if unlikely(backing == NULL)
{
return;
}
}
// Copy data into backing
switch (iobacking_sig(backing))
{
case T_BOOLEAN:
{
const bool * from = (const bool *)data;
bool * to = (bool *)iobacking_data(backing);
*to = (from == NULL)? false : *from;
break;
}
case T_INTEGER:
{
const int * from = (const int *)data;
int * to = (int *)iobacking_data(backing);
*to = (from == NULL)? 0 : *from;
break;
}
case T_DOUBLE:
{
const double * from = (const double *)data;
double * to = (double *)iobacking_data(backing);
*to = (from == NULL)? 0.0 : *from;
break;
}
case T_CHAR:
{
const char * from = (const char *)data;
char * to = (char *)iobacking_data(backing);
*to = (from == NULL)? '\0' : *from;
break;
}
case T_STRING:
{
const char * const * from = (const char * const *)data;
char ** to = (char **)iobacking_data(backing);
const char * str = (from == NULL)? "" : ((*from == NULL)? "" : *from);
strncpy(*to, str, AUL_STRING_MAXLEN - 1);
break;
}
case T_ARRAY_BOOLEAN:
case T_ARRAY_INTEGER:
case T_ARRAY_DOUBLE:
case T_BUFFER:
{
const buffer_t ** from = (const buffer_t **)data;
buffer_t ** to = (buffer_t **)iobacking_data(backing);
if (!iobacking_isnull(backing))
{
buffer_free(*to);
*to = NULL;
}
if (from != NULL)
{
*to = buffer_dup(*from);
}
break;
}
/*
default:
{
LOGK(LOG_ERR, "Unknown signature backing: %c", iobacking_sig(backing));
break;
}
*/
}
iobacking_isnull(backing) = (data == NULL);
}