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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +4 -4
- data/SPEC-Websocket-Draft.md +3 -6
- data/bin/mustache.rb +128 -0
- data/examples/test_template.mustache +16 -0
- data/ext/iodine/fio.c +9397 -0
- data/ext/iodine/fio.h +4723 -0
- data/ext/iodine/fio_ary.h +353 -54
- data/ext/iodine/fio_cli.c +351 -361
- data/ext/iodine/fio_cli.h +84 -105
- data/ext/iodine/fio_hashmap.h +70 -16
- data/ext/iodine/fio_json_parser.h +35 -24
- data/ext/iodine/fio_siphash.c +104 -4
- data/ext/iodine/fio_siphash.h +18 -2
- data/ext/iodine/fio_str.h +1218 -0
- data/ext/iodine/fio_tmpfile.h +1 -1
- data/ext/iodine/fiobj.h +13 -8
- data/ext/iodine/fiobj4sock.h +6 -8
- data/ext/iodine/fiobj_ary.c +107 -17
- data/ext/iodine/fiobj_ary.h +36 -4
- data/ext/iodine/fiobj_data.c +146 -127
- data/ext/iodine/fiobj_data.h +25 -23
- data/ext/iodine/fiobj_hash.c +7 -7
- data/ext/iodine/fiobj_hash.h +6 -5
- data/ext/iodine/fiobj_json.c +20 -17
- data/ext/iodine/fiobj_json.h +5 -5
- data/ext/iodine/fiobj_mem.h +71 -0
- data/ext/iodine/fiobj_mustache.c +310 -0
- data/ext/iodine/fiobj_mustache.h +40 -0
- data/ext/iodine/fiobj_numbers.c +199 -94
- data/ext/iodine/fiobj_numbers.h +7 -7
- data/ext/iodine/fiobj_str.c +142 -333
- data/ext/iodine/fiobj_str.h +65 -55
- data/ext/iodine/fiobject.c +49 -11
- data/ext/iodine/fiobject.h +40 -39
- data/ext/iodine/http.c +382 -190
- data/ext/iodine/http.h +124 -80
- data/ext/iodine/http1.c +99 -127
- data/ext/iodine/http1.h +5 -5
- data/ext/iodine/http1_parser.c +3 -2
- data/ext/iodine/http1_parser.h +2 -2
- data/ext/iodine/http_internal.c +14 -12
- data/ext/iodine/http_internal.h +25 -19
- data/ext/iodine/iodine.c +37 -18
- data/ext/iodine/iodine.h +4 -0
- data/ext/iodine/iodine_caller.c +9 -2
- data/ext/iodine/iodine_caller.h +2 -0
- data/ext/iodine/iodine_connection.c +82 -117
- data/ext/iodine/iodine_defer.c +57 -50
- data/ext/iodine/iodine_defer.h +0 -1
- data/ext/iodine/iodine_fiobj2rb.h +4 -2
- data/ext/iodine/iodine_helpers.c +4 -4
- data/ext/iodine/iodine_http.c +25 -32
- data/ext/iodine/iodine_json.c +2 -1
- data/ext/iodine/iodine_mustache.c +423 -0
- data/ext/iodine/iodine_mustache.h +6 -0
- data/ext/iodine/iodine_pubsub.c +48 -153
- data/ext/iodine/iodine_pubsub.h +5 -4
- data/ext/iodine/iodine_rack_io.c +7 -5
- data/ext/iodine/iodine_store.c +16 -13
- data/ext/iodine/iodine_tcp.c +26 -34
- data/ext/iodine/mustache_parser.h +1085 -0
- data/ext/iodine/redis_engine.c +740 -646
- data/ext/iodine/redis_engine.h +13 -15
- data/ext/iodine/resp_parser.h +11 -5
- data/ext/iodine/websocket_parser.h +13 -13
- data/ext/iodine/websockets.c +240 -393
- data/ext/iodine/websockets.h +52 -113
- data/lib/iodine.rb +1 -1
- data/lib/iodine/mustache.rb +140 -0
- data/lib/iodine/version.rb +1 -1
- metadata +15 -28
- data/ext/iodine/defer.c +0 -566
- data/ext/iodine/defer.h +0 -148
- data/ext/iodine/evio.c +0 -26
- data/ext/iodine/evio.h +0 -161
- data/ext/iodine/evio_callbacks.c +0 -26
- data/ext/iodine/evio_epoll.c +0 -251
- data/ext/iodine/evio_kqueue.c +0 -194
- data/ext/iodine/facil.c +0 -2325
- data/ext/iodine/facil.h +0 -616
- data/ext/iodine/fio_base64.c +0 -277
- data/ext/iodine/fio_base64.h +0 -71
- data/ext/iodine/fio_llist.h +0 -257
- data/ext/iodine/fio_mem.c +0 -675
- data/ext/iodine/fio_mem.h +0 -143
- data/ext/iodine/fio_random.c +0 -248
- data/ext/iodine/fio_random.h +0 -45
- data/ext/iodine/fio_sha1.c +0 -362
- data/ext/iodine/fio_sha1.h +0 -107
- data/ext/iodine/fio_sha2.c +0 -842
- data/ext/iodine/fio_sha2.h +0 -169
- data/ext/iodine/pubsub.c +0 -867
- data/ext/iodine/pubsub.h +0 -221
- data/ext/iodine/sock.c +0 -1366
- data/ext/iodine/sock.h +0 -566
- data/ext/iodine/spnlock.inc +0 -111
data/ext/iodine/fio_cli.h
CHANGED
@@ -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
|
-
|
57
|
-
|
15
|
+
/* *****************************************************************************
|
16
|
+
CLI API
|
17
|
+
***************************************************************************** */
|
58
18
|
|
59
|
-
/**
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
*
|
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
|
-
*
|
69
|
-
*
|
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
|
34
|
+
* The following optional type requirements are:
|
72
35
|
*
|
73
|
-
*
|
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
|
-
*
|
76
|
-
*
|
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
|
43
|
+
* The arguments "-?", "-h", "-help" and "--help" are automatically handled
|
44
|
+
* unless overridden.
|
84
45
|
*
|
85
|
-
*
|
46
|
+
* Example use:
|
86
47
|
*
|
87
|
-
*
|
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
|
-
*
|
56
|
+
* This would allow access to the named arguments:
|
98
57
|
*
|
99
|
-
*
|
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
|
-
*
|
104
|
-
*
|
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
|
-
*
|
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
|
-
|
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
|
-
*
|
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
|
-
|
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
|
-
*
|
83
|
+
* Clears the memory used by the CLI dictionary, removing all parsed data.
|
125
84
|
*
|
126
|
-
*
|
85
|
+
* This function is NOT thread safe.
|
127
86
|
*/
|
128
|
-
|
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
|
-
*
|
105
|
+
* Sets the argument's value as a NUL terminated C String (no copy!).
|
132
106
|
*
|
133
|
-
*
|
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
|
-
*
|
136
|
-
|
137
|
-
|
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
|
-
*
|
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
|
119
|
+
void fio_cli_set(char const *name, char const *value);
|
145
120
|
|
146
121
|
/**
|
147
|
-
*
|
122
|
+
* This MACRO is the same as:
|
148
123
|
*
|
149
|
-
*
|
124
|
+
* if(!fio_cli_get(name)) {
|
125
|
+
* fio_cli_set(name, value)
|
126
|
+
* }
|
150
127
|
*/
|
151
|
-
|
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" */
|
data/ext/iodine/fio_hashmap.h
CHANGED
@@ -5,8 +5,11 @@ License: MIT
|
|
5
5
|
*/
|
6
6
|
|
7
7
|
/**
|
8
|
-
* A simple ordered Hash Table implementation, with a minimal API
|
9
|
-
*
|
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 + (
|
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) ==
|
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 +
|
339
|
-
|
340
|
-
|
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
|
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
|
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
|
-
"
|
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
|
-
"
|
721
|
+
"Re-adding a removed item shouldn't change the position marker!");
|
701
722
|
TEST_ASSERT(fio_hash_find(&h, 1) == (void *)1,
|
702
|
-
"
|
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
|
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
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
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
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
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__)
|