1 /*
2 * Copyright (c) 2013 Hugh Bailey <obs.jim@gmail.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #pragma once
18
19 #include <string.h>
20 #include "../util/c99defs.h"
21 #include "../util/bmem.h"
22
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26
27 /*
28 * Procedure call data structure
29 *
30 * This is used to store parameters (and return value) sent to/from signals,
31 * procedures, and callbacks.
32 */
33
34 enum call_param_type {
35 CALL_PARAM_TYPE_VOID,
36 CALL_PARAM_TYPE_INT,
37 CALL_PARAM_TYPE_FLOAT,
38 CALL_PARAM_TYPE_BOOL,
39 CALL_PARAM_TYPE_PTR,
40 CALL_PARAM_TYPE_STRING
41 };
42
43 #define CALL_PARAM_IN (1 << 0)
44 #define CALL_PARAM_OUT (1 << 1)
45
46 struct calldata {
47 uint8_t *stack;
48 size_t size; /* size of the stack, in bytes */
49 size_t capacity; /* capacity of the stack, in bytes */
50 bool fixed; /* fixed size (using call stack) */
51 };
52
53 typedef struct calldata calldata_t;
54
calldata_init(struct calldata * data)55 static inline void calldata_init(struct calldata *data)
56 {
57 memset(data, 0, sizeof(struct calldata));
58 }
59
60 static inline void calldata_clear(struct calldata *data);
61
calldata_init_fixed(struct calldata * data,uint8_t * stack,size_t size)62 static inline void calldata_init_fixed(struct calldata *data, uint8_t *stack,
63 size_t size)
64 {
65 data->stack = stack;
66 data->capacity = size;
67 data->fixed = true;
68 data->size = 0;
69 calldata_clear(data);
70 }
71
calldata_free(struct calldata * data)72 static inline void calldata_free(struct calldata *data)
73 {
74 if (!data->fixed)
75 bfree(data->stack);
76 }
77
78 EXPORT bool calldata_get_data(const calldata_t *data, const char *name,
79 void *out, size_t size);
80 EXPORT void calldata_set_data(calldata_t *data, const char *name,
81 const void *in, size_t new_size);
82
calldata_clear(struct calldata * data)83 static inline void calldata_clear(struct calldata *data)
84 {
85 if (data->stack) {
86 data->size = sizeof(size_t);
87 memset(data->stack, 0, sizeof(size_t));
88 }
89 }
90
calldata_create(void)91 static inline calldata_t *calldata_create(void)
92 {
93 return (calldata_t *)bzalloc(sizeof(struct calldata));
94 }
95
calldata_destroy(calldata_t * cd)96 static inline void calldata_destroy(calldata_t *cd)
97 {
98 calldata_free(cd);
99 bfree(cd);
100 }
101
102 /* ------------------------------------------------------------------------- */
103 /* NOTE: 'get' functions return true only if parameter exists, and is the
104 * same type. They return false otherwise. */
105
calldata_get_int(const calldata_t * data,const char * name,long long * val)106 static inline bool calldata_get_int(const calldata_t *data, const char *name,
107 long long *val)
108 {
109 return calldata_get_data(data, name, val, sizeof(*val));
110 }
111
calldata_get_float(const calldata_t * data,const char * name,double * val)112 static inline bool calldata_get_float(const calldata_t *data, const char *name,
113 double *val)
114 {
115 return calldata_get_data(data, name, val, sizeof(*val));
116 }
117
calldata_get_bool(const calldata_t * data,const char * name,bool * val)118 static inline bool calldata_get_bool(const calldata_t *data, const char *name,
119 bool *val)
120 {
121 return calldata_get_data(data, name, val, sizeof(*val));
122 }
123
calldata_get_ptr(const calldata_t * data,const char * name,void * p_ptr)124 static inline bool calldata_get_ptr(const calldata_t *data, const char *name,
125 void *p_ptr)
126 {
127 return calldata_get_data(data, name, p_ptr, sizeof(p_ptr));
128 }
129
130 EXPORT bool calldata_get_string(const calldata_t *data, const char *name,
131 const char **str);
132
133 /* ------------------------------------------------------------------------- */
134 /* call if you know your data is valid */
135
calldata_int(const calldata_t * data,const char * name)136 static inline long long calldata_int(const calldata_t *data, const char *name)
137 {
138 long long val = 0;
139 calldata_get_int(data, name, &val);
140 return val;
141 }
142
calldata_float(const calldata_t * data,const char * name)143 static inline double calldata_float(const calldata_t *data, const char *name)
144 {
145 double val = 0.0;
146 calldata_get_float(data, name, &val);
147 return val;
148 }
149
calldata_bool(const calldata_t * data,const char * name)150 static inline bool calldata_bool(const calldata_t *data, const char *name)
151 {
152 bool val = false;
153 calldata_get_bool(data, name, &val);
154 return val;
155 }
156
calldata_ptr(const calldata_t * data,const char * name)157 static inline void *calldata_ptr(const calldata_t *data, const char *name)
158 {
159 void *val = NULL;
160 calldata_get_ptr(data, name, &val);
161 return val;
162 }
163
calldata_string(const calldata_t * data,const char * name)164 static inline const char *calldata_string(const calldata_t *data,
165 const char *name)
166 {
167 const char *val = NULL;
168 calldata_get_string(data, name, &val);
169 return val;
170 }
171
172 /* ------------------------------------------------------------------------- */
173
calldata_set_int(calldata_t * data,const char * name,long long val)174 static inline void calldata_set_int(calldata_t *data, const char *name,
175 long long val)
176 {
177 calldata_set_data(data, name, &val, sizeof(val));
178 }
179
calldata_set_float(calldata_t * data,const char * name,double val)180 static inline void calldata_set_float(calldata_t *data, const char *name,
181 double val)
182 {
183 calldata_set_data(data, name, &val, sizeof(val));
184 }
185
calldata_set_bool(calldata_t * data,const char * name,bool val)186 static inline void calldata_set_bool(calldata_t *data, const char *name,
187 bool val)
188 {
189 calldata_set_data(data, name, &val, sizeof(val));
190 }
191
calldata_set_ptr(calldata_t * data,const char * name,void * ptr)192 static inline void calldata_set_ptr(calldata_t *data, const char *name,
193 void *ptr)
194 {
195 calldata_set_data(data, name, &ptr, sizeof(ptr));
196 }
197
calldata_set_string(calldata_t * data,const char * name,const char * str)198 static inline void calldata_set_string(calldata_t *data, const char *name,
199 const char *str)
200 {
201 if (str)
202 calldata_set_data(data, name, str, strlen(str) + 1);
203 else
204 calldata_set_data(data, name, NULL, 0);
205 }
206
207 #ifdef __cplusplus
208 }
209 #endif
210