iodine 0.4.14 → 0.4.15
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +61 -33
- data/README.md +7 -5
- data/ext/iodine/base64.c +12 -0
- data/ext/iodine/defer.c +211 -108
- data/ext/iodine/defer.h +7 -0
- data/ext/iodine/facil.c +5 -1
- data/ext/iodine/facil.h +1 -1
- data/ext/iodine/fio2resp.c +19 -30
- data/ext/iodine/fio2resp.h +2 -1
- data/ext/iodine/fio_cli_helper.c +2 -2
- data/ext/iodine/fiobj.h +11 -624
- data/ext/iodine/fiobj_ary.c +65 -26
- data/ext/iodine/fiobj_ary.h +106 -0
- data/ext/iodine/fiobj_hash.c +175 -115
- data/ext/iodine/fiobj_hash.h +128 -0
- data/ext/iodine/fiobj_internal.c +189 -0
- data/ext/iodine/{fiobj_types.h → fiobj_internal.h} +126 -136
- data/ext/iodine/fiobj_json.c +161 -207
- data/ext/iodine/fiobj_json.h +43 -0
- data/ext/iodine/fiobj_numbers.c +53 -35
- data/ext/iodine/fiobj_numbers.h +49 -0
- data/ext/iodine/fiobj_primitives.c +103 -70
- data/ext/iodine/fiobj_primitives.h +55 -0
- data/ext/iodine/fiobj_str.c +171 -59
- data/ext/iodine/fiobj_str.h +113 -0
- data/ext/iodine/fiobj_sym.c +46 -124
- data/ext/iodine/fiobj_sym.h +60 -0
- data/ext/iodine/fiobject.c +589 -0
- data/ext/iodine/fiobject.h +276 -0
- data/ext/iodine/pubsub.h +1 -1
- data/ext/iodine/resp.c +2 -2
- data/ext/iodine/siphash.c +11 -0
- data/ext/iodine/spnlock.inc +7 -5
- data/ext/iodine/websocket_parser.h +44 -7
- data/lib/iodine/version.rb +1 -1
- metadata +13 -8
- data/ext/iodine/fiobj_alloc.c +0 -81
- data/ext/iodine/fiobj_generic.c +0 -260
- data/ext/iodine/fiobj_io.c +0 -58
- data/ext/iodine/fiobj_misc.c +0 -213
- data/ext/iodine/fiobj_tests.c +0 -474
data/ext/iodine/defer.h
CHANGED
@@ -13,6 +13,10 @@ library.
|
|
13
13
|
|
14
14
|
All deferred execution is shared among the same process and inherited by any
|
15
15
|
forked process.
|
16
|
+
|
17
|
+
The defer library could produce a single page "memory leak", since the last task
|
18
|
+
buffer is nenver freed (it's left "on call" for new events). To avoid this leak
|
19
|
+
call `defer_clear_queue` before exiting the program.
|
16
20
|
*/
|
17
21
|
#define H_DEFER_H
|
18
22
|
#define LIB_DEFER_VERSION_MAJOR 0
|
@@ -40,6 +44,9 @@ void defer_perform(void);
|
|
40
44
|
/** returns true if there are deferred functions waiting for execution. */
|
41
45
|
int defer_has_queue(void);
|
42
46
|
|
47
|
+
/** Clears the queue without performing any of the tasks. */
|
48
|
+
void defer_clear_queue(void);
|
49
|
+
|
43
50
|
/* *****************************************************************************
|
44
51
|
Thread Pool support
|
45
52
|
***************************************************************************** */
|
data/ext/iodine/facil.c
CHANGED
@@ -25,7 +25,11 @@ typedef struct ProtocolMetadata {
|
|
25
25
|
unsigned rsv : 8;
|
26
26
|
} protocol_metadata_s;
|
27
27
|
|
28
|
-
|
28
|
+
union protocol_metadata_union_u {
|
29
|
+
size_t opaque;
|
30
|
+
protocol_metadata_s meta;
|
31
|
+
};
|
32
|
+
#define prt_meta(prt) (((union protocol_metadata_union_u *)(&(prt)->rsv))->meta)
|
29
33
|
|
30
34
|
struct connection_data_s {
|
31
35
|
protocol_s *protocol;
|
data/ext/iodine/facil.h
CHANGED
data/ext/iodine/fio2resp.c
CHANGED
@@ -10,8 +10,8 @@ Copyright refers to the parser, not the protocol.
|
|
10
10
|
#define _GNU_SOURCE
|
11
11
|
#endif
|
12
12
|
|
13
|
-
#include "fio2resp.h"
|
14
13
|
#include "fiobj.h"
|
14
|
+
#include "resp.h"
|
15
15
|
|
16
16
|
#include <stdio.h>
|
17
17
|
#include <stdlib.h>
|
@@ -20,42 +20,31 @@ Copyright refers to the parser, not the protocol.
|
|
20
20
|
static int resp_fioformat_task(fiobj_s *obj, void *s_) {
|
21
21
|
fiobj_s *str = s_;
|
22
22
|
|
23
|
-
|
24
|
-
case FIOBJ_T_FALSE:
|
23
|
+
if (obj->type == FIOBJ_T_FALSE)
|
25
24
|
fiobj_str_write(str, "false\r\n", 7);
|
26
|
-
|
27
|
-
case FIOBJ_T_TRUE:
|
25
|
+
else if (obj->type == FIOBJ_T_TRUE)
|
28
26
|
fiobj_str_write(str, "true\r\n", 6);
|
29
|
-
|
30
|
-
case FIOBJ_T_STRING:
|
31
|
-
case FIOBJ_T_SYMBOL: {
|
32
|
-
/* use this opportunity to optimize memory allocation to page boundries */
|
33
|
-
fio_cstr_s s = fiobj_obj2cstr(str);
|
34
|
-
if (fiobj_str_capa(str) <= s.len + 128 + fiobj_obj2cstr(obj).len) {
|
35
|
-
fiobj_str_resize(str, (((fiobj_str_capa(str) >> 12) + 1) << 12) - 1);
|
36
|
-
fiobj_str_resize(str, s.len);
|
37
|
-
}
|
38
|
-
}
|
39
|
-
/* fallthrough */
|
40
|
-
case FIOBJ_T_NUMBER:
|
41
|
-
case FIOBJ_T_FLOAT:
|
42
|
-
fiobj_str_join(str, obj);
|
43
|
-
fiobj_str_write(str, "\r\n", 2);
|
44
|
-
break;
|
45
|
-
case FIOBJ_T_IO:
|
46
|
-
case FIOBJ_T_NULL:
|
27
|
+
else if (obj->type == FIOBJ_T_NULL)
|
47
28
|
fiobj_str_write(str, "$-1\r\n", 4);
|
48
|
-
|
49
|
-
case FIOBJ_T_ARRAY:
|
29
|
+
else if (obj->type == FIOBJ_T_ARRAY)
|
50
30
|
fiobj_str_write2(str, "*%lu\r\n", (unsigned long)fiobj_ary_count(obj));
|
51
|
-
|
52
|
-
case FIOBJ_T_HASH:
|
31
|
+
else if (obj->type == FIOBJ_T_HASH)
|
53
32
|
fiobj_str_write2(str, "*%lu\r\n", (unsigned long)fiobj_hash_count(obj));
|
54
|
-
|
55
|
-
|
33
|
+
else if (obj->type == FIOBJ_T_COUPLET) {
|
34
|
+
fiobj_str_write(str, "*2\r\n", 4);
|
56
35
|
resp_fioformat_task(fiobj_couplet2key(obj), s_);
|
57
36
|
resp_fioformat_task(fiobj_couplet2obj(obj), s_);
|
58
|
-
|
37
|
+
} else {
|
38
|
+
if (obj->type == FIOBJ_T_SYMBOL || FIOBJ_IS_STRING(obj)) {
|
39
|
+
/* use this opportunity to optimize memory allocation to page boundries */
|
40
|
+
fio_cstr_s s = fiobj_obj2cstr(str);
|
41
|
+
if (fiobj_str_capa(str) <= s.len + 128 + fiobj_obj2cstr(obj).len) {
|
42
|
+
fiobj_str_resize(str, (((fiobj_str_capa(str) >> 12) + 1) << 12) - 1);
|
43
|
+
fiobj_str_resize(str, s.len);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
fiobj_str_join(str, obj);
|
47
|
+
fiobj_str_write(str, "\r\n", 2);
|
59
48
|
}
|
60
49
|
return 0;
|
61
50
|
}
|
data/ext/iodine/fio2resp.h
CHANGED
@@ -11,6 +11,7 @@ This is a neive implementation of the RESP protocol for Redis.
|
|
11
11
|
*/
|
12
12
|
#define H_FIO2RESP_FORMAT_H
|
13
13
|
|
14
|
+
#include "fiobj.h"
|
14
15
|
#include "resp.h"
|
15
16
|
|
16
17
|
/* support C++ */
|
@@ -21,7 +22,7 @@ extern "C" {
|
|
21
22
|
/* *****************************************************************************
|
22
23
|
`fiobj_s` => RESP (formatting): implemented seperately; can be safely removed.
|
23
24
|
***************************************************************************** */
|
24
|
-
|
25
|
+
|
25
26
|
/**
|
26
27
|
* Returns a **new** String object containing a RESP representation of `obj`.
|
27
28
|
*
|
data/ext/iodine/fio_cli_helper.c
CHANGED
@@ -181,7 +181,7 @@ static void fio_cli_parse(void) {
|
|
181
181
|
goto error;
|
182
182
|
/* at this point arg_name is a handle to the argument's Symbol */
|
183
183
|
fiobj_s *type = fiobj_hash_get(arg_type, arg_name);
|
184
|
-
if (
|
184
|
+
if (type->type == FIOBJ_T_NULL) {
|
185
185
|
/* type is BOOL, no further processing required */
|
186
186
|
start = "1";
|
187
187
|
len = 1;
|
@@ -197,7 +197,7 @@ static void fio_cli_parse(void) {
|
|
197
197
|
} else
|
198
198
|
start = start + len;
|
199
199
|
len = 0;
|
200
|
-
if (
|
200
|
+
if (type->type == FIOBJ_T_FALSE) /* no restrictions on data */
|
201
201
|
goto set_arg;
|
202
202
|
/* test that the argument is numerical */
|
203
203
|
if (start[len] == '-') /* negative number? */
|
data/ext/iodine/fiobj.h
CHANGED
@@ -1,631 +1,18 @@
|
|
1
|
-
#ifndef H_FACIL_IO_OBJECTS_H
|
2
1
|
/*
|
3
|
-
Copyright: Boaz
|
2
|
+
Copyright: Boaz Segev, 2017
|
4
3
|
License: MIT
|
5
|
-
|
6
|
-
Feel free to copy, use and enjoy according to the license provided.
|
7
|
-
*/
|
8
|
-
|
9
|
-
/**
|
10
|
-
This facil.io core library provides wrappers around complex and (or) dynamic
|
11
|
-
types, abstracting some complexity and making dynamic type related tasks easier.
|
12
|
-
|
13
|
-
|
14
|
-
The library offers a rudementry protection against cyclic references using the
|
15
|
-
`FIOBJ_NESTING_PROTECTION` flag (i.e., nesting an Array within itself)...
|
16
|
-
however, this isn't fully tested and the performance price is high.
|
17
4
|
*/
|
18
|
-
#
|
5
|
+
#ifndef FIOBJ_H
|
6
|
+
#define FIOBJ_H
|
19
7
|
|
20
|
-
#include
|
21
|
-
#include <stdint.h>
|
22
|
-
#include <stdio.h>
|
23
|
-
#include <stdlib.h>
|
8
|
+
#include "fiobject.h"
|
24
9
|
|
25
|
-
#
|
26
|
-
|
27
|
-
#
|
10
|
+
#include "fiobj_ary.h"
|
11
|
+
#include "fiobj_hash.h"
|
12
|
+
#include "fiobj_json.h"
|
13
|
+
#include "fiobj_numbers.h"
|
14
|
+
#include "fiobj_primitives.h"
|
15
|
+
#include "fiobj_str.h"
|
16
|
+
#include "fiobj_sym.h"
|
28
17
|
|
29
|
-
/**
|
30
|
-
* Sets the default state for nesting protection.
|
31
|
-
*
|
32
|
-
* NOTICE: facil.io's default makefile will disables nesting protection.
|
33
|
-
*
|
34
|
-
* This effects traversing functions, such as `fiobj_each2`, `fiobj_dup`,
|
35
|
-
* `fiobj_free` etc'.
|
36
|
-
*/
|
37
|
-
#ifndef FIOBJ_NESTING_PROTECTION
|
38
|
-
#define FIOBJ_NESTING_PROTECTION 0
|
39
18
|
#endif
|
40
|
-
|
41
|
-
/* *****************************************************************************
|
42
|
-
The Object type (`fiobj_s`) and it's variants
|
43
|
-
***************************************************************************** */
|
44
|
-
|
45
|
-
/* FIO Object types */
|
46
|
-
typedef enum {
|
47
|
-
/** A simple flag object indicating a NULL (or nil) object */
|
48
|
-
FIOBJ_T_NULL,
|
49
|
-
/** A simple flag object indicating a TRUE value. */
|
50
|
-
FIOBJ_T_TRUE,
|
51
|
-
/** A simple flag object indicating a FALSE value. */
|
52
|
-
FIOBJ_T_FALSE,
|
53
|
-
/** A signed numerical object containing an `int64_t`. */
|
54
|
-
FIOBJ_T_NUMBER,
|
55
|
-
/** A signed numerical object containing a `double`. */
|
56
|
-
FIOBJ_T_FLOAT,
|
57
|
-
/** A String object. */
|
58
|
-
FIOBJ_T_STRING,
|
59
|
-
/** A Symbol object. This object contains an immutable String. */
|
60
|
-
FIOBJ_T_SYMBOL,
|
61
|
-
/** An Array object. */
|
62
|
-
FIOBJ_T_ARRAY,
|
63
|
-
/** A Hash Table object. Hash keys MUST be Symbol objects. */
|
64
|
-
FIOBJ_T_HASH,
|
65
|
-
/** A Hash Table key-value pair. See `fiobj_each2`.
|
66
|
-
*
|
67
|
-
* This should be considered a virtual object and shouldn't saved outside of
|
68
|
-
* the `fiobj_each2` loop.
|
69
|
-
*/
|
70
|
-
FIOBJ_T_COUPLET,
|
71
|
-
/** An IO object containing an `intptr_t` as a `fd` (File Descriptor). */
|
72
|
-
FIOBJ_T_IO,
|
73
|
-
} fiobj_type_en;
|
74
|
-
|
75
|
-
typedef struct fiobj_s { fiobj_type_en type; } fiobj_s;
|
76
|
-
typedef fiobj_s *fiobj_pt;
|
77
|
-
|
78
|
-
/* *****************************************************************************
|
79
|
-
Helper macros
|
80
|
-
***************************************************************************** */
|
81
|
-
|
82
|
-
/** returns TRUE (1) if the object is NULL */
|
83
|
-
#define FIOBJ_ISNULL(o) ((o) == NULL || (o)->type == FIOBJ_T_NULL)
|
84
|
-
|
85
|
-
/** returns TRUE (1) if the object is either NULL or FALSE */
|
86
|
-
#define FIOBJ_FALSE(o) \
|
87
|
-
((o) == NULL || (o)->type == FIOBJ_T_FALSE || (o)->type == FIOBJ_T_NULL)
|
88
|
-
|
89
|
-
/** returns TRUE (1) if the object isn't NULL, FALSE, 0, or an empty String */
|
90
|
-
#define FIOBJ_TRUE(o) \
|
91
|
-
((o) && \
|
92
|
-
((o)->type == FIOBJ_T_TRUE || \
|
93
|
-
((o)->type == FIOBJ_T_NUMBER && fiobj_obj2num((o)) != 0) || \
|
94
|
-
((o)->type == FIOBJ_T_FLOAT && fiobj_obj2float((o)) != 0) || \
|
95
|
-
((o)->type == FIOBJ_T_STRING && fiobj_obj2cstr((o)).data[0] != 0) || \
|
96
|
-
(o)->type == FIOBJ_T_SYMBOL || (o)->type == FIOBJ_T_ARRAY || \
|
97
|
-
(o)->type == FIOBJ_T_HASH || (o)->type == FIOBJ_T_IO || \
|
98
|
-
(o)->type == FIOBJ_T_FILE))
|
99
|
-
|
100
|
-
/* *****************************************************************************
|
101
|
-
JSON API
|
102
|
-
***************************************************************************** */
|
103
|
-
|
104
|
-
/**
|
105
|
-
* Parses JSON, setting `pobj` to point to the new Object.
|
106
|
-
*
|
107
|
-
* Returns the number of bytes consumed. On Error, 0 is returned and no data is
|
108
|
-
* consumed.
|
109
|
-
*/
|
110
|
-
size_t fiobj_json2obj(fiobj_s **pobj, const void *data, size_t len);
|
111
|
-
/* Formats an object into a JSON String. Remember to `fiobj_free`. */
|
112
|
-
fiobj_s *fiobj_obj2json(fiobj_s *, uint8_t pretty);
|
113
|
-
|
114
|
-
/* *****************************************************************************
|
115
|
-
Generic Object API
|
116
|
-
***************************************************************************** */
|
117
|
-
|
118
|
-
/**
|
119
|
-
* Copy by reference(!) - increases an object's (and any nested object's)
|
120
|
-
* reference count.
|
121
|
-
*
|
122
|
-
* Always returns the value passed along.
|
123
|
-
*
|
124
|
-
* Future implementations might provide `fiobj_dup2` providing a deep copy.
|
125
|
-
*
|
126
|
-
* We don't need this feature just yet, so I'm not working on it.
|
127
|
-
*/
|
128
|
-
fiobj_s *fiobj_dup(fiobj_s *);
|
129
|
-
|
130
|
-
/**
|
131
|
-
* Decreases an object's reference count, releasing memory and
|
132
|
-
* resources.
|
133
|
-
*
|
134
|
-
* This function affects nested objects, meaning that when an Array or
|
135
|
-
* a Hashe object is passed along, it's children (nested objects) are
|
136
|
-
* also freed.
|
137
|
-
*/
|
138
|
-
void fiobj_free(fiobj_s *);
|
139
|
-
|
140
|
-
/**
|
141
|
-
* Returns an Object's numerical value.
|
142
|
-
*
|
143
|
-
* If a String or Symbol are passed to the function, they will be
|
144
|
-
* parsed assuming base 10 numerical data.
|
145
|
-
*
|
146
|
-
* Hashes and Arrays return their object count.
|
147
|
-
*
|
148
|
-
* IO and File objects return their underlying file descriptor.
|
149
|
-
*
|
150
|
-
* A type error results in 0.
|
151
|
-
*/
|
152
|
-
int64_t fiobj_obj2num(fiobj_s *obj);
|
153
|
-
|
154
|
-
/**
|
155
|
-
* Returns a Float's value.
|
156
|
-
*
|
157
|
-
* If a String or Symbol are passed to the function, they will be
|
158
|
-
* parsed assuming base 10 numerical data.
|
159
|
-
*
|
160
|
-
* Hashes and Arrays return their object count.
|
161
|
-
*
|
162
|
-
* IO and File objects return their underlying file descriptor.
|
163
|
-
*
|
164
|
-
* A type error results in 0.
|
165
|
-
*/
|
166
|
-
double fiobj_obj2float(fiobj_s *obj);
|
167
|
-
|
168
|
-
/** A string information type, reports anformation about a C string. */
|
169
|
-
typedef struct {
|
170
|
-
union {
|
171
|
-
uint64_t len;
|
172
|
-
uint64_t length;
|
173
|
-
};
|
174
|
-
union {
|
175
|
-
const void *buffer;
|
176
|
-
const uint8_t *bytes;
|
177
|
-
const char *data;
|
178
|
-
const char *value;
|
179
|
-
const char *name;
|
180
|
-
};
|
181
|
-
} fio_cstr_s;
|
182
|
-
|
183
|
-
/**
|
184
|
-
* Returns a C String (NUL terminated) using the `fio_cstr_s` data type.
|
185
|
-
*
|
186
|
-
* The Sting in binary safe and might contain NUL bytes in the middle as well as
|
187
|
-
* a terminating NUL.
|
188
|
-
*
|
189
|
-
* If a Symbol, a Number or a Float are passed to the function, they
|
190
|
-
* will be parsed as a *temporary*, thread-safe, String.
|
191
|
-
*
|
192
|
-
* Numbers will be represented in base 10 numerical data.
|
193
|
-
*
|
194
|
-
* A type error results in NULL (i.e. object isn't a String).
|
195
|
-
*/
|
196
|
-
fio_cstr_s fiobj_obj2cstr(fiobj_s *obj);
|
197
|
-
|
198
|
-
/**
|
199
|
-
* Single layer iteration using a callback for each nested fio object.
|
200
|
-
*
|
201
|
-
* Accepts any `fiobj_s *` type but only collections (Arrays and Hashes) are
|
202
|
-
* processed. The container itself (the Array or the Hash) is **not** processed
|
203
|
-
* (unlike `fiobj_each2`).
|
204
|
-
*
|
205
|
-
* The callback task function must accept an object and an opaque user pointer.
|
206
|
-
*
|
207
|
-
* Hash objects pass along a `FIOBJ_T_COUPLET` object, containing
|
208
|
-
* references for both the key (Symbol) and the object (any object).
|
209
|
-
*
|
210
|
-
* If the callback returns -1, the loop is broken. Any other value is ignored.
|
211
|
-
*
|
212
|
-
* Returns the "stop" position, i.e., the number of items processed + the
|
213
|
-
* starting point.
|
214
|
-
*/
|
215
|
-
size_t fiobj_each1(fiobj_s *, size_t start_at,
|
216
|
-
int (*task)(fiobj_s *obj, void *arg), void *arg);
|
217
|
-
|
218
|
-
/**
|
219
|
-
* Deep iteration using a callback for each fio object, including the parent.
|
220
|
-
*
|
221
|
-
* Accepts any `fiobj_s *` type.
|
222
|
-
*
|
223
|
-
* Collections (Arrays, Hashes) are deeply probed and shouldn't be edited
|
224
|
-
* during an `fiobj_each2` call (or weird things may happen).
|
225
|
-
*
|
226
|
-
* The callback task function must accept an object and an opaque user pointer.
|
227
|
-
*
|
228
|
-
* If `FIOBJ_NESTING_PROTECTION` is equal to 1 and a cyclic (or recursive)
|
229
|
-
* nesting is detected, a NULL pointer (not a NULL object) will be used instead
|
230
|
-
* of the original (cyclic) object and the original (cyclic) object will be
|
231
|
-
* available using the `fiobj_each_get_cyclic` function.
|
232
|
-
*
|
233
|
-
* Hash objects pass along a `FIOBJ_T_COUPLET` object, containing
|
234
|
-
* references for both the key (Symbol) and the object (any object).
|
235
|
-
*
|
236
|
-
* Notice that when passing collections to the function, the collection itself
|
237
|
-
* is sent to the callback followed by it's children (if any). This is true also
|
238
|
-
* for nested collections (a nested Hash will be sent first, followed by the
|
239
|
-
* nested Hash's children and then followed by the rest of it's siblings.
|
240
|
-
*
|
241
|
-
* If the callback returns -1, the loop is broken. Any other value is ignored.
|
242
|
-
*/
|
243
|
-
void fiobj_each2(fiobj_s *, int (*task)(fiobj_s *obj, void *arg), void *arg);
|
244
|
-
|
245
|
-
/** Within `fiobj_each2`, this will return the current cyclic object, if any. */
|
246
|
-
fiobj_s *fiobj_each_get_cyclic(void);
|
247
|
-
|
248
|
-
/**
|
249
|
-
* Deeply compare two objects. No hashing is involved.
|
250
|
-
*
|
251
|
-
* Uses a similar algorithm to `fiobj_each2`, except adjusted to two objects.
|
252
|
-
*
|
253
|
-
* Hash order will be ignored when comapring Hashes.
|
254
|
-
*
|
255
|
-
* KNOWN ISSUES:
|
256
|
-
*
|
257
|
-
* * Cyclic nesting will cause this function to hang (much like `fiobj_each2`).
|
258
|
-
*
|
259
|
-
* If `FIOBJ_NESTING_PROTECTION` is set, then cyclic nesting might produce
|
260
|
-
* false positives.
|
261
|
-
*
|
262
|
-
* * Hash order will be ignored when comapring Hashes, which means that equal
|
263
|
-
* Hases might behave differently during iteration.
|
264
|
-
*
|
265
|
-
*/
|
266
|
-
int fiobj_iseq(fiobj_s *obj1, fiobj_s *obj2);
|
267
|
-
|
268
|
-
/* *****************************************************************************
|
269
|
-
NULL, TRUE, FALSE API
|
270
|
-
***************************************************************************** */
|
271
|
-
|
272
|
-
/** Retruns a NULL object. Use `fiobj_free` to free memory.*/
|
273
|
-
fiobj_s *fiobj_null(void);
|
274
|
-
|
275
|
-
/** Retruns a TRUE object. Use `fiobj_free` to free memory. */
|
276
|
-
fiobj_s *fiobj_true(void);
|
277
|
-
|
278
|
-
/** Retruns a FALSE object. Use `fiobj_free` to free memory. */
|
279
|
-
fiobj_s *fiobj_false(void);
|
280
|
-
|
281
|
-
/* *****************************************************************************
|
282
|
-
Number and Float API
|
283
|
-
***************************************************************************** */
|
284
|
-
|
285
|
-
/** Creates a Number object. Remember to use `fiobj_free`. */
|
286
|
-
fiobj_s *fiobj_num_new(int64_t num);
|
287
|
-
|
288
|
-
/** Creates a Float object. Remember to use `fiobj_free`. */
|
289
|
-
fiobj_s *fiobj_float_new(double num);
|
290
|
-
|
291
|
-
/** Mutates a Number object's value. Effects every object's reference! */
|
292
|
-
void fiobj_num_set(fiobj_s *target, int64_t num);
|
293
|
-
|
294
|
-
/** Mutates a Float object's value. Effects every object's reference! */
|
295
|
-
void fiobj_float_set(fiobj_s *target, double num);
|
296
|
-
|
297
|
-
/* *****************************************************************************
|
298
|
-
String API
|
299
|
-
***************************************************************************** */
|
300
|
-
|
301
|
-
/** Creates a String object. Remember to `fiobj_free`. */
|
302
|
-
fiobj_s *fiobj_str_new(const char *str, size_t len);
|
303
|
-
|
304
|
-
/**
|
305
|
-
* Creates a buffer String object. Remember to use `fiobj_free`.
|
306
|
-
*
|
307
|
-
* The default allocation (if capa == 0) is a full memory page (~4096 bytes).
|
308
|
-
*/
|
309
|
-
fiobj_s *fiobj_str_buf(size_t capa);
|
310
|
-
|
311
|
-
/** Creates a copy from an existing String. Remember to use `fiobj_free`. */
|
312
|
-
fiobj_s *fiobj_str_copy(fiobj_s *src);
|
313
|
-
|
314
|
-
/**
|
315
|
-
* Creates a static String object from a static C string. Remember `fiobj_free`.
|
316
|
-
*
|
317
|
-
* This variation avoids allocating memory for an existing static String.
|
318
|
-
*
|
319
|
-
* The object still needs to be frees, but the string isn't copied and isn't
|
320
|
-
* freed.
|
321
|
-
*
|
322
|
-
* NOTICE: static strings can't be written to.
|
323
|
-
*/
|
324
|
-
fiobj_s *fiobj_str_static(const char *str, size_t len);
|
325
|
-
|
326
|
-
/**
|
327
|
-
* Allocates a new String using `prinf` semantics. Remember to `fiobj_free`.
|
328
|
-
*
|
329
|
-
* Returns NULL on error.
|
330
|
-
*/
|
331
|
-
__attribute__((format(printf, 1, 2))) fiobj_s *
|
332
|
-
fiobj_strprintf(const char *printf_frmt, ...);
|
333
|
-
__attribute__((format(printf, 1, 0))) fiobj_s *
|
334
|
-
fiobj_strvprintf(const char *printf_frmt, va_list argv);
|
335
|
-
|
336
|
-
/** Returns a String's capacity, if any. */
|
337
|
-
size_t fiobj_str_capa(fiobj_s *str);
|
338
|
-
|
339
|
-
/** Resizes a String object, allocating more memory if required. */
|
340
|
-
void fiobj_str_resize(fiobj_s *str, size_t size);
|
341
|
-
|
342
|
-
/** Confirms the requested capacity is available and allocates as required. */
|
343
|
-
void fiobj_str_capa_assert(fiobj_s *str, size_t size);
|
344
|
-
|
345
|
-
/** Deallocates any unnecessary memory (if supported by OS). */
|
346
|
-
void fiobj_str_minimize(fiobj_s *str);
|
347
|
-
|
348
|
-
/** Empties a String's data, keeping the existing allocated buffer. */
|
349
|
-
void fiobj_str_clear(fiobj_s *str);
|
350
|
-
|
351
|
-
/**
|
352
|
-
* Writes data at the end of the string, resizing the string as required.
|
353
|
-
*
|
354
|
-
* Returns the new length of the String.
|
355
|
-
*/
|
356
|
-
size_t fiobj_str_write(fiobj_s *dest, const char *data, size_t len);
|
357
|
-
/**
|
358
|
-
* Writes data at the end of the string, using `printf` syntaz and resizing the
|
359
|
-
* string as required.
|
360
|
-
*
|
361
|
-
* Returns the new length of the String.
|
362
|
-
*/
|
363
|
-
size_t fiobj_str_write2(fiobj_s *dest, const char *format, ...);
|
364
|
-
|
365
|
-
/**
|
366
|
-
* Writes data at the end of the string, resizing the string as required.
|
367
|
-
* Returns the new length of the String
|
368
|
-
*/
|
369
|
-
size_t fiobj_str_join(fiobj_s *dest, fiobj_s *obj);
|
370
|
-
|
371
|
-
/* *****************************************************************************
|
372
|
-
Symbol API
|
373
|
-
***************************************************************************** */
|
374
|
-
|
375
|
-
/**
|
376
|
-
* Creates a Symbol object. Always use `fiobj_free`.
|
377
|
-
*
|
378
|
-
* It is better to keep the symbol object than to create a new one each time.
|
379
|
-
* This approach prevents the symbol from being deallocated and reallocated as
|
380
|
-
* well as minimizes hash value computation.
|
381
|
-
*/
|
382
|
-
fiobj_s *fiobj_sym_new(const char *str, size_t len);
|
383
|
-
|
384
|
-
/** Allocated a new Symbol using `prinf` semantics. Remember to `fiobj_free`.*/
|
385
|
-
fiobj_s *fiobj_symprintf(const char *printf_frmt, ...)
|
386
|
-
__attribute__((format(printf, 1, 2)));
|
387
|
-
|
388
|
-
fiobj_s *fiobj_symvprintf(const char *printf_frmt, va_list argv)
|
389
|
-
__attribute__((format(printf, 1, 0)));
|
390
|
-
|
391
|
-
/** Returns 1 if both Symbols are equal and 0 if not. */
|
392
|
-
int fiobj_sym_iseql(fiobj_s *sym1, fiobj_s *sym2);
|
393
|
-
|
394
|
-
/**
|
395
|
-
* Returns a symbol's identifier.
|
396
|
-
*
|
397
|
-
* The unique identifier is calculated using SipHash and is equal for all Symbol
|
398
|
-
* objects that were created using the same data.
|
399
|
-
*/
|
400
|
-
uintptr_t fiobj_sym_id(fiobj_s *sym);
|
401
|
-
|
402
|
-
/* *****************************************************************************
|
403
|
-
IO API
|
404
|
-
***************************************************************************** */
|
405
|
-
|
406
|
-
/** Wrapps a file descriptor in an IO object. Use `fiobj_free` to close. */
|
407
|
-
fiobj_s *fio_io_wrap(intptr_t fd);
|
408
|
-
|
409
|
-
/**
|
410
|
-
* Return an IO's fd.
|
411
|
-
*
|
412
|
-
* A type error results in -1.
|
413
|
-
*/
|
414
|
-
intptr_t fiobj_io_fd(fiobj_s *obj);
|
415
|
-
|
416
|
-
/* *****************************************************************************
|
417
|
-
Array API
|
418
|
-
***************************************************************************** */
|
419
|
-
|
420
|
-
/** Creates an empty Array object. Use `fiobj_free` when done. */
|
421
|
-
fiobj_s *fiobj_ary_new(void);
|
422
|
-
|
423
|
-
/** Creates an empty Array object, preallocating the requested capacity. */
|
424
|
-
fiobj_s *fiobj_ary_new2(size_t capa);
|
425
|
-
|
426
|
-
/** Returns the number of elements in the Array. */
|
427
|
-
size_t fiobj_ary_count(fiobj_s *ary);
|
428
|
-
|
429
|
-
/**
|
430
|
-
* Returns a temporary object owned by the Array.
|
431
|
-
*
|
432
|
-
* Negative values are retrived from the end of the array. i.e., `-1` is the
|
433
|
-
* last item.
|
434
|
-
*/
|
435
|
-
fiobj_s *fiobj_ary_entry(fiobj_s *ary, int64_t pos);
|
436
|
-
|
437
|
-
/**
|
438
|
-
* Sets an object at the requested position.
|
439
|
-
*
|
440
|
-
* If the position overflows the current array size, all intermediate
|
441
|
-
* positions will be set to NULL and the Array will grow in size.
|
442
|
-
*
|
443
|
-
* The old object (if any) occupying the same space will be freed.
|
444
|
-
*
|
445
|
-
* Negative values are retrived from the end of the array. i.e., `-1`
|
446
|
-
* is the last item.
|
447
|
-
*
|
448
|
-
* Type errors are silently ignored.
|
449
|
-
*
|
450
|
-
* For the Array [41], `fiobj_ary_set(ary, fiobj_num_new(42), -10)` will become:
|
451
|
-
* `[42, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 41]`
|
452
|
-
*/
|
453
|
-
void fiobj_ary_set(fiobj_s *ary, fiobj_s *obj, int64_t pos);
|
454
|
-
|
455
|
-
/**
|
456
|
-
* Pushes an object to the end of the Array.
|
457
|
-
*
|
458
|
-
* The Array now owns the object. If an error occurs or the Array is freed, the
|
459
|
-
* object will be freed.
|
460
|
-
*
|
461
|
-
* Use `fiobj_dup` to push a copy, if required.
|
462
|
-
*/
|
463
|
-
void fiobj_ary_push(fiobj_s *ary, fiobj_s *obj);
|
464
|
-
|
465
|
-
/** Pushes a copy of an object to the end of the Array, returning the object.*/
|
466
|
-
static inline __attribute__((unused)) fiobj_s *
|
467
|
-
fiobj_ary_push_dup(fiobj_s *ary, fiobj_s *obj) {
|
468
|
-
fiobj_ary_push(ary, fiobj_dup(obj));
|
469
|
-
return obj;
|
470
|
-
}
|
471
|
-
|
472
|
-
/** Pops an object from the end of the Array. */
|
473
|
-
fiobj_s *fiobj_ary_pop(fiobj_s *ary);
|
474
|
-
|
475
|
-
/**
|
476
|
-
* Unshifts an object to the begining of the Array. This could be
|
477
|
-
* expensive.
|
478
|
-
*
|
479
|
-
* The Array now owns the object. Use `fiobj_dup` to push a copy if
|
480
|
-
* required.
|
481
|
-
*/
|
482
|
-
void fiobj_ary_unshift(fiobj_s *ary, fiobj_s *obj);
|
483
|
-
|
484
|
-
/** Unshifts a copy to the begining of the Array, returning the object.*/
|
485
|
-
static inline __attribute__((unused)) fiobj_s *
|
486
|
-
fiobj_ary_unshift_dup(fiobj_s *ary, fiobj_s *obj) {
|
487
|
-
fiobj_ary_unshift(ary, fiobj_dup(obj));
|
488
|
-
return obj;
|
489
|
-
}
|
490
|
-
|
491
|
-
/** Shifts an object from the beginning of the Array. */
|
492
|
-
fiobj_s *fiobj_ary_shift(fiobj_s *ary);
|
493
|
-
|
494
|
-
/* *****************************************************************************
|
495
|
-
Hash API
|
496
|
-
***************************************************************************** */
|
497
|
-
|
498
|
-
/**
|
499
|
-
* Creates a mutable empty Hash object. Use `fiobj_free` when done.
|
500
|
-
*
|
501
|
-
* Notice that these Hash objects are designed for smaller collections and
|
502
|
-
* retain order of object insertion.
|
503
|
-
*/
|
504
|
-
fiobj_s *fiobj_hash_new(void);
|
505
|
-
|
506
|
-
/** Returns the number of elements in the Hash. */
|
507
|
-
size_t fiobj_hash_count(fiobj_s *hash);
|
508
|
-
|
509
|
-
/**
|
510
|
-
* Sets a key-value pair in the Hash, duplicating the Symbol and **moving** the
|
511
|
-
* ownership of the object to the Hash.
|
512
|
-
*
|
513
|
-
* This implies Symbol objects should be initialized once per application run,
|
514
|
-
* when possible.
|
515
|
-
*
|
516
|
-
* Returns -1 on error.
|
517
|
-
*/
|
518
|
-
int fiobj_hash_set(fiobj_s *hash, fiobj_s *sym, fiobj_s *obj);
|
519
|
-
|
520
|
-
/**
|
521
|
-
* Removes a key-value pair from the Hash, if it exists, returning the old
|
522
|
-
* object (instead of freeing it).
|
523
|
-
*/
|
524
|
-
fiobj_s *fiobj_hash_remove(fiobj_s *hash, fiobj_s *sym);
|
525
|
-
|
526
|
-
/**
|
527
|
-
* Deletes a key-value pair from the Hash, if it exists, freeing the associated
|
528
|
-
* object.
|
529
|
-
*
|
530
|
-
* Returns -1 on type error or if the object never existed.
|
531
|
-
*/
|
532
|
-
int fiobj_hash_delete(fiobj_s *hash, fiobj_s *sym);
|
533
|
-
|
534
|
-
/**
|
535
|
-
* Returns a temporary handle to the object associated with the Symbol, NULL if
|
536
|
-
* none.
|
537
|
-
*/
|
538
|
-
fiobj_s *fiobj_hash_get(fiobj_s *hash, fiobj_s *sym);
|
539
|
-
|
540
|
-
/**
|
541
|
-
* Returns a temporary handle to the object associated with the C string Symbol.
|
542
|
-
*
|
543
|
-
* This function takes a C string instead of a Symbol, which is slower if a
|
544
|
-
* Symbol can be cached but faster if a Symbol must be allocated.
|
545
|
-
*
|
546
|
-
* Returns NULL if no object is asociated with this C string data.
|
547
|
-
*/
|
548
|
-
fiobj_s *fiobj_hash_get2(fiobj_s *hash, const char *str, size_t len);
|
549
|
-
|
550
|
-
/**
|
551
|
-
* Returns 1 if the key (Symbol) exists in the Hash, even if value is NULL.
|
552
|
-
*/
|
553
|
-
int fiobj_hash_haskey(fiobj_s *hash, fiobj_s *sym);
|
554
|
-
|
555
|
-
/* *****************
|
556
|
-
Hash API - Couplets
|
557
|
-
****************** */
|
558
|
-
|
559
|
-
/**
|
560
|
-
* If object is a Hash couplet (occurs in `fiobj_each2`), returns the key
|
561
|
-
* (Symbol) from the key-value pair.
|
562
|
-
*
|
563
|
-
* Otherwise returns NULL.
|
564
|
-
*/
|
565
|
-
fiobj_s *fiobj_couplet2key(fiobj_s *obj);
|
566
|
-
|
567
|
-
/**
|
568
|
-
* If object is a Hash couplet (occurs in `fiobj_each2`), returns the object
|
569
|
-
* (the value) from the key-value pair.
|
570
|
-
*
|
571
|
-
* Otherwise returns NULL.
|
572
|
-
*/
|
573
|
-
fiobj_s *fiobj_couplet2obj(fiobj_s *obj);
|
574
|
-
|
575
|
-
/* *****************************************************************************
|
576
|
-
Helpers: not fiobj_s specific, but since they're used internally, they're here.
|
577
|
-
***************************************************************************** */
|
578
|
-
|
579
|
-
/**
|
580
|
-
* A helper function that converts between String data to a signed int64_t.
|
581
|
-
*
|
582
|
-
* Numbers are assumed to be in base 10.
|
583
|
-
*
|
584
|
-
* The `0x##` (or `x##`) and `0b##` (or `b##`) are recognized as base 16 and
|
585
|
-
* base 2 (binary MSB first) respectively.
|
586
|
-
*
|
587
|
-
* The pointer will be updated to point to the first byte after the number.
|
588
|
-
*/
|
589
|
-
int64_t fio_atol(char **pstr);
|
590
|
-
|
591
|
-
/** A helper function that convers between String data to a signed double. */
|
592
|
-
double fio_atof(char **pstr);
|
593
|
-
|
594
|
-
/**
|
595
|
-
* A helper function that convers between a signed int64_t to a string.
|
596
|
-
*
|
597
|
-
* No overflow guard is provided, make sure there's at least 66 bytes available
|
598
|
-
* (for base 2).
|
599
|
-
*
|
600
|
-
* Supports base 2, base 10 and base 16. An unsupported base will silently
|
601
|
-
* default to base 10. Prefixes aren't added (i.e., no "0x" or "0b" at the
|
602
|
-
* beginning of the string).
|
603
|
-
*
|
604
|
-
* Returns the number of bytes actually written (excluding the NUL terminator).
|
605
|
-
*/
|
606
|
-
size_t fio_ltoa(char *dest, int64_t num, uint8_t base);
|
607
|
-
|
608
|
-
/**
|
609
|
-
* A helper function that convers between a double to a string.
|
610
|
-
*
|
611
|
-
* No overflow guard is provided, make sure there's at least 130 bytes available
|
612
|
-
* (for base 2).
|
613
|
-
*
|
614
|
-
* Supports base 2, base 10 and base 16. An unsupported base will silently
|
615
|
-
* default to base 10. Prefixes aren't added (i.e., no "0x" or "0b" at the
|
616
|
-
* beginning of the string).
|
617
|
-
*
|
618
|
-
* Returns the number of bytes actually written (excluding the NUL terminator).
|
619
|
-
*/
|
620
|
-
size_t fio_ftoa(char *dest, double num, uint8_t base);
|
621
|
-
|
622
|
-
#ifdef DEBUG
|
623
|
-
void fiobj_test(void);
|
624
|
-
int fiobj_test_json_str(char const *json, size_t len, uint8_t print_result);
|
625
|
-
#endif
|
626
|
-
|
627
|
-
#ifdef __cplusplus
|
628
|
-
} /* closing brace for extern "C" */
|
629
|
-
#endif
|
630
|
-
|
631
|
-
#endif /* H_FACIL_IO_OBJECTS_H */
|