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