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,43 @@
1
+ #ifndef H_FIOBJ_JSON_H
2
+ #define H_FIOBJ_JSON_H
3
+
4
+ /*
5
+ Copyright: Boaz Segev, 2017
6
+ License: MIT
7
+ */
8
+
9
+ #include "fiobj_ary.h"
10
+ #include "fiobj_hash.h"
11
+ #include "fiobj_numbers.h"
12
+ #include "fiobj_primitives.h"
13
+ #include "fiobj_str.h"
14
+ #include "fiobj_sym.h"
15
+
16
+ #ifdef __cplusplus
17
+ extern "C" {
18
+ #endif
19
+
20
+ /* *****************************************************************************
21
+ JSON API
22
+ ***************************************************************************** */
23
+
24
+ /** Limit JSON nesting, we can handle more, but this is mostly for security. */
25
+ #ifndef JSON_MAX_DEPTH
26
+ #define JSON_MAX_DEPTH 24
27
+ #endif
28
+
29
+ /**
30
+ * Parses JSON, setting `pobj` to point to the new Object.
31
+ *
32
+ * Returns the number of bytes consumed. On Error, 0 is returned and no data is
33
+ * consumed.
34
+ */
35
+ size_t fiobj_json2obj(fiobj_s **pobj, const void *data, size_t len);
36
+ /* Formats an object into a JSON string. Remember to `fiobj_free`. */
37
+ fiobj_s *fiobj_obj2json(fiobj_s *, uint8_t pretty);
38
+
39
+ #ifdef __cplusplus
40
+ } /* extern "C" */
41
+ #endif
42
+
43
+ #endif
@@ -1,11 +1,26 @@
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
+ #include "fiobj_internal.h"
7
+
8
+ /* *****************************************************************************
9
+ Numbers Type
10
+ ***************************************************************************** */
11
+
12
+ typedef struct {
13
+ struct fiobj_vtable_s *vtable;
14
+ uint64_t i;
15
+ } fiobj_num_s;
16
+
17
+ typedef struct {
18
+ struct fiobj_vtable_s *vtable;
19
+ double f;
20
+ } fiobj_float_s;
21
+
22
+ #define obj2num(o) ((fiobj_num_s *)(o))
23
+ #define obj2float(o) ((fiobj_float_s *)(o))
9
24
 
10
25
  /* *****************************************************************************
11
26
  Numbers VTable
@@ -13,19 +28,22 @@ Numbers VTable
13
28
 
14
29
  static __thread char num_buffer[512];
15
30
 
16
- static int64_t fio_i2i(fiobj_s *o) { return obj2num(o)->i; }
17
- static int64_t fio_f2i(fiobj_s *o) {
18
- return (int64_t)floorl(((fio_float_s *)o)->f);
31
+ static int64_t fio_i2i(const fiobj_s *o) { return obj2num(o)->i; }
32
+ static int64_t fio_f2i(const fiobj_s *o) {
33
+ return (int64_t)floorl(obj2float(o)->f);
19
34
  }
20
- static double fio_i2f(fiobj_s *o) { return (double)obj2num(o)->i; }
21
- static double fio_f2f(fiobj_s *o) { return obj2float(o)->f; }
35
+ static double fio_i2f(const fiobj_s *o) { return (double)obj2num(o)->i; }
36
+ static double fio_f2f(const fiobj_s *o) { return obj2float(o)->f; }
37
+
38
+ static int fio_itrue(const fiobj_s *o) { return (obj2num(o)->i != 0); }
39
+ static int fio_ftrue(const fiobj_s *o) { return (obj2float(o)->f != 0); }
22
40
 
23
- static fio_cstr_s fio_i2str(fiobj_s *o) {
41
+ static fio_cstr_s fio_i2str(const fiobj_s *o) {
24
42
  return (fio_cstr_s){
25
43
  .buffer = num_buffer, .len = fio_ltoa(num_buffer, obj2num(o)->i, 10),
26
44
  };
27
45
  }
28
- static fio_cstr_s fio_f2str(fiobj_s *o) {
46
+ static fio_cstr_s fio_f2str(const fiobj_s *o) {
29
47
  if (isnan(obj2float(o)->f))
30
48
  return (fio_cstr_s){.buffer = "NaN", .len = 3};
31
49
  else if (isinf(obj2float(o)->f)) {
@@ -39,54 +57,56 @@ static fio_cstr_s fio_f2str(fiobj_s *o) {
39
57
  };
40
58
  }
41
59
 
42
- static int fiobj_i_is_eq(fiobj_s *self, fiobj_s *other) {
43
- if (!other || other->type != self->type ||
44
- obj2num(self)->i != obj2num(other)->i)
45
- return 0;
46
- return 1;
60
+ static int fiobj_i_is_eq(const fiobj_s *self, const fiobj_s *other) {
61
+ return self->type == other->type && obj2num(self)->i == obj2num(other)->i;
47
62
  }
48
- static int fiobj_f_is_eq(fiobj_s *self, fiobj_s *other) {
49
- if (!other || other->type != self->type ||
50
- obj2float(self)->f != obj2float(other)->f)
51
- return 0;
52
- return 1;
63
+ static int fiobj_f_is_eq(const fiobj_s *self, const fiobj_s *other) {
64
+ return self->type == other->type && obj2float(self)->f == obj2float(other)->f;
53
65
  }
54
66
 
55
67
  static struct fiobj_vtable_s FIOBJ_VTABLE_INT = {
68
+ .name = "Number",
56
69
  .free = fiobj_simple_dealloc,
57
70
  .to_i = fio_i2i,
58
71
  .to_f = fio_i2f,
59
72
  .to_str = fio_i2str,
73
+ .is_true = fio_itrue,
60
74
  .is_eq = fiobj_i_is_eq,
61
75
  .count = fiobj_noop_count,
76
+ .unwrap = fiobj_noop_unwrap,
62
77
  .each1 = fiobj_noop_each1,
63
78
  };
64
79
 
80
+ const uintptr_t FIOBJ_T_NUMBER = (uintptr_t)&FIOBJ_VTABLE_INT;
81
+
65
82
  static struct fiobj_vtable_s FIOBJ_VTABLE_FLOAT = {
83
+ .name = "Float",
66
84
  .free = fiobj_simple_dealloc,
67
85
  .to_i = fio_f2i,
68
86
  .to_f = fio_f2f,
87
+ .is_true = fio_ftrue,
69
88
  .to_str = fio_f2str,
70
89
  .is_eq = fiobj_f_is_eq,
71
90
  .count = fiobj_noop_count,
91
+ .unwrap = fiobj_noop_unwrap,
72
92
  .each1 = fiobj_noop_each1,
73
93
  };
74
94
 
95
+ const uintptr_t FIOBJ_T_FLOAT = (uintptr_t)&FIOBJ_VTABLE_FLOAT;
96
+
75
97
  /* *****************************************************************************
76
98
  Number API
77
99
  ***************************************************************************** */
78
100
 
79
101
  /** Creates a Number object. Remember to use `fiobj_free`. */
80
102
  fiobj_s *fiobj_num_new(int64_t num) {
81
- fiobj_head_s *head;
82
- head = malloc(sizeof(*head) + sizeof(fio_num_s));
83
- if (!head)
103
+ fiobj_num_s *o = (fiobj_num_s *)fiobj_alloc(sizeof(*o));
104
+ if (!o)
84
105
  perror("ERROR: fiobj number couldn't allocate memory"), exit(errno);
85
- *head = (fiobj_head_s){
86
- .ref = 1, .vtable = &FIOBJ_VTABLE_INT,
106
+ *o = (fiobj_num_s){
107
+ .vtable = &FIOBJ_VTABLE_INT, .i = num,
87
108
  };
88
- *obj2num(HEAD2OBJ(head)) = (fio_num_s){.i = num, .type = FIOBJ_T_NUMBER};
89
- return HEAD2OBJ(head);
109
+ return (fiobj_s *)o;
90
110
  }
91
111
 
92
112
  /** Mutates a Number object's value. Effects every object's reference! */
@@ -98,15 +118,13 @@ Float API
98
118
 
99
119
  /** Creates a Float object. Remember to use `fiobj_free`. */
100
120
  fiobj_s *fiobj_float_new(double num) {
101
- fiobj_head_s *head;
102
- head = malloc(sizeof(*head) + sizeof(fio_float_s));
103
- if (!head)
121
+ fiobj_float_s *o = (fiobj_float_s *)fiobj_alloc(sizeof(*o));
122
+ if (!o)
104
123
  perror("ERROR: fiobj float couldn't allocate memory"), exit(errno);
105
- *head = (fiobj_head_s){
106
- .ref = 1, .vtable = &FIOBJ_VTABLE_FLOAT,
124
+ *o = (fiobj_float_s){
125
+ .vtable = &FIOBJ_VTABLE_FLOAT, .f = num,
107
126
  };
108
- *obj2float(HEAD2OBJ(head)) = (fio_float_s){.f = num, .type = FIOBJ_T_FLOAT};
109
- return HEAD2OBJ(head);
127
+ return (fiobj_s *)o;
110
128
  }
111
129
 
112
130
  /** Mutates a Float object's value. Effects every object's reference! */
@@ -0,0 +1,49 @@
1
+ #ifndef H_FIOBJ_NUMBERS_H
2
+ #define H_FIOBJ_NUMBERS_H
3
+ /*
4
+ Copyright: Boaz Segev, 2017
5
+ License: MIT
6
+ */
7
+
8
+ #include "fiobject.h"
9
+
10
+ #ifdef __cplusplus
11
+ extern "C" {
12
+ #endif
13
+
14
+ /* *****************************************************************************
15
+ Numbers API (Integers)
16
+ ***************************************************************************** */
17
+
18
+ extern const uintptr_t FIOBJ_T_NUMBER;
19
+
20
+ /** Creates a Number object. Remember to use `fiobj_free`. */
21
+ fiobj_s *fiobj_num_new(int64_t num);
22
+
23
+ /** Mutates a Number object's value. Effects every object's reference! */
24
+ void fiobj_num_set(fiobj_s *target, int64_t num);
25
+
26
+ /* *****************************************************************************
27
+ Float API (Double)
28
+ ***************************************************************************** */
29
+
30
+ extern const uintptr_t FIOBJ_T_FLOAT;
31
+
32
+ /** Creates a Float object. Remember to use `fiobj_free`. */
33
+ fiobj_s *fiobj_float_new(double num);
34
+
35
+ /** Mutates a Float object's value. Effects every object's reference! */
36
+ void fiobj_float_set(fiobj_s *obj, double num);
37
+
38
+ /* *****************************************************************************
39
+ Pointer Wrapping Helper MACROs (uses integers)
40
+ ***************************************************************************** */
41
+
42
+ #define fiobj_ptr_wrap(ptr) fiobj_num_new((int64_t)(ptr))
43
+ #define fiobj_ptr_unwrap(obj) ((void *)fiobj_obj2num((obj)))
44
+
45
+ #ifdef __cplusplus
46
+ } /* extern "C" */
47
+ #endif
48
+
49
+ #endif
@@ -1,98 +1,131 @@
1
1
  /*
2
- Copyright: Boaz segev, 2017
2
+ Copyright: Boaz Segev, 2017
3
3
  License: MIT
4
+ */
4
5
 
5
- Feel free to copy, use and enjoy according to the license provided.
6
+ /**
7
+ Herein are defined some primitive types for the facil.io dynamic object system.
6
8
  */
7
- #include "fiobj_types.h"
9
+ #include "fiobj_primitives.h"
10
+ #include "fiobj_internal.h"
8
11
 
9
12
  /* *****************************************************************************
10
- NULL, TRUE, FALSE VTable
13
+ NULL
11
14
  ***************************************************************************** */
12
15
 
13
- static int fiobj_simple_is_eq(fiobj_s *self, fiobj_s *other) {
14
- if (!other || other->type != self->type)
15
- return 0;
16
- return 1;
16
+ static int fiobj_primitive_is_eq(const fiobj_s *self, const fiobj_s *other) {
17
+ return self == other;
17
18
  }
18
19
 
19
- static fio_cstr_s fio_true2str(fiobj_s *obj) {
20
- return (fio_cstr_s){.buffer = "true", .len = 4};
21
- (void)obj;
22
- }
23
- static fio_cstr_s fio_false2str(fiobj_s *obj) {
24
- return (fio_cstr_s){.buffer = "false", .len = 5};
25
- (void)obj;
26
- }
27
- static fio_cstr_s fio_null2str(fiobj_s *obj) {
28
- return (fio_cstr_s){.buffer = "null", .len = 4};
29
- (void)obj;
30
- }
31
- static int64_t fio_true2i(fiobj_s *obj) {
32
- return 1;
33
- (void)obj;
34
- }
35
- static double fio_true2f(fiobj_s *obj) {
36
- return 1;
37
- (void)obj;
38
- }
39
-
40
- static struct fiobj_vtable_s FIOBJ_VTABLE_NULL = {
41
- .free = fiobj_simple_dealloc,
20
+ static struct fiobj_vtable_s NULL_VTABLE = {
21
+ .name = "NULL",
22
+ /* deallocate an object */
23
+ .free = fiobj_noop_free,
24
+ /* object should evaluate as true/false? */
25
+ .is_true = fiobj_noop_false,
26
+ /* object value as String */
27
+ .to_str = fiobj_noop_str,
28
+ /* object value as Integer */
42
29
  .to_i = fiobj_noop_i,
30
+ /* object value as Float */
43
31
  .to_f = fiobj_noop_f,
44
- .to_str = fio_null2str,
45
- .is_eq = fiobj_simple_is_eq,
32
+ .is_eq = fiobj_primitive_is_eq,
33
+ /* return the number of nested object */
46
34
  .count = fiobj_noop_count,
35
+ /* return a wrapped object (if object wrapping exists, i.e. Hash couplet) */
36
+ .unwrap = fiobj_noop_unwrap,
37
+ /* perform a task for the object's children (-1 stops iteration)
38
+ * returns the number of items processed + `start_at`.
39
+ */
47
40
  .each1 = fiobj_noop_each1,
48
41
  };
49
- static struct fiobj_vtable_s FIOBJ_VTABLE_TRUE = {
50
- .free = fiobj_simple_dealloc,
51
- .to_i = fio_true2i,
52
- .to_f = fio_true2f,
53
- .to_str = fio_true2str,
54
- .is_eq = fiobj_simple_is_eq,
55
- .count = fiobj_noop_count,
56
- .each1 = fiobj_noop_each1,
57
- };
58
- static struct fiobj_vtable_s FIOBJ_VTABLE_FALSE = {
59
- .free = fiobj_simple_dealloc,
42
+
43
+ /** Identifies the NULL type. */
44
+ const uintptr_t FIOBJ_T_NULL = (uintptr_t)(&NULL_VTABLE);
45
+
46
+ /** Returns a NULL object. */
47
+ fiobj_s *fiobj_null(void) {
48
+ static struct {
49
+ fiobj_head_s head;
50
+ struct fiobj_vtable_s *vtable;
51
+ } null_obj = {.head = {.ref = 1}, .vtable = &NULL_VTABLE};
52
+ return (fiobj_s *)(&null_obj.vtable);
53
+ }
54
+
55
+ /* *****************************************************************************
56
+ True
57
+ ***************************************************************************** */
58
+
59
+ static struct fiobj_vtable_s TRUE_VTABLE = {
60
+ .name = "True",
61
+ /* deallocate an object */
62
+ .free = fiobj_noop_free,
63
+ /* object should evaluate as true/false? */
64
+ .is_true = fiobj_noop_true,
65
+ /* object value as String */
66
+ .to_str = fiobj_noop_str,
67
+ /* object value as Integer */
60
68
  .to_i = fiobj_noop_i,
69
+ /* object value as Float */
61
70
  .to_f = fiobj_noop_f,
62
- .to_str = fio_false2str,
63
- .is_eq = fiobj_simple_is_eq,
71
+ .is_eq = fiobj_primitive_is_eq,
72
+ /* return the number of nested object */
64
73
  .count = fiobj_noop_count,
74
+ /* return a wrapped object (if object wrapping exists, i.e. Hash couplet) */
75
+ .unwrap = fiobj_noop_unwrap,
76
+ /* perform a task for the object's children (-1 stops iteration)
77
+ * returns the number of items processed + `start_at`.
78
+ */
65
79
  .each1 = fiobj_noop_each1,
66
80
  };
67
81
 
82
+ /** Identifies the TRUE type. */
83
+ const uintptr_t FIOBJ_T_TRUE = (uintptr_t)(&TRUE_VTABLE);
84
+
85
+ /** Returns a TRUE object. */
86
+ fiobj_s *fiobj_true(void) {
87
+ static struct {
88
+ fiobj_head_s head;
89
+ struct fiobj_vtable_s *vtable;
90
+ } obj = {.head = {.ref = 1}, .vtable = &TRUE_VTABLE};
91
+ return (fiobj_s *)(&obj.vtable);
92
+ }
93
+
68
94
  /* *****************************************************************************
69
- NULL, TRUE, FALSE API
95
+ False
70
96
  ***************************************************************************** */
71
97
 
72
- inline static fiobj_s *fiobj_simple_alloc(fiobj_type_en t,
73
- struct fiobj_vtable_s *vt) {
74
- fiobj_head_s *head;
75
- head = malloc(sizeof(*head) + sizeof(fiobj_s));
76
- if (!head)
77
- perror("ERROR: fiobj primitive couldn't allocate memory"), exit(errno);
78
- *head = (fiobj_head_s){
79
- .ref = 1, .vtable = vt,
80
- };
81
- HEAD2OBJ(head)->type = t;
82
- return HEAD2OBJ(head);
83
- }
98
+ static struct fiobj_vtable_s FALSE_VTABLE = {
99
+ .name = "False",
100
+ /* deallocate an object */
101
+ .free = fiobj_noop_free,
102
+ /* object should evaluate as true/false? */
103
+ .is_true = fiobj_noop_false,
104
+ /* object value as String */
105
+ .to_str = fiobj_noop_str,
106
+ /* object value as Integer */
107
+ .to_i = fiobj_noop_i,
108
+ /* object value as Float */
109
+ .to_f = fiobj_noop_f,
110
+ .is_eq = fiobj_primitive_is_eq,
111
+ /* return the number of nested object */
112
+ .count = fiobj_noop_count,
113
+ /* return a wrapped object (if object wrapping exists, i.e. Hash couplet) */
114
+ .unwrap = fiobj_noop_unwrap,
115
+ /* perform a task for the object's children (-1 stops iteration)
116
+ * returns the number of items processed + `start_at`.
117
+ */
118
+ .each1 = fiobj_noop_each1,
119
+ };
84
120
 
85
- /** Retruns a NULL object. */
86
- fiobj_s *fiobj_null(void) {
87
- return fiobj_simple_alloc(FIOBJ_T_NULL, &FIOBJ_VTABLE_NULL);
88
- }
121
+ /** Identifies the FALSE type. */
122
+ const uintptr_t FIOBJ_T_FALSE = (uintptr_t)(&FALSE_VTABLE);
89
123
 
90
- /** Retruns a FALSE object. */
124
+ /** Returns a FALSE object. */
91
125
  fiobj_s *fiobj_false(void) {
92
- return fiobj_simple_alloc(FIOBJ_T_FALSE, &FIOBJ_VTABLE_FALSE);
93
- }
94
-
95
- /** Retruns a TRUE object. */
96
- fiobj_s *fiobj_true(void) {
97
- return fiobj_simple_alloc(FIOBJ_T_TRUE, &FIOBJ_VTABLE_TRUE);
126
+ static struct {
127
+ fiobj_head_s head;
128
+ struct fiobj_vtable_s *vtable;
129
+ } obj = {.head = {.ref = 1}, .vtable = &FALSE_VTABLE};
130
+ return (fiobj_s *)(&obj.vtable);
98
131
  }