-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdynamic.h
352 lines (319 loc) · 13.3 KB
/
dynamic.h
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/**
* @file dynamic.h
* @author André Dietrich
* @date 9 April 2016
* @brief Dynamic data types as part of the SelectScript-VM implementation.
*
* @license MIT
*
* @see https://ess-ovgu.github.io/dynamiC
*/
#ifndef DYN_C_H
#define DYN_C_H
#include <stdlib.h>
#include "dynamic_types.h"
#include "dynamic_defines.h"
#include "dynamic_string.h"
#include "dynamic_encoding.h"
/**
* \defgroup DynamicBase
*
* @brief basic functionality for scalar dynamic data types
*
* These functions and macros cover basic scalar data types, their handling,
* initialization, etc. Every module includes its own functions for memory
* allocation and freeing, but functions such as dyn_free, dyn_get_string,
* as well es others provide basic interfaces, which hide the additional and
* type specific functionality which is required to deal with different dynamic
* data types.
*
* @{
*/
//! Mandatory initialization for dynamic elements (NONE)
#define DYN_INIT(dyn) (dyn)->type=NONE
//! Return type value of a dynamic element @see TYPE
#define DYN_TYPE(dyn) (dyn)->type
//! Check if dynamic element is of type NONE
#define DYN_IS_NONE(dyn) !DYN_TYPE(dyn)
//! Check if dynamic element is not of type NONE
#define DYN_NOT_NONE(dyn) DYN_TYPE(dyn)
//! Check if dynamic element is of type REFERENCE
#define DYN_IS_REFERENCE(dyn) \
DYN_TYPE(dyn)==REFERENCE || DYN_TYPE(dyn)==REFERENCE2
//! Return type value of a dynamic element @see TYPE
TYPE dyn_type (const dyn_c* dyn);
//! free allocated memory
void dyn_free (dyn_c* dyn);
//! Deep copy dynamic element
trilean dyn_copy (const dyn_c* dyn, dyn_c* copy);
//! Move dynamic element to new reference, from is of type NONE afterwards
void dyn_move (dyn_c* from, dyn_c* to);
#define DYN_MOVE(from, to) *to = *from; DYN_INIT(from)
/** @brief Reterns the length of an element.
*
* @param[in] dyn value to check
* @return length
*/
dyn_ushort dyn_length (const dyn_c* dyn);
//! Return the number of allocated bytes
dyn_uint dyn_size (const dyn_c* dyn);
//! Set dynamic element to NONE
void dyn_set_none (dyn_c* dyn);
//! Set dynamic element to BOOL (DYN_TRUE or DYN_FALSE)
void dyn_set_bool (dyn_c* dyn, const dyn_char v);
//! Set dynamic element to INTEGER
void dyn_set_int (dyn_c* dyn, const dyn_int v);
//! Set dynamic element to FLOAT
void dyn_set_float (dyn_c* dyn, const dyn_float v);
//! Set dynamic element to point to an arbitrary value
void dyn_set_extern (dyn_c* dyn, const void* v);
//! Set dynamic element to STRING
trilean dyn_set_string (dyn_c* dyn, dyn_const_str v);
//! Set dynamic element as reference to another dynamic element
void dyn_set_ref (dyn_c* ref, dyn_c* orig);
//! Return boolean value of an dynamic element
trilean dyn_get_bool (const dyn_c* dyn);
/** @brief Returns the trinary truth value (DYN_TRUE|DYN_FALSE|DYN_NONE) of an
* element.
*
* Only an element of type NONE results in a return value of DYN_NONE, all
* other types result in a boolean value, as defined in @see dyn_get_bool
*
* @param[in] dyn value to check
* @returnval DYN_TRUE ( 1)
* @returnval DYN_FALSE ( 0)
* @returnval DYN_NONE (-1)
*/
trilean dyn_get_bool_3 (const dyn_c* dyn);
//! Return integer value of a dynamic element
dyn_int dyn_get_int (const dyn_c* dyn);
//! Return float value of a dynamic element
dyn_float dyn_get_float (const dyn_c* dyn);
//! Return string representation value of a dynamic element
dyn_str dyn_get_string (const dyn_c* dyn);
//! Return pointer, stored in dyn->data.ex
const void* dyn_get_extern (const dyn_c* dyn);
//! Add string representation of dynamic element to string
void dyn_string_add (const dyn_c* dyn, dyn_str string);
//! Calculate length of string representation of dynamic element
dyn_ushort dyn_string_len (const dyn_c* dyn);
/**@}*/
/**
* \defgroup DynamicList
*
* @brief All list related functions.
*
* @{
*/
//! Initialize dyn as list with default length
#define DYN_SET_LIST(dyn) dyn_set_list_len(dyn, LIST_DEFAULT)
//! Return list length
#define DYN_LIST_LEN(dyn) (dyn)->data.list->length
//! Return the reference to the ith element within a dynamic list
#define DYN_LIST_GET_REF(dyn,i) &(dyn)->data.list->container[i]
//! Return the reference to the last element within a list
#define DYN_LIST_GET_END(dyn) \
&(dyn)->data.list->container[DYN_LIST_LEN(dyn)-1]
//! Return the reference to the ith element starting from the last
#define DYN_LIST_GET_REF_END(dyn,i) \
&(dyn)->data.list->container[DYN_LIST_LEN(dyn)-i]
//! Set dynamic element to list with maximal length
trilean dyn_set_list_len (dyn_c* dyn, dyn_ushort len);
//! Push new element to the end of a list
dyn_c* dyn_list_push (dyn_c* list, const dyn_c* element);
//! Push NONE element to the end of a list
dyn_c* dyn_list_push_none (dyn_c* list);
//! Pop the last element from the list and move it to param element
trilean dyn_list_pop (dyn_c* list, dyn_c* element);
//! Copy the ith element of a list to param element
trilean dyn_list_get (const dyn_c* list, dyn_c* element, const dyn_short i);
//! Return a reference to the ith element within list, negative values are allowed
dyn_c* dyn_list_get_ref (const dyn_c* list, const dyn_short i);
//! Pop i elements from the end of a list
trilean dyn_list_popi (dyn_c* list, const dyn_short i);
//! Free the allocated memory of the entire list and set it to NONE
void dyn_list_free (dyn_c* list);
//! Make a deep copy of the entire list
trilean dyn_list_copy (const dyn_c* list, dyn_c* copy);
//! Delete the ith element from a list
trilean dyn_list_remove (dyn_c* list, dyn_ushort i);
//! Insert a new element at the ith position into a list
trilean dyn_list_insert (dyn_c* list, dyn_c* element, const dyn_ushort i);
//! Change the maximal space of a list
trilean dyn_list_resize (dyn_c* list, const dyn_ushort size);
//! Return the length of the string representation of a list
dyn_ushort dyn_list_string_len (const dyn_c* list);
//! Add string representation of a list to str
void dyn_list_string_add (const dyn_c* list, dyn_str str);
/**@}*/
/**
* \defgroup DynamicSet
*
* @brief Extension of type LIST to handle and implement SET
*
* @{
*/
#ifdef S2_SET
//! Initialize dynamic element as empty set with maximal length
trilean dyn_set_set_len (dyn_c* set, const dyn_ushort len);
//! Insert new element into set, if and only if it is not included yet
trilean dyn_set_insert (dyn_c* set, dyn_c* element);
// Delete element from a set
//dyn_char dyn_set_remove (dyn_c* set, dyn_c* element);
#endif
/**@}*/
/**
* \defgroup DynamicDictionary
* @{
*/
//! Return number of elements within a dictionary
#define DYN_DICT_LEN(dyn) \
dyn->data.dict->value.data.list->length
//! Return a reference to the ith element stored within a dictionary
#define DYN_DICT_GET_I_REF(dyn,i) \
&(dyn)->data.dict->value.data.list->container[i]
//! Return a reference to the ith key stored within a dictionary
#define DYN_DICT_GET_I_KEY(dyn,i) (dyn)->data.dict->key[i]
//! Return the maximal usable number of elements of a dictionary
#define DYN_DICT_SPACE(dyn) dyn->value.data.list->space
//! Return the number of elements stored within a dictionary
#define DYN_DICT_LENGTH(dyn) dyn->value.data.list->length
//! Set dyn to a dictionary with a max. length of elements
trilean dyn_set_dict (dyn_c* dyn, const dyn_ushort length);
//! Replace the ith element in a dictionary with a new value
trilean dyn_dict_change (dyn_c* dict, const dyn_ushort i, const dyn_c *value);
//! Insert a new key-value pair into the dictionary
dyn_c* dyn_dict_insert (dyn_c* dict, dyn_const_str key, dyn_c *value);
//! Remove key-value pair from dictionary
trilean dyn_dict_remove (dyn_c* dict, dyn_const_str key);
//! Get the reference to value stored at key
dyn_c* dyn_dict_get (const dyn_c* dict, dyn_const_str key);
//! Set the available space for elements
trilean dyn_dict_resize (dyn_c* dict, const dyn_ushort size);
//! Get the reference to ith value in dict
dyn_c* dyn_dict_get_i_ref (const dyn_c* dict, const dyn_ushort i);
//! Get the reference to ith key in dict
dyn_str dyn_dict_get_i_key (const dyn_c* dict, const dyn_ushort i);
//! Check if dict has key and return its position - 1 (returns 0 if not found)
dyn_ushort dyn_dict_has_key (const dyn_c* dict, dyn_const_str key);
//! todo
void dyn_dict_empty (dyn_c* dict);
//! Free all allocated memory
void dyn_dict_free (dyn_c* dict);
//! Copy the entire dict
trilean dyn_dict_copy (const dyn_c* dict, dyn_c* copy);
//! Calculate the required string length
dyn_ushort dyn_dict_string_len(const dyn_c* dict);
//! Add the dict-string representation to string
void dyn_dict_string_add(const dyn_c* dict, dyn_str string);
/**@}*/
/**
* \defgroup DynamicFunction
* @{
*/
#define DYN_FCT_C 0
#define DYN_FCT_SYS 1
#define DYN_FCT_PROC 2
#define DYN_FCT_GET_CODE(dyn) dyn->data.fct->ptr
trilean dyn_set_fct (dyn_c* dyn, void *ptr, const dyn_ushort type, dyn_const_str info);
void dyn_fct_free (dyn_c* dyn);
trilean dyn_fct_copy (const dyn_c* dyn, dyn_c* copy);
/**@}*/
/**
* \defgroup DynamicOperations
*
* @brief Defintion of all dynamic operations, including arithmetic, logical,
* relational, and bit-operations.
*
* These functions cover all basic operations, which are common for most
* programming languages. In principle most operations known from Python are
* offered with a similar behavior, but with two differences. Dynamic
* operations evaluate a result based on the data type with the highes priority
* and not on the basis of left-hand and right-hand parameters. That means, for
* dynple (see the defintion of every function):
*
* @code
* // LIST type is higher than STRING type
* dyn_op_add([1,2,3], "test string") == [1,2,3,"test string"]
* dyn_op_add("test string", [1,2,3]) == ["test string",1,2,3]
*
* // STRING type is higher than INTEGER type
* dyn_op_mul(3, "abc") == "abcabcabc"
* dyn_op_mul("abc", 3) == "abcabcabc"
*
* // FLOAT type is higher than INTEGER type
* dyn_op_div(9.0, 3) == 3.0
* dyn_op_div(9, 3.0) == 3.0
* @endcode
*
* The result is always stored and returned within the first parameter passed
* to an operator function. If this parameter is a dynamic reference of TYPE
* REFERENCE or REFERENCE2, then a new element is created, the original element
* remains. If the operation was performed without any error, then DYN_TRUE is
* returned by every function of that module, otherwise DYN_FALSE.
*
* A second characteristic of the operations applied is that a trinary logical
* system is applied to simplify error-handling amongst other benefits. Trinary
* means that next to the two boolean values DYN_TRUE and DYN_FALSE, the NONE
* type is used to represent another unknown or undefined state. The benefit is,
* that comparing two distinct dynamic types such as a list and a string with
* less than or greater than results in that unknown/undefined state and not
* in an error. This trinary logical system is also perfect for applying
* logical operations, see therefor the corresponding logical functions.
*
* @see https://en.wikipedia.org/wiki/Three-valued_logic
*
* @{
*/
//! Negate dynamic value in param dyn
trilean dyn_op_neg(dyn_c *dyn);
//! Add dyn2 to dyn1
trilean dyn_op_add(dyn_c *dyn1, dyn_c *dyn2);
//! Subtract dyn2 from dyn1
trilean dyn_op_sub(dyn_c *dyn1, dyn_c *dyn2);
//! Multiply dyn1 with dyn2
trilean dyn_op_mul(dyn_c *dyn1, dyn_c *dyn2);
//! Divide dyn1 by dyn2
trilean dyn_op_div(dyn_c *dyn1, dyn_c *dyn2);
//! dyn1 Modulo dyn2
trilean dyn_op_mod(dyn_c *dyn1, dyn_c *dyn2);
//! dyn1 to the power of dyn2
trilean dyn_op_pow(dyn_c *dyn1, dyn_c *dyn2);
//! Logical (trinary) AND operation
trilean dyn_op_and(dyn_c *dyn1, dyn_c *dyn2);
//! Logical (trinary) OR operation
trilean dyn_op_or (dyn_c *dyn1, dyn_c *dyn2);
//! Logical (trinary) XOR operation
trilean dyn_op_xor(dyn_c *dyn1, dyn_c *dyn2);
//! Logical (trinary) Negation
trilean dyn_op_not(dyn_c *dyn);
//! Type and Value Equality
trilean dyn_op_id (dyn_c *dyn1, dyn_c *dyn2);
//! Relational Equality
trilean dyn_op_eq (dyn_c *dyn1, dyn_c *dyn2);
//! Relational Not Equal
trilean dyn_op_ne (dyn_c *dyn1, dyn_c *dyn2);
//! Relational Less Than
trilean dyn_op_lt (dyn_c *dyn1, dyn_c *dyn2);
//! Relational Less Than or Equal
trilean dyn_op_le (dyn_c *dyn1, dyn_c *dyn2);
//! Relational Greater Than
trilean dyn_op_gt (dyn_c *dyn1, dyn_c *dyn2);
//! Relational Greater Than or Equal
trilean dyn_op_ge (dyn_c *dyn1, dyn_c *dyn2);
//! Check if dyn2 is element of dyn1
trilean dyn_op_in (dyn_c *element, dyn_c *container);
//! Binary complement
trilean dyn_op_b_not(dyn_c *dyn);
//! Binary AND
trilean dyn_op_b_and(dyn_c *dyn1, dyn_c *dyn2);
//! Binary OR
trilean dyn_op_b_or (dyn_c *dyn1, dyn_c *dyn2);
//! Binary XOR
trilean dyn_op_b_xor(dyn_c *dyn1, dyn_c *dyn2);
//! Binary shift left
trilean dyn_op_b_shift_l(dyn_c *dyn1, dyn_c *dyn2);
//! Binary shift right
trilean dyn_op_b_shift_r(dyn_c *dyn1, dyn_c *dyn2);
/**@}*/
#endif //DYN_C_H