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.

Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -33
  3. data/README.md +7 -5
  4. data/ext/iodine/base64.c +12 -0
  5. data/ext/iodine/defer.c +211 -108
  6. data/ext/iodine/defer.h +7 -0
  7. data/ext/iodine/facil.c +5 -1
  8. data/ext/iodine/facil.h +1 -1
  9. data/ext/iodine/fio2resp.c +19 -30
  10. data/ext/iodine/fio2resp.h +2 -1
  11. data/ext/iodine/fio_cli_helper.c +2 -2
  12. data/ext/iodine/fiobj.h +11 -624
  13. data/ext/iodine/fiobj_ary.c +65 -26
  14. data/ext/iodine/fiobj_ary.h +106 -0
  15. data/ext/iodine/fiobj_hash.c +175 -115
  16. data/ext/iodine/fiobj_hash.h +128 -0
  17. data/ext/iodine/fiobj_internal.c +189 -0
  18. data/ext/iodine/{fiobj_types.h → fiobj_internal.h} +126 -136
  19. data/ext/iodine/fiobj_json.c +161 -207
  20. data/ext/iodine/fiobj_json.h +43 -0
  21. data/ext/iodine/fiobj_numbers.c +53 -35
  22. data/ext/iodine/fiobj_numbers.h +49 -0
  23. data/ext/iodine/fiobj_primitives.c +103 -70
  24. data/ext/iodine/fiobj_primitives.h +55 -0
  25. data/ext/iodine/fiobj_str.c +171 -59
  26. data/ext/iodine/fiobj_str.h +113 -0
  27. data/ext/iodine/fiobj_sym.c +46 -124
  28. data/ext/iodine/fiobj_sym.h +60 -0
  29. data/ext/iodine/fiobject.c +589 -0
  30. data/ext/iodine/fiobject.h +276 -0
  31. data/ext/iodine/pubsub.h +1 -1
  32. data/ext/iodine/resp.c +2 -2
  33. data/ext/iodine/siphash.c +11 -0
  34. data/ext/iodine/spnlock.inc +7 -5
  35. data/ext/iodine/websocket_parser.h +44 -7
  36. data/lib/iodine/version.rb +1 -1
  37. metadata +13 -8
  38. data/ext/iodine/fiobj_alloc.c +0 -81
  39. data/ext/iodine/fiobj_generic.c +0 -260
  40. data/ext/iodine/fiobj_io.c +0 -58
  41. data/ext/iodine/fiobj_misc.c +0 -213
  42. data/ext/iodine/fiobj_tests.c +0 -474
@@ -0,0 +1,55 @@
1
+ #ifndef FIOBJ_PRIMITIVES_H
2
+ /*
3
+ Copyright: Boaz Segev, 2017
4
+ License: MIT
5
+ */
6
+
7
+ /**
8
+ Herein are defined some primitive types for the facil.io dynamic object system.
9
+ */
10
+ #define FIOBJ_PRIMITIVES_H
11
+
12
+ #include "fiobject.h"
13
+
14
+ #ifdef __cplusplus
15
+ extern "C" {
16
+ #endif
17
+
18
+ /* *****************************************************************************
19
+ NULL
20
+ ***************************************************************************** */
21
+
22
+ /** Identifies the NULL type. */
23
+ extern const uintptr_t FIOBJ_T_NULL;
24
+
25
+ /** Returns a NULL object. */
26
+ fiobj_s *fiobj_null(void);
27
+
28
+ /** Tests if a `fiobj_s *` is NULL. */
29
+ #define FIOBJ_IS_NULL(o) ((o) == NULL) || ((fiobj_s *)(o)->type == FIOBJ_T_NULL)
30
+
31
+ /* *****************************************************************************
32
+ True
33
+ ***************************************************************************** */
34
+
35
+ /** Identifies the TRUE type. */
36
+ extern const uintptr_t FIOBJ_T_TRUE;
37
+
38
+ /** Returns a TRUE object. */
39
+ fiobj_s *fiobj_true(void);
40
+
41
+ /* *****************************************************************************
42
+ False
43
+ ***************************************************************************** */
44
+
45
+ /** Identifies the FALSE type. */
46
+ extern const uintptr_t FIOBJ_T_FALSE;
47
+
48
+ /** Returns a FALSE object. */
49
+ fiobj_s *fiobj_false(void);
50
+
51
+ #ifdef __cplusplus
52
+ } /* extern "C" */
53
+ #endif
54
+
55
+ #endif
@@ -1,11 +1,40 @@
1
1
  /*
2
- Copyright: Boaz segev, 2017
2
+ Copyright: Boaz Segev, 2017
3
3
  License: MIT
4
-
5
- Feel free to copy, use and enjoy according to the license provided.
6
4
  */
7
5
 
8
- #include "fiobj_types.h"
6
+ #if defined(__unix__) || defined(__APPLE__) || defined(__linux__)
7
+ #ifndef _GNU_SOURCE
8
+ #define _GNU_SOURCE
9
+ #endif
10
+ #include <unistd.h>
11
+ #endif
12
+
13
+ #include "fiobj_internal.h"
14
+ #include "fiobj_str.h"
15
+
16
+ #include <errno.h>
17
+ #include <fcntl.h>
18
+ #include <limits.h>
19
+ #include <sys/stat.h>
20
+
21
+ #ifndef PATH_MAX
22
+ #define PATH_MAX 2096
23
+ #endif
24
+
25
+ /* *****************************************************************************
26
+ String Type
27
+ ***************************************************************************** */
28
+
29
+ typedef struct {
30
+ struct fiobj_vtable_s *vtable;
31
+ uint64_t capa;
32
+ uint64_t len;
33
+ uint8_t is_static;
34
+ char *str;
35
+ } fiobj_str_s;
36
+
37
+ #define obj2str(o) ((fiobj_str_s *)(o))
9
38
 
10
39
  /* *****************************************************************************
11
40
  String VTable
@@ -13,70 +42,80 @@ String VTable
13
42
 
14
43
  static void fiobj_str_dealloc(fiobj_s *o) {
15
44
  free(obj2str(o)->str);
16
- free(&OBJ2HEAD(o));
45
+ fiobj_dealloc(o);
17
46
  }
18
47
 
19
- static void fiobj_str_dealloc_static(fiobj_s *o) { free(&OBJ2HEAD(o)); }
20
-
21
- static int fiobj_str_is_eq(fiobj_s *self, fiobj_s *other) {
22
- if (!other || other->type != self->type ||
48
+ static int fiobj_str_is_eq(const fiobj_s *self, const fiobj_s *other) {
49
+ if (!other || (FIOBJ_IS_STRING(other)) ||
23
50
  obj2str(self)->len != obj2str(other)->len)
24
51
  return 0;
25
52
  return self == other || obj2str(self)->str == obj2str(other)->str ||
26
53
  !memcmp(obj2str(self)->str, obj2str(other)->str, obj2str(self)->len);
27
54
  }
28
55
 
29
- static fio_cstr_s fio_str2str(fiobj_s *o) {
56
+ static fio_cstr_s fio_str2str(const fiobj_s *o) {
30
57
  return (fio_cstr_s){.buffer = obj2str(o)->str, .len = obj2str(o)->len};
31
58
  }
32
- static int64_t fio_str2i(fiobj_s *o) {
59
+ static int64_t fio_str2i(const fiobj_s *o) {
33
60
  char *s = obj2str(o)->str;
34
61
  return fio_atol(&s);
35
62
  }
36
- static double fio_str2f(fiobj_s *o) {
63
+ static double fio_str2f(const fiobj_s *o) {
37
64
  char *s = obj2str(o)->str;
38
65
  return fio_atof(&s);
39
66
  }
40
67
 
68
+ static int fio_str2bool(const fiobj_s *o) { return obj2str(o)->len != 0; }
69
+
41
70
  static struct fiobj_vtable_s FIOBJ_VTABLE_STRING = {
71
+ .name = "String",
42
72
  .free = fiobj_str_dealloc,
43
73
  .to_i = fio_str2i,
44
74
  .to_f = fio_str2f,
45
75
  .to_str = fio_str2str,
46
76
  .is_eq = fiobj_str_is_eq,
77
+ .is_true = fio_str2bool,
47
78
  .count = fiobj_noop_count,
79
+ .unwrap = fiobj_noop_unwrap,
48
80
  .each1 = fiobj_noop_each1,
49
81
  };
50
82
 
83
+ const uintptr_t FIOBJ_T_STRING = (uintptr_t)(&FIOBJ_VTABLE_STRING);
84
+
51
85
  static struct fiobj_vtable_s FIOBJ_VTABLE_STATIC_STRING = {
52
- .free = fiobj_str_dealloc_static,
86
+ .name = "StaticString",
87
+ .free = fiobj_simple_dealloc,
53
88
  .to_i = fio_str2i,
54
89
  .to_f = fio_str2f,
55
90
  .to_str = fio_str2str,
56
91
  .is_eq = fiobj_str_is_eq,
92
+ .is_true = fio_str2bool,
57
93
  .count = fiobj_noop_count,
94
+ .unwrap = fiobj_noop_unwrap,
58
95
  .each1 = fiobj_noop_each1,
59
96
  };
60
97
 
98
+ const uintptr_t FIOBJ_T_STRING_STATIC =
99
+ (uintptr_t)(&FIOBJ_VTABLE_STATIC_STRING);
100
+
61
101
  /* *****************************************************************************
62
102
  String API
63
103
  ***************************************************************************** */
64
104
 
65
105
  static inline fiobj_s *fiobj_str_alloc(size_t len) {
66
- fiobj_head_s *head;
67
- head = malloc(sizeof(*head) + sizeof(fio_str_s));
68
- if (!head)
106
+ fiobj_s *o = fiobj_alloc(sizeof(fiobj_str_s) + len + 1);
107
+ if (!o)
69
108
  perror("ERROR: fiobj string couldn't allocate memory"), exit(errno);
70
- *head = (fiobj_head_s){
71
- .ref = 1, .vtable = &FIOBJ_VTABLE_STRING,
72
- };
73
- *obj2str(HEAD2OBJ(head)) = (fio_str_s){
74
- .type = FIOBJ_T_STRING, .len = len, .capa = len, .str = malloc(len + 1),
109
+ *obj2str(o) = (fiobj_str_s){
110
+ .vtable = &FIOBJ_VTABLE_STRING,
111
+ .len = len,
112
+ .capa = len + 1,
113
+ .str = malloc(len + 1),
75
114
  };
76
- if (!obj2str(HEAD2OBJ(head))->str)
115
+ if (!obj2str(o)->str)
77
116
  perror("ERROR: fiobj string couldn't allocate memory"), exit(errno);
78
- obj2str(HEAD2OBJ(head))->str[len] = 0;
79
- return HEAD2OBJ(head);
117
+ obj2str(o)->str[len] = 0;
118
+ return o;
80
119
  }
81
120
 
82
121
  /** Creates a String object. Remember to use `fiobj_free`. */
@@ -98,6 +137,25 @@ fiobj_s *fiobj_str_buf(size_t capa) {
98
137
  return s;
99
138
  }
100
139
 
140
+ /**
141
+ * Creates a String object. Remember to use `fiobj_free`.
142
+ *
143
+ * The ownership of the memory indicated by `str` will now "move" to the object,
144
+ * so `free` will be called for `str` by the `fiobj` library as needed.
145
+ */
146
+ fiobj_s *fiobj_str_move(char *str, size_t len, size_t capacity) {
147
+ fiobj_s *o = fiobj_alloc(sizeof(fiobj_str_s) + len + 1);
148
+ if (!o)
149
+ perror("ERROR: fiobj string couldn't allocate memory"), exit(errno);
150
+ *obj2str(o) = (fiobj_str_s){
151
+ .vtable = &FIOBJ_VTABLE_STRING,
152
+ .len = len,
153
+ .capa = (capacity < len ? len : capacity),
154
+ .str = (char *)str,
155
+ };
156
+ return o;
157
+ }
158
+
101
159
  /**
102
160
  * Creates a static String object from a static C string. Remember `fiobj_free`.
103
161
  *
@@ -109,21 +167,18 @@ fiobj_s *fiobj_str_buf(size_t capa) {
109
167
  * NOTICE: static strings can't be written to.
110
168
  */
111
169
  fiobj_s *fiobj_str_static(const char *str, size_t len) {
112
- fiobj_head_s *head;
113
- head = malloc(sizeof(*head) + sizeof(fio_str_s));
114
- if (!head)
170
+ fiobj_s *o = fiobj_alloc(sizeof(fiobj_str_s) + len + 1);
171
+ if (!o)
115
172
  perror("ERROR: fiobj string couldn't allocate memory"), exit(errno);
116
- *head = (fiobj_head_s){
117
- .ref = 1, .vtable = &FIOBJ_VTABLE_STATIC_STRING,
118
- };
119
- *obj2str(HEAD2OBJ(head)) = (fio_str_s){
120
- .type = FIOBJ_T_STRING,
173
+ *obj2str(o) = (fiobj_str_s){
174
+ .vtable = &FIOBJ_VTABLE_STATIC_STRING,
121
175
  .len = (len ? len : strlen(str)),
122
176
  .capa = 0,
123
177
  .str = (char *)str,
124
- .is_static = 1,
125
178
  };
126
- return HEAD2OBJ(head);
179
+ if (!obj2str(o)->str)
180
+ perror("ERROR: fiobj string couldn't allocate memory"), exit(errno);
181
+ return o;
127
182
  }
128
183
 
129
184
  /** Creates a copy from an existing String. Remember to use `fiobj_free`. */
@@ -145,7 +200,7 @@ fiobj_strvprintf(const char *format, va_list argv) {
145
200
  if (len <= 0)
146
201
  return str;
147
202
  str = fiobj_str_new(NULL, len);
148
- vsnprintf(((fio_str_s *)(str))->str, len + 1, format, argv);
203
+ vsnprintf(obj2str(str)->str, len + 1, format, argv);
149
204
  return str;
150
205
  }
151
206
  __attribute__((format(printf, 1, 2))) fiobj_s *
@@ -157,23 +212,82 @@ fiobj_strprintf(const char *format, ...) {
157
212
  return str;
158
213
  }
159
214
 
215
+ /** Dumps the `filename` file's contents into a new String. If `limit == 0`,
216
+ * than the data will be read until EOF.
217
+ *
218
+ * If the file can't be located, opened or read, or if `start_at` is beyond the
219
+ * EOF position, NULL is returned.
220
+ *
221
+ * Remember to use `fiobj_free`.
222
+ */
223
+ fiobj_s *fiobj_str_readfile(const char *filename, size_t start_at,
224
+ size_t limit) {
225
+ #if defined(__unix__) || defined(__linux__) || defined(__APPLE__)
226
+ /* POSIX implementations. */
227
+ if (filename == NULL)
228
+ return NULL;
229
+ struct stat f_data;
230
+ int file = -1;
231
+ size_t file_path_len = strlen(filename);
232
+ if (file_path_len == 0 || file_path_len > PATH_MAX)
233
+ return NULL;
234
+
235
+ char real_public_path[PATH_MAX + 1];
236
+ real_public_path[PATH_MAX] = 0;
237
+
238
+ if (filename[0] == '~' && getenv("HOME") && file_path_len <= PATH_MAX) {
239
+ strcpy(real_public_path, getenv("HOME"));
240
+ memcpy(real_public_path + strlen(real_public_path), filename + 1,
241
+ file_path_len);
242
+ filename = real_public_path;
243
+ }
244
+
245
+ if (stat(filename, &f_data) || f_data.st_size < 0)
246
+ return NULL;
247
+
248
+ if (limit <= 0 || (size_t)f_data.st_size < limit + start_at)
249
+ limit = f_data.st_size - start_at;
250
+ fiobj_s *str = fiobj_str_buf(limit + 1);
251
+ if (!str)
252
+ return NULL;
253
+ file = open(filename, O_RDONLY);
254
+ if (file < 0) {
255
+ fiobj_str_dealloc(str);
256
+ return NULL;
257
+ }
258
+
259
+ if (pread(file, obj2str(str)->str, limit, start_at) != (ssize_t)limit) {
260
+ fiobj_str_dealloc(str);
261
+ close(file);
262
+ return NULL;
263
+ }
264
+ close(file);
265
+ obj2str(str)->len = limit;
266
+ obj2str(str)->str[limit] = 0;
267
+ return str;
268
+ #else
269
+ /* TODO: consider adding non POSIX implementations. */
270
+ return NULL;
271
+ #endif
272
+ }
273
+
160
274
  /** Confirms the requested capacity is available and allocates as required. */
161
- void fiobj_str_capa_assert(fiobj_s *str, size_t size) {
162
- if (str->type != FIOBJ_T_STRING || ((fio_str_s *)str)->capa == 0 ||
163
- ((fio_str_s *)str)->capa >= size + 1)
164
- return;
275
+ size_t fiobj_str_capa_assert(fiobj_s *str, size_t size) {
276
+ if (str->type != FIOBJ_T_STRING || obj2str(str)->capa == 0 ||
277
+ obj2str(str)->capa >= size + 1)
278
+ return obj2str(str)->capa;
165
279
  /* it's better to crash than live without memory... */
166
- ((fio_str_s *)str)->str = realloc(((fio_str_s *)str)->str, size + 1);
167
- ((fio_str_s *)str)->capa = size + 1;
168
- ((fio_str_s *)str)->str[size] = 0;
169
- return;
280
+ obj2str(str)->str = realloc(obj2str(str)->str, size + 1);
281
+ obj2str(str)->capa = size + 1;
282
+ obj2str(str)->str[size] = 0;
283
+ return obj2str(str)->capa;
170
284
  }
171
285
 
172
286
  /** Return's a String's capacity, if any. */
173
287
  size_t fiobj_str_capa(fiobj_s *str) {
174
288
  if (str->type != FIOBJ_T_STRING)
175
289
  return 0;
176
- return ((fio_str_s *)str)->capa;
290
+ return obj2str(str)->capa;
177
291
  }
178
292
 
179
293
  /** Resizes a String object, allocating more memory if required. */
@@ -181,8 +295,8 @@ void fiobj_str_resize(fiobj_s *str, size_t size) {
181
295
  if (str->type != FIOBJ_T_STRING)
182
296
  return;
183
297
  fiobj_str_capa_assert(str, size);
184
- ((fio_str_s *)str)->len = size;
185
- ((fio_str_s *)str)->str[size] = 0;
298
+ obj2str(str)->len = size;
299
+ obj2str(str)->str[size] = 0;
186
300
  return;
187
301
  }
188
302
 
@@ -190,9 +304,8 @@ void fiobj_str_resize(fiobj_s *str, size_t size) {
190
304
  void fiobj_str_minimize(fiobj_s *str) {
191
305
  if (str->type != FIOBJ_T_STRING)
192
306
  return;
193
- ((fio_str_s *)str)->capa = ((fio_str_s *)str)->len + 1;
194
- ((fio_str_s *)str)->str =
195
- realloc(((fio_str_s *)str)->str, ((fio_str_s *)str)->capa);
307
+ obj2str(str)->capa = obj2str(str)->len + 1;
308
+ obj2str(str)->str = realloc(obj2str(str)->str, obj2str(str)->capa);
196
309
  return;
197
310
  }
198
311
 
@@ -200,8 +313,8 @@ void fiobj_str_minimize(fiobj_s *str) {
200
313
  void fiobj_str_clear(fiobj_s *str) {
201
314
  if (str->type != FIOBJ_T_STRING)
202
315
  return;
203
- ((fio_str_s *)str)->str[0] = 0;
204
- ((fio_str_s *)str)->len = 0;
316
+ obj2str(str)->str[0] = 0;
317
+ obj2str(str)->len = 0;
205
318
  }
206
319
 
207
320
  /**
@@ -220,11 +333,10 @@ size_t fiobj_str_write(fiobj_s *dest, const char *data, size_t len) {
220
333
  obj2str(dest)->str[pos] = data[len];
221
334
  }
222
335
  } else {
223
- memcpy(((fio_str_s *)dest)->str + ((fio_str_s *)dest)->len - len, data,
224
- len);
336
+ memcpy(obj2str(dest)->str + obj2str(dest)->len - len, data, len);
225
337
  }
226
338
  // ((fio_str_s *)dest)->str[((fio_str_s *)dest)->len] = 0; // see str_resize
227
- return ((fio_str_s *)dest)->len;
339
+ return obj2str(dest)->len;
228
340
  }
229
341
  /**
230
342
  * Writes data at the end of the string, resizing the string as required.
@@ -238,14 +350,14 @@ size_t fiobj_str_write2(fiobj_s *dest, const char *format, ...) {
238
350
  int len = vsnprintf(NULL, 0, format, argv);
239
351
  va_end(argv);
240
352
  if (len <= 0)
241
- return ((fio_str_s *)dest)->len;
242
- fiobj_str_resize(dest, ((fio_str_s *)dest)->len + len);
353
+ return obj2str(dest)->len;
354
+ fiobj_str_resize(dest, obj2str(dest)->len + len);
243
355
  va_start(argv, format);
244
- vsnprintf(((fio_str_s *)(dest))->str + ((fio_str_s *)dest)->len - len,
245
- len + 1, format, argv);
356
+ vsnprintf(obj2str(dest)->str + obj2str(dest)->len - len, len + 1, format,
357
+ argv);
246
358
  va_end(argv);
247
359
  // ((fio_str_s *)dest)->str[((fio_str_s *)dest)->len] = 0; // see str_resize
248
- return ((fio_str_s *)dest)->len;
360
+ return obj2str(dest)->len;
249
361
  }
250
362
  /**
251
363
  * Writes data at the end of the string, resizing the string as required.
@@ -0,0 +1,113 @@
1
+ #ifndef H_FIOBJ_STR_H
2
+ /*
3
+ Copyright: Boaz Segev, 2017
4
+ License: MIT
5
+ */
6
+ #define H_FIOBJ_STR_H
7
+
8
+ #include "fiobject.h"
9
+
10
+ #ifdef __cplusplus
11
+ extern "C" {
12
+ #endif
13
+
14
+ /** String type identifier */
15
+ extern const uintptr_t FIOBJ_T_STRING;
16
+
17
+ /** Static String type identifier */
18
+ extern const uintptr_t FIOBJ_T_STRING_STATIC;
19
+
20
+ #define FIOBJ_IS_STRING(obj) \
21
+ (obj->type == FIOBJ_T_STRING || obj->type == FIOBJ_T_STRING_STATIC)
22
+
23
+ /* *****************************************************************************
24
+ String API
25
+ ***************************************************************************** */
26
+
27
+ /** Creates a String object. Remember to use `fiobj_free`. */
28
+ fiobj_s *fiobj_str_new(const char *str, size_t len);
29
+
30
+ /** Creates a buffer String object. capa includes NUL.
31
+ *
32
+ * Remember to use `fiobj_free`.
33
+ */
34
+ fiobj_s *fiobj_str_buf(size_t capa);
35
+
36
+ /**
37
+ * Creates a static String object from a static C string. Remember `fiobj_free`.
38
+ *
39
+ * This variation avoids allocating memory for an existing static String.
40
+ *
41
+ * The object still needs to be frees, but the string isn't copied and isn't
42
+ * freed.
43
+ *
44
+ * NOTICE: static strings can't be written to.
45
+ */
46
+ fiobj_s *fiobj_str_static(const char *str, size_t len);
47
+
48
+ /** Creates a copy from an existing String. Remember to use `fiobj_free`. */
49
+ fiobj_s *fiobj_str_copy(fiobj_s *src);
50
+
51
+ /** Creates a String object using a printf like interface. */
52
+ __attribute__((format(printf, 1, 0))) fiobj_s *
53
+ fiobj_strvprintf(const char *format, va_list argv);
54
+
55
+ /** Creates a String object using a printf like interface. */
56
+ __attribute__((format(printf, 1, 2))) fiobj_s *
57
+ fiobj_strprintf(const char *format, ...);
58
+
59
+ /** Dumps the `filename` file's contents into a new String. If `limit == 0`,
60
+ * than the data will be read until EOF.
61
+ *
62
+ * If the file can't be located, opened or read, or if `start_at` is beyond the
63
+ * EOF position, NULL is returned.
64
+ *
65
+ * Remember to use `fiobj_free`.
66
+ *
67
+ * NOTE: Requires a UNIX system, otherwise always returns NULL.
68
+ */
69
+ fiobj_s *fiobj_str_readfile(const char *filename, size_t start_at,
70
+ size_t limit);
71
+ /**
72
+ * Confirms the requested capacity is available and allocates as required.
73
+ *
74
+ * Returns updated capacity.
75
+ */
76
+ size_t fiobj_str_capa_assert(fiobj_s *str, size_t size);
77
+
78
+ /** Return's a String's capacity, if any. This should include the NUL byte. */
79
+ size_t fiobj_str_capa(fiobj_s *str);
80
+
81
+ /** Resizes a String object, allocating more memory if required. */
82
+ void fiobj_str_resize(fiobj_s *str, size_t size);
83
+
84
+ /** Deallocates any unnecessary memory (if supported by OS). */
85
+ void fiobj_str_minimize(fiobj_s *str);
86
+
87
+ /** Empties a String's data. */
88
+ void fiobj_str_clear(fiobj_s *str);
89
+
90
+ /**
91
+ * Writes data at the end of the string, resizing the string as required.
92
+ * Returns the new length of the String
93
+ */
94
+ size_t fiobj_str_write(fiobj_s *dest, const char *data, size_t len);
95
+
96
+ /**
97
+ * Writes data at the end of the string, resizing the string as required.
98
+ * Returns the new length of the String
99
+ */
100
+ __attribute__((format(printf, 2, 3))) size_t
101
+ fiobj_str_write2(fiobj_s *dest, const char *format, ...);
102
+
103
+ /**
104
+ * Writes data at the end of the string, resizing the string as required.
105
+ * Returns the new length of the String
106
+ */
107
+ size_t fiobj_str_join(fiobj_s *dest, fiobj_s *obj);
108
+
109
+ #ifdef __cplusplus
110
+ } /* extern "C" */
111
+ #endif
112
+
113
+ #endif