iodine 0.6.5 → 0.7.0

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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +4 -4
  4. data/SPEC-Websocket-Draft.md +3 -6
  5. data/bin/mustache.rb +128 -0
  6. data/examples/test_template.mustache +16 -0
  7. data/ext/iodine/fio.c +9397 -0
  8. data/ext/iodine/fio.h +4723 -0
  9. data/ext/iodine/fio_ary.h +353 -54
  10. data/ext/iodine/fio_cli.c +351 -361
  11. data/ext/iodine/fio_cli.h +84 -105
  12. data/ext/iodine/fio_hashmap.h +70 -16
  13. data/ext/iodine/fio_json_parser.h +35 -24
  14. data/ext/iodine/fio_siphash.c +104 -4
  15. data/ext/iodine/fio_siphash.h +18 -2
  16. data/ext/iodine/fio_str.h +1218 -0
  17. data/ext/iodine/fio_tmpfile.h +1 -1
  18. data/ext/iodine/fiobj.h +13 -8
  19. data/ext/iodine/fiobj4sock.h +6 -8
  20. data/ext/iodine/fiobj_ary.c +107 -17
  21. data/ext/iodine/fiobj_ary.h +36 -4
  22. data/ext/iodine/fiobj_data.c +146 -127
  23. data/ext/iodine/fiobj_data.h +25 -23
  24. data/ext/iodine/fiobj_hash.c +7 -7
  25. data/ext/iodine/fiobj_hash.h +6 -5
  26. data/ext/iodine/fiobj_json.c +20 -17
  27. data/ext/iodine/fiobj_json.h +5 -5
  28. data/ext/iodine/fiobj_mem.h +71 -0
  29. data/ext/iodine/fiobj_mustache.c +310 -0
  30. data/ext/iodine/fiobj_mustache.h +40 -0
  31. data/ext/iodine/fiobj_numbers.c +199 -94
  32. data/ext/iodine/fiobj_numbers.h +7 -7
  33. data/ext/iodine/fiobj_str.c +142 -333
  34. data/ext/iodine/fiobj_str.h +65 -55
  35. data/ext/iodine/fiobject.c +49 -11
  36. data/ext/iodine/fiobject.h +40 -39
  37. data/ext/iodine/http.c +382 -190
  38. data/ext/iodine/http.h +124 -80
  39. data/ext/iodine/http1.c +99 -127
  40. data/ext/iodine/http1.h +5 -5
  41. data/ext/iodine/http1_parser.c +3 -2
  42. data/ext/iodine/http1_parser.h +2 -2
  43. data/ext/iodine/http_internal.c +14 -12
  44. data/ext/iodine/http_internal.h +25 -19
  45. data/ext/iodine/iodine.c +37 -18
  46. data/ext/iodine/iodine.h +4 -0
  47. data/ext/iodine/iodine_caller.c +9 -2
  48. data/ext/iodine/iodine_caller.h +2 -0
  49. data/ext/iodine/iodine_connection.c +82 -117
  50. data/ext/iodine/iodine_defer.c +57 -50
  51. data/ext/iodine/iodine_defer.h +0 -1
  52. data/ext/iodine/iodine_fiobj2rb.h +4 -2
  53. data/ext/iodine/iodine_helpers.c +4 -4
  54. data/ext/iodine/iodine_http.c +25 -32
  55. data/ext/iodine/iodine_json.c +2 -1
  56. data/ext/iodine/iodine_mustache.c +423 -0
  57. data/ext/iodine/iodine_mustache.h +6 -0
  58. data/ext/iodine/iodine_pubsub.c +48 -153
  59. data/ext/iodine/iodine_pubsub.h +5 -4
  60. data/ext/iodine/iodine_rack_io.c +7 -5
  61. data/ext/iodine/iodine_store.c +16 -13
  62. data/ext/iodine/iodine_tcp.c +26 -34
  63. data/ext/iodine/mustache_parser.h +1085 -0
  64. data/ext/iodine/redis_engine.c +740 -646
  65. data/ext/iodine/redis_engine.h +13 -15
  66. data/ext/iodine/resp_parser.h +11 -5
  67. data/ext/iodine/websocket_parser.h +13 -13
  68. data/ext/iodine/websockets.c +240 -393
  69. data/ext/iodine/websockets.h +52 -113
  70. data/lib/iodine.rb +1 -1
  71. data/lib/iodine/mustache.rb +140 -0
  72. data/lib/iodine/version.rb +1 -1
  73. metadata +15 -28
  74. data/ext/iodine/defer.c +0 -566
  75. data/ext/iodine/defer.h +0 -148
  76. data/ext/iodine/evio.c +0 -26
  77. data/ext/iodine/evio.h +0 -161
  78. data/ext/iodine/evio_callbacks.c +0 -26
  79. data/ext/iodine/evio_epoll.c +0 -251
  80. data/ext/iodine/evio_kqueue.c +0 -194
  81. data/ext/iodine/facil.c +0 -2325
  82. data/ext/iodine/facil.h +0 -616
  83. data/ext/iodine/fio_base64.c +0 -277
  84. data/ext/iodine/fio_base64.h +0 -71
  85. data/ext/iodine/fio_llist.h +0 -257
  86. data/ext/iodine/fio_mem.c +0 -675
  87. data/ext/iodine/fio_mem.h +0 -143
  88. data/ext/iodine/fio_random.c +0 -248
  89. data/ext/iodine/fio_random.h +0 -45
  90. data/ext/iodine/fio_sha1.c +0 -362
  91. data/ext/iodine/fio_sha1.h +0 -107
  92. data/ext/iodine/fio_sha2.c +0 -842
  93. data/ext/iodine/fio_sha2.h +0 -169
  94. data/ext/iodine/pubsub.c +0 -867
  95. data/ext/iodine/pubsub.h +0 -221
  96. data/ext/iodine/sock.c +0 -1366
  97. data/ext/iodine/sock.h +0 -566
  98. data/ext/iodine/spnlock.inc +0 -111
@@ -5,47 +5,6 @@ License: MIT
5
5
  Feel free to copy, use and enjoy according to the license provided.
6
6
  */
7
7
  #ifndef H_FIO_CLI_HELPER_H
8
- /**
9
-
10
- This is a customized version for command line interface (CLI) arguments. All
11
- arguments are converted into a key-value paired Hash.
12
-
13
- The CLI helper automatically provides `-?`, `-h` and `-help` support that
14
- prints a short explanation for every option and exits.
15
-
16
- The CLI will parse arguments in the form `-arg value` as well as `-arg=value`
17
- and `-argvalue`
18
-
19
- NOTICE:
20
-
21
- This interface is NOT thread-safe, since normally the command line arguments are
22
- parsed before new threads are spawned.
23
-
24
- It's important to set all the requirement before requesting any results,
25
- otherwise, parsing errors might occure - i.e., allowed parameters would be
26
- parsed as errors, since they hadn't been declared yet.
27
-
28
- EXAMPLE:
29
-
30
- // initialize the CLI helper.
31
- fio_cli_start(argc, argv, "App description or NULL");
32
-
33
- // setup possible command line arguments.
34
- fio_cli_accept_num("port p", "the port to listen to, defaults to 3000.");
35
- fio_cli_accept_bool("log v", "enable logging");
36
-
37
- // read command line arguments and copy results.
38
- uint8_t logging = fio_cli_get_int("v");
39
- const char *port = fio_cli_get_str("port");
40
- if (!port)
41
- port = "3000";
42
- // use parsed information.
43
- // ...
44
- // cleanup
45
- fio_cli_end();
46
-
47
-
48
- */
49
8
  #define H_FIO_CLI_HELPER_H
50
9
 
51
10
  /* support C++ */
@@ -53,102 +12,122 @@ EXAMPLE:
53
12
  extern "C" {
54
13
  #endif
55
14
 
56
- /** Initialize the CLI helper and adds the `info` string to the help section. */
57
- void fio_cli_start(int argc, const char **argv, const char *info);
15
+ /* *****************************************************************************
16
+ CLI API
17
+ ***************************************************************************** */
58
18
 
59
- /** Tells the CLI helper to ignore unrecognized command line arguments. */
60
- void fio_cli_ignore_unknown(void);
61
-
62
- /** Clears the memory and resources related to the CLI helper. */
63
- void fio_cli_end(void);
19
+ /** Indicates the previous CLI argument should be a String (default). */
20
+ #define FIO_CLI_TYPE_STRING ((char *)0x1)
21
+ /** Indicates the previous CLI argument is a Boolean value. */
22
+ #define FIO_CLI_TYPE_BOOL ((char *)0x2)
23
+ /** Indicates the previous CLI argument should be an Integer (numerical). */
24
+ #define FIO_CLI_TYPE_INT ((char *)0x3)
64
25
 
65
26
  /**
66
- * Sets a CLI acceptable argument of type Number (both `int` and `float`).
27
+ * This function parses the Command Line Interface (CLI), creating a temporary
28
+ * "dictionary" that allows easy access to the CLI using their names or aliases.
67
29
  *
68
- * The `aliases` string sets aliases for the same argument. i.e. "string s".
69
- * Notice that collisions will prefer new information quitely.
30
+ * Command line arguments may be typed. If an optional type requirement is
31
+ * provided and the provided arument fails to match the required type, execution
32
+ * will end and an error message will be printed along with a short "help".
70
33
  *
71
- * The first alias will be the name available for `fio_cli_get_*` functions.
34
+ * The following optional type requirements are:
72
35
  *
73
- * The `desc` string will be printed if `-?`, `-h` of `-help` are used.
36
+ * * FIO_CLI_TYPE_STRING - (default) string argument.
37
+ * * FIO_CLI_TYPE_BOOL - boolean argument (no value).
38
+ * * FIO_CLI_TYPE_INT - integer argument ('-', '+', '0'-'9' chars accepted).
74
39
  *
75
- * The function will crash the application on failure, printing an error
76
- * message.
77
- */
78
- void fio_cli_accept_num(const char *aliases, const char *desc);
79
-
80
- /**
81
- * Sets a CLI acceptable argument of type String.
40
+ * Argument names MUST start with the '-' character. The first word starting
41
+ * without the '-' character will begin the description for the CLI argument.
82
42
  *
83
- * The `aliases` string sets aliases for the same argument. i.e. "string s".
43
+ * The arguments "-?", "-h", "-help" and "--help" are automatically handled
44
+ * unless overridden.
84
45
  *
85
- * The first alias will be the name used
46
+ * Example use:
86
47
  *
87
- * The `desc` string will be printed if `-?`, `-h` of `-help` are used.
48
+ * fio_cli_start(argc, argv, 0, "this example accepts the following:",
49
+ * "-t -thread number of threads to run.", FIO_CLI_TYPE_INT,
50
+ * "-w -workers number of workers to run.", FIO_CLI_TYPE_INT,
51
+ * "-b, -address the address to bind to.",
52
+ * "-p,-port the port to bind to.", FIO_CLI_TYPE_INT,
53
+ * "-v -log enable logging.", FIO_CLI_TYPE_BOOL);
88
54
  *
89
- * The function will crash the application on failure, printing an error
90
- * message.
91
- */
92
- void fio_cli_accept_str(const char *aliases, const char *desc);
93
-
94
- /**
95
- * Sets a CLI acceptable argument of type Bool (true if exists).
96
55
  *
97
- * The `aliases` string sets aliases for the same argument. i.e. "string s".
56
+ * This would allow access to the named arguments:
98
57
  *
99
- * The first alias will be the name available for `fio_cli_get_*` functions.
58
+ * fio_cli_get("-b") == fio_cli_get("-address");
100
59
  *
101
- * The `desc` string will be printed if `-?`, `-h` of `-help` are used.
102
60
  *
103
- * The function will crash the application on failure, printing an error
104
- * message.
105
- */
106
- void fio_cli_accept_bool(const char *aliases, const char *desc);
107
-
108
- /**
109
- * Returns a C String containing the value of the received argument, or NULL if
110
- * none.
61
+ * Once all the data was accessed, free the parsed data dictionary using:
62
+ *
63
+ * fio_cli_end();
111
64
  *
112
- * Boolean that were set to TRUE have the string "1".
65
+ * It should be noted, arguments will be recognized in a number of forms, i.e.:
66
+ *
67
+ * app -t=1 -p3000 -a localhost
68
+ *
69
+ * This function is NOT thread safe.
113
70
  */
114
- const char *fio_cli_get_str(const char *opt);
115
-
71
+ #define fio_cli_start(argc, argv, allow_unknown, description, ...) \
72
+ fio_cli_start((argc), (argv), (allow_unknown), (description), \
73
+ (char const *[]){__VA_ARGS__, NULL})
74
+ #define FIO_CLI_IGNORE
116
75
  /**
117
- * Returns an Integer containing the parsed value of the argument.
118
- *
119
- * For boolean values, the value will be 0 for FALSE and 1 for TRUE.
76
+ * Never use the function directly, always use the MACRO, because the macro
77
+ * attaches a NULL marker at the end of the `names` argument collection.
120
78
  */
121
- int fio_cli_get_int(const char *opt);
122
-
79
+ void fio_cli_start FIO_CLI_IGNORE(int argc, char const *argv[],
80
+ int allow_unknown, char const *description,
81
+ char const **names);
123
82
  /**
124
- * Returns a Float containing the parsed value of the argument.
83
+ * Clears the memory used by the CLI dictionary, removing all parsed data.
125
84
  *
126
- * For boolean values, the value will be 0 for FALSE and 1 for TRUE.
85
+ * This function is NOT thread safe.
127
86
  */
128
- double fio_cli_get_float(const char *opt);
87
+ void fio_cli_end(void);
88
+
89
+ /** Returns the argument's value as a NUL terminated C String. */
90
+ char const *fio_cli_get(char const *name);
91
+
92
+ /** Returns the argument's value as an integer. */
93
+ int fio_cli_get_i(char const *name);
94
+
95
+ /** This MACRO returns the argument's value as a boolean. */
96
+ #define fio_cli_get_bool(name) (fio_cli_get((name)) != NULL)
97
+
98
+ /** Returns the number of unrecognized argument. */
99
+ unsigned int fio_cli_unknown_count(void);
100
+
101
+ /** Returns the unrecognized argument using a 0 based `index`. */
102
+ char const *fio_cli_unknown(unsigned int index);
129
103
 
130
104
  /**
131
- * Overrides the existing value of the argument with the requested C String.
105
+ * Sets the argument's value as a NUL terminated C String (no copy!).
132
106
  *
133
- * The String isn't copied, it's only referenced.
107
+ * CAREFUL: This does not automatically detect aliases or type violations! it
108
+ * will only effect the specific name given, even if invalid. i.e.:
134
109
  *
135
- * Boolean that were set to TRUE have the string "1".
136
- */
137
- void fio_cli_set_str(const char *opt, const char *value);
138
-
139
- /**
140
- * Overrides the existing value of the argument with the requested Integer.
110
+ * fio_cli_start(argc, argv,
111
+ * "this is example accepts the following options:",
112
+ * "-p -port the port to bind to", FIO_CLI_TYPE_INT;
113
+ *
114
+ * fio_cli_set("-p", "hello"); // fio_cli_get("-p") != fio_cli_get("-port");
141
115
  *
142
- * For boolean values, the value will be 0 for FALSE and 1 for TRUE.
116
+ * Note: this does NOT copy the C strings to memory. Memory should be kept alive
117
+ * until `fio_cli_end` is called.
143
118
  */
144
- void fio_cli_set_int(const char *opt, int value);
119
+ void fio_cli_set(char const *name, char const *value);
145
120
 
146
121
  /**
147
- * Overrides the existing value of the argument with the requested Float.
122
+ * This MACRO is the same as:
148
123
  *
149
- * For boolean values, the value will be 0 for FALSE and 1 for TRUE.
124
+ * if(!fio_cli_get(name)) {
125
+ * fio_cli_set(name, value)
126
+ * }
150
127
  */
151
- void fio_cli_set_float(const char *opt, double value);
128
+ #define fio_cli_set_default(name, value) \
129
+ if (!fio_cli_get((name))) \
130
+ fio_cli_set(name, value);
152
131
 
153
132
  #ifdef __cplusplus
154
133
  } /* extern "C" */
@@ -5,8 +5,11 @@ License: MIT
5
5
  */
6
6
 
7
7
  /**
8
- * A simple ordered Hash Table implementation, with a minimal API and zero hash
9
- * collision protection.
8
+ * A simple ordered Hash Table implementation, with a minimal API.
9
+ *
10
+ * Keys types are adjustable using macros. A single C file is limited to a
11
+ * single key type. Keys can be strings, integers, anything. By default, keys
12
+ * are uint64_t.
10
13
  *
11
14
  * Unique keys are required. Full key collisions aren't handled, instead the old
12
15
  * value is replaced and returned.
@@ -150,6 +153,11 @@ FIO_FUNC inline size_t fio_hash_count(const fio_hash_s *hash);
150
153
  */
151
154
  FIO_FUNC inline size_t fio_hash_capa(const fio_hash_s *hash);
152
155
 
156
+ /**
157
+ * Returns non-zero if the hash is fragmented (more than 50% holes).
158
+ */
159
+ FIO_FUNC inline size_t fio_hash_is_fragmented(const fio_hash_s *hash);
160
+
153
161
  /**
154
162
  * Attempts to minimize memory usage by removing empty spaces caused by deleted
155
163
  * items and rehashing the Hash Map.
@@ -324,20 +332,21 @@ FIO_FUNC inline uintptr_t fio_hash_map_cuckoo_steps(uintptr_t step) {
324
332
  /* seeks the hash's position in the map */
325
333
  FIO_FUNC fio_hash_data_s *fio_hash_seek_pos_(fio_hash_s *hash,
326
334
  FIO_HASH_KEY_TYPE key) {
335
+ const uint64_t hashed_key = FIO_HASH_KEY2UINT(key);
327
336
  /* TODO: consider implementing Robing Hood reordering during seek? */
328
- fio_hash_data_s *pos = hash->map + (FIO_HASH_KEY2UINT(key) & hash->mask);
337
+ fio_hash_data_s *pos = hash->map + (hashed_key & hash->mask);
329
338
  uintptr_t i = 0;
330
339
  const uintptr_t limit = hash->capa > FIO_HASH_MAX_MAP_SEEK
331
340
  ? FIO_HASH_MAX_MAP_SEEK
332
341
  : ((hash->capa >> 1) | 1);
333
342
  while (i < limit) {
334
343
  if (FIO_HASH_KEY_ISINVALID(pos->key) ||
335
- (FIO_HASH_KEY2UINT(pos->key) == FIO_HASH_KEY2UINT(key) &&
344
+ (FIO_HASH_KEY2UINT(pos->key) == hashed_key &&
336
345
  FIO_HASH_COMPARE_KEYS(pos->key, key)))
337
346
  return pos;
338
- pos = hash->map + (((FIO_HASH_KEY2UINT(key) & hash->mask) +
339
- fio_hash_map_cuckoo_steps(i++)) &
340
- hash->mask);
347
+ pos = hash->map +
348
+ (((hashed_key & hash->mask) + fio_hash_map_cuckoo_steps(i++)) &
349
+ hash->mask);
341
350
  }
342
351
  return NULL;
343
352
  }
@@ -357,9 +366,14 @@ FIO_FUNC inline void *fio_hash_find(fio_hash_s *hash, FIO_HASH_KEY_TYPE key) {
357
366
  */
358
367
  FIO_FUNC void *fio_hash_insert(fio_hash_s *hash, FIO_HASH_KEY_TYPE key,
359
368
  void *obj) {
369
+ /* nothing to do if there's nothing to do. */
370
+ if (!obj && !hash->count) {
371
+ return NULL;
372
+ }
360
373
  /* ensure some space */
361
- if (obj && hash->pos >= hash->capa)
374
+ if (obj && hash->pos >= hash->capa) {
362
375
  fio_hash_rehash(hash);
376
+ }
363
377
 
364
378
  /* find where the object belongs in the map */
365
379
  fio_hash_data_s *info = fio_hash_seek_pos_(hash, key);
@@ -603,7 +617,7 @@ FIO_FUNC inline size_t fio_hash_count(const fio_hash_s *hash) {
603
617
 
604
618
  /**
605
619
  * Returns a temporary theoretical Hash map capacity.
606
- * This could be used for testig performance and memory consumption.
620
+ * This could be used for testing performance and memory consumption.
607
621
  */
608
622
  FIO_FUNC inline size_t fio_hash_capa(const fio_hash_s *hash) {
609
623
  if (!hash)
@@ -611,6 +625,13 @@ FIO_FUNC inline size_t fio_hash_capa(const fio_hash_s *hash) {
611
625
  return hash->capa;
612
626
  }
613
627
 
628
+ /**
629
+ * Returns non-zero if the hash is fragmented (more than 50% holes).
630
+ */
631
+ FIO_FUNC inline size_t fio_hash_is_fragmented(const fio_hash_s *hash) {
632
+ return (hash->pos > (hash->count << 1));
633
+ }
634
+
614
635
  /**
615
636
  * Attempts to minimize memory usage by removing empty spaces caused by deleted
616
637
  * items and rehashing the Hash Map.
@@ -656,7 +677,7 @@ FIO_FUNC void fio_hash_test(void) {
656
677
  #define TEST_ASSERT(cond, ...) \
657
678
  if (!(cond)) { \
658
679
  fprintf(stderr, "* " __VA_ARGS__); \
659
- fprintf(stderr, "Testing failed.\n"); \
680
+ fprintf(stderr, "\n !!! Testing failed !!!\n"); \
660
681
  exit(-1); \
661
682
  }
662
683
  fio_hash_s h = {.capa = 0};
@@ -693,13 +714,13 @@ FIO_FUNC void fio_hash_test(void) {
693
714
  fio_hash_insert(&h, 1, (void *)1);
694
715
  TEST_ASSERT(
695
716
  count + 1 == h.count,
696
- "Readding a removed item should increase count by 1 (%zu + 1 != %zu).",
717
+ "Re-adding a removed item should increase count by 1 (%zu + 1 != %zu).",
697
718
  count, (size_t)h.count);
698
719
  TEST_ASSERT(
699
720
  pos == h.pos,
700
- "Readding a removed item shouldn't change the position marker!");
721
+ "Re-adding a removed item shouldn't change the position marker!");
701
722
  TEST_ASSERT(fio_hash_find(&h, 1) == (void *)1,
702
- "Readding a removed item should update the item (%p != 1)!",
723
+ "Re-adding a removed item should update the item (%p != 1)!",
703
724
  fio_hash_find(&h, 1));
704
725
  fio_hash_insert(&h, 1, NULL);
705
726
  TEST_ASSERT(count == h.count,
@@ -738,7 +759,7 @@ FIO_FUNC void fio_hash_test(void) {
738
759
  fprintf(stderr, "* Compacting Hash to %lu\n", FIO_HASHMAP_TEXT_COUNT >> 1);
739
760
  fio_hash_compact(&h);
740
761
  {
741
- fprintf(stderr, "* Testing that %lu items are continues\n",
762
+ fprintf(stderr, "* Testing that %lu items are continuous\n",
742
763
  FIO_HASHMAP_TEXT_COUNT >> 1);
743
764
  uintptr_t i = 0;
744
765
  FIO_HASH_FOR_LOOP(&h, pos) {
@@ -748,12 +769,45 @@ FIO_FUNC void fio_hash_test(void) {
748
769
  }
749
770
  TEST_ASSERT(i == h.count, "count error (%lu != %lu).", i, h.count);
750
771
  }
772
+
773
+ fio_hash_free(&h);
774
+ TEST_ASSERT(!h.map && !h.ordered && !h.pos && !h.capa,
775
+ "Hash not re-initialized after fio_hash_free");
776
+
777
+ fio_hash_new2(&h, FIO_HASHMAP_TEXT_COUNT);
778
+ for (unsigned long i = 1; i < FIO_HASHMAP_TEXT_COUNT; ++i) {
779
+ fio_hash_insert(&h, i, (void *)i);
780
+ TEST_ASSERT((i == (uintptr_t)fio_hash_find(&h, i)),
781
+ "insertion (2nd round) != find");
782
+ }
783
+ for (unsigned long i = 1; i < FIO_HASHMAP_TEXT_COUNT; i += 2) {
784
+ uintptr_t old = (uintptr_t)fio_hash_insert(&h, i, NULL);
785
+ TEST_ASSERT(old == i, "Removal didn't return old value.");
786
+ TEST_ASSERT(!(fio_hash_find(&h, i)), "Removal failed (still exists).");
787
+ }
788
+ fio_hash_rehash(&h);
789
+ {
790
+ fprintf(stderr,
791
+ "* Testing that %lu items are continuous (after rehashing)\n",
792
+ FIO_HASHMAP_TEXT_COUNT >> 1);
793
+ uintptr_t i = 0;
794
+ FIO_HASH_FOR_LOOP(&h, pos) {
795
+ TEST_ASSERT(pos->obj, "Found a hole after compact.");
796
+ TEST_ASSERT(pos->key == (uintptr_t)pos->obj, "Key and value mismatch.");
797
+ ++i;
798
+ }
799
+ TEST_ASSERT(i == h.count, "count error (%lu != %lu) post rehash.", i,
800
+ h.count);
801
+ }
751
802
  fio_hash_free(&h);
752
- fprintf(stderr, "* passed... without testing that FIO_HASH_KEY_DESTROY is "
753
- "called only once.\n");
754
803
  }
804
+
805
+ #undef TEST_ASSERT
755
806
  #endif /* DEBUG Testing */
756
807
 
808
+ #undef FIO_HASH_REALLOC
809
+ #undef FIO_HASH_CALLOC
810
+ #undef FIO_HASH_FREE
757
811
  #undef FIO_FUNC
758
812
 
759
813
  #endif /* H_FIO_SIMPLE_HASH_H */
@@ -26,6 +26,16 @@
26
26
  #include <stdio.h>
27
27
  #endif
28
28
 
29
+ #if !defined(__GNUC__) && !defined(__clang__) && !defined(FIO_GNUC_BYPASS)
30
+ #define __attribute__(...)
31
+ #define __has_include(...) 0
32
+ #define __has_builtin(...) 0
33
+ #define FIO_GNUC_BYPASS 1
34
+ #elif !defined(__clang__) && __GNUC__ < 5
35
+ #define __has_builtin(...) 0
36
+ #define FIO_GNUC_BYPASS 1
37
+ #endif
38
+
29
39
  /* *****************************************************************************
30
40
  JSON API
31
41
  ***************************************************************************** */
@@ -192,36 +202,37 @@ static inline int seek2marker(uint8_t **buffer,
192
202
  /* too short for this mess */
193
203
  if ((uintptr_t)limit <= 8 + ((uintptr_t)*buffer & (~(uintptr_t)7)))
194
204
  goto finish;
195
-
196
205
  /* align memory */
197
- {
198
- const uint8_t *alignment =
199
- (uint8_t *)(((uintptr_t)(*buffer) & (~(uintptr_t)7)) + 8);
200
- if (limit >= alignment) {
201
- while (*buffer < alignment) {
202
- if (string_seek_stop[**buffer])
203
- return 1;
204
- *buffer += 1;
206
+ if (1) {
207
+ {
208
+ const uint8_t *alignment =
209
+ (uint8_t *)(((uintptr_t)(*buffer) & (~(uintptr_t)7)) + 8);
210
+ if (limit >= alignment) {
211
+ while (*buffer < alignment) {
212
+ if (string_seek_stop[**buffer])
213
+ return 1;
214
+ *buffer += 1;
215
+ }
205
216
  }
206
217
  }
207
- }
208
- const uint8_t *limit64 = (uint8_t *)((uintptr_t)limit & (~(uintptr_t)7));
218
+ const uint8_t *limit64 = (uint8_t *)((uintptr_t)limit & (~(uintptr_t)7));
209
219
  #else
210
220
  const uint8_t *limit64 = (uint8_t *)limit - 7;
211
221
  #endif
212
- uint64_t wanted1 = 0x0101010101010101ULL * '"';
213
- uint64_t wanted2 = 0x0101010101010101ULL * '\\';
214
- for (; *buffer < limit64; *buffer += 8) {
215
- const uint64_t eq1 = ~((*((uint64_t *)*buffer)) ^ wanted1);
216
- const uint64_t t1 =
217
- ((eq1 & 0x7f7f7f7f7f7f7f7fULL) + 0x0101010101010101ULL) &
218
- (eq1 & 0x8080808080808080ULL);
219
- const uint64_t eq2 = ~((*((uint64_t *)*buffer)) ^ wanted2);
220
- const uint64_t t2 =
221
- ((eq2 & 0x7f7f7f7f7f7f7f7fULL) + 0x0101010101010101ULL) &
222
- (eq2 & 0x8080808080808080ULL);
223
- if ((t1 | t2)) {
224
- break;
222
+ uint64_t wanted1 = 0x0101010101010101ULL * '"';
223
+ uint64_t wanted2 = 0x0101010101010101ULL * '\\';
224
+ for (; *buffer < limit64; *buffer += 8) {
225
+ const uint64_t eq1 = ~((*((uint64_t *)*buffer)) ^ wanted1);
226
+ const uint64_t t1 =
227
+ ((eq1 & 0x7f7f7f7f7f7f7f7fULL) + 0x0101010101010101ULL) &
228
+ (eq1 & 0x8080808080808080ULL);
229
+ const uint64_t eq2 = ~((*((uint64_t *)*buffer)) ^ wanted2);
230
+ const uint64_t t2 =
231
+ ((eq2 & 0x7f7f7f7f7f7f7f7fULL) + 0x0101010101010101ULL) &
232
+ (eq2 & 0x8080808080808080ULL);
233
+ if ((t1 | t2)) {
234
+ break;
235
+ }
225
236
  }
226
237
  }
227
238
  #if !ALLOW_UNALIGNED_MEMORY_ACCESS || (!__x86_64__ && !__aarch64__)