iodine 0.7.1 → 0.7.2
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/.travis.yml +3 -3
- data/CHANGELOG.md +8 -0
- data/bin/mustache.rb +12 -40
- data/ext/iodine/fio.c +343 -236
- data/ext/iodine/fio.h +419 -183
- data/ext/iodine/fio_cli.c +4 -5
- data/ext/iodine/fiobj_ary.c +2 -3
- data/ext/iodine/fiobj_data.c +1 -1
- data/ext/iodine/fiobj_hash.c +88 -105
- data/ext/iodine/fiobj_json.c +4 -3
- data/ext/iodine/fiobj_numbers.c +1 -1
- data/ext/iodine/fiobj_str.c +5 -5
- data/ext/iodine/fiobject.c +14 -3
- data/ext/iodine/fiobject.h +4 -0
- data/ext/iodine/http.c +62 -77
- data/ext/iodine/http1.c +9 -12
- data/ext/iodine/http_internal.c +15 -6
- data/ext/iodine/http_internal.h +0 -8
- data/ext/iodine/iodine.c +12 -25
- data/ext/iodine/iodine_defer.c +59 -54
- data/ext/iodine/iodine_http.c +4 -32
- data/ext/iodine/iodine_mustache.c +138 -16
- data/ext/iodine/iodine_mustache.h +3 -3
- data/ext/iodine/iodine_store.c +16 -21
- data/ext/iodine/mustache_parser.h +49 -5
- data/ext/iodine/redis_engine.c +31 -31
- data/ext/iodine/websockets.c +11 -5
- data/lib/iodine.rb +13 -1
- data/lib/iodine/mustache.rb +13 -41
- data/lib/iodine/version.rb +1 -1
- metadata +2 -4
- data/ext/iodine/fio_hashmap.h +0 -813
- data/ext/iodine/fio_str.h +0 -1218
data/ext/iodine/fio.h
CHANGED
@@ -11,82 +11,84 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
11
11
|
#define H_FACIL_IO_H
|
12
12
|
|
13
13
|
/* *****************************************************************************
|
14
|
-
Table of contents:
|
15
|
-
=================
|
16
|
-
* Version and helper macros
|
17
|
-
* Helper String Information Type
|
18
|
-
* Memory pool / custom allocator for short lived objects
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
26
|
-
*
|
27
|
-
*
|
28
|
-
*
|
29
|
-
*
|
30
|
-
*
|
31
|
-
*
|
32
|
-
*
|
33
|
-
* Cluster Messages
|
34
|
-
* Cluster
|
35
|
-
*
|
36
|
-
*
|
37
|
-
*
|
38
|
-
*
|
39
|
-
*
|
40
|
-
*
|
41
|
-
*
|
42
|
-
*
|
43
|
-
*
|
44
|
-
*
|
45
|
-
* SHA-
|
46
|
-
*
|
47
|
-
*
|
48
|
-
*
|
49
|
-
*
|
50
|
-
*
|
51
|
-
*
|
52
|
-
|
53
|
-
|
54
|
-
*
|
55
|
-
*
|
56
|
-
*
|
57
|
-
*
|
58
|
-
*
|
59
|
-
*
|
60
|
-
*
|
61
|
-
*
|
62
|
-
|
63
|
-
*
|
64
|
-
*
|
65
|
-
*
|
66
|
-
*
|
67
|
-
*
|
68
|
-
*
|
69
|
-
*
|
70
|
-
* String
|
71
|
-
* String API -
|
72
|
-
* String API -
|
73
|
-
* String API -
|
74
|
-
* String
|
75
|
-
* String Implementation -
|
76
|
-
* String Implementation -
|
77
|
-
* String Implementation -
|
78
|
-
*
|
79
|
-
*
|
80
|
-
*
|
81
|
-
*
|
82
|
-
*
|
83
|
-
*
|
84
|
-
* Set / Hash Map
|
85
|
-
* Set / Hash Map
|
86
|
-
* Set / Hash Map Internal
|
87
|
-
* Set / Hash Map
|
88
|
-
*
|
89
|
-
|
14
|
+
* Table of contents (find by subject):
|
15
|
+
* =================
|
16
|
+
* Version and helper macros
|
17
|
+
* Helper String Information Type
|
18
|
+
* Memory pool / custom allocator for short lived objects
|
19
|
+
* Logging and testing helpers
|
20
|
+
*
|
21
|
+
* Connection Callback (Protocol) Management
|
22
|
+
* Listening to Incoming Connections
|
23
|
+
* Connecting to remote servers as a client
|
24
|
+
* Starting the IO reactor and reviewing it's state
|
25
|
+
* Socket / Connection Functions
|
26
|
+
* Connection Read / Write Hooks, for overriding the system calls
|
27
|
+
* Concurrency overridable functions
|
28
|
+
* Connection Task scheduling
|
29
|
+
* Event / Task scheduling
|
30
|
+
* Startup / State Callbacks (fork, start up, idle, etc')
|
31
|
+
* Lower Level API - for special circumstances, use with care under
|
32
|
+
*
|
33
|
+
* Pub/Sub / Cluster Messages API
|
34
|
+
* Cluster Messages and Pub/Sub
|
35
|
+
* Cluster / Pub/Sub Middleware and Extensions ("Engines")
|
36
|
+
*
|
37
|
+
* Atomic Operations and Spin Locking Helper Functions
|
38
|
+
* Byte Swapping and Network Order
|
39
|
+
*
|
40
|
+
* Converting Numbers to Strings (and back)
|
41
|
+
* Strings to Numbers
|
42
|
+
* Numbers to Strings* Random Generator Functions
|
43
|
+
*
|
44
|
+
* SipHash
|
45
|
+
* SHA-1
|
46
|
+
* SHA-2
|
47
|
+
* Base64 (URL) encoding
|
48
|
+
*
|
49
|
+
* Memory Allocator Details
|
50
|
+
*
|
51
|
+
* Spin locking Implementation
|
52
|
+
*
|
53
|
+
******** facil.io Data Types (String, Set / Hash Map, Linked Lists, etc')
|
54
|
+
*
|
55
|
+
* These types can be included by defining the macros and (re)including fio.h.
|
56
|
+
*
|
57
|
+
*
|
58
|
+
*
|
59
|
+
* #ifdef FIO_INCLUDE_LINKED_LIST
|
60
|
+
*
|
61
|
+
* Linked List Helpers
|
62
|
+
* Independent Linked List API
|
63
|
+
* Embedded Linked List API* Independent Linked List Implementation
|
64
|
+
* Embeded Linked List Implementation
|
65
|
+
*
|
66
|
+
*
|
67
|
+
*
|
68
|
+
* #ifdef FIO_INCLUDE_STR
|
69
|
+
*
|
70
|
+
* String Helpers
|
71
|
+
* String API - Initialization and Destruction
|
72
|
+
* String API - String state (data pointers, length, capacity, etc')
|
73
|
+
* String API - Memory management
|
74
|
+
* String API - UTF-8 State
|
75
|
+
* String Implementation - state (data pointers, length, capacity, etc')
|
76
|
+
* String Implementation - Memory management
|
77
|
+
* String Implementation - UTF-8 State
|
78
|
+
* String Implementation - Content Manipulation and Review
|
79
|
+
*
|
80
|
+
*
|
81
|
+
*
|
82
|
+
* #ifdef FIO_SET_NAME - can be included more than once
|
83
|
+
*
|
84
|
+
* Set / Hash Map Data-Store
|
85
|
+
* Set / Hash Map API
|
86
|
+
* Set / Hash Map Internal Data Structures
|
87
|
+
* Set / Hash Map Internal Helpers
|
88
|
+
* Set / Hash Map Implementation
|
89
|
+
*
|
90
|
+
*****************************************************************************
|
91
|
+
*/
|
90
92
|
|
91
93
|
/* *****************************************************************************
|
92
94
|
Version and helper macros
|
@@ -199,44 +201,11 @@ Version and helper macros
|
|
199
201
|
#define FIO_FUNC static __attribute__((unused))
|
200
202
|
#endif
|
201
203
|
|
202
|
-
#ifndef FIO_ASSERT_ALLOC
|
203
|
-
/** Tests for an allocation failure. The behavior can be overridden. */
|
204
|
-
#define FIO_ASSERT_ALLOC(ptr) \
|
205
|
-
if (!(ptr)) { \
|
206
|
-
fprintf(stderr, \
|
207
|
-
"FATAL ERROR: memory allocation error "__FILE__ \
|
208
|
-
":%d\n", \
|
209
|
-
__LINE__); \
|
210
|
-
perror(" Error details (errno)"); \
|
211
|
-
kill(0, SIGINT); \
|
212
|
-
exit(errno); \
|
213
|
-
}
|
214
|
-
#endif
|
215
|
-
|
216
204
|
#if defined(__FreeBSD__)
|
217
205
|
#include <netinet/in.h>
|
218
206
|
#include <sys/socket.h>
|
219
207
|
#endif
|
220
208
|
|
221
|
-
#if FIO_PRINT_STATE
|
222
|
-
#define FIO_LOG_STATE(...) fprintf(stderr, __VA_ARGS__)
|
223
|
-
#else
|
224
|
-
#define FIO_LOG_STATE(...)
|
225
|
-
#endif
|
226
|
-
|
227
|
-
#if DEBUG
|
228
|
-
#define FIO_LOG_DEBUG(...) FIO_LOG_STATE("INFO [DEBUG]: " __VA_ARGS__)
|
229
|
-
#define FIO_ASSERT(cond, ...) \
|
230
|
-
if (!(cond)) { \
|
231
|
-
fprintf(stderr, "FATAL [DEBUG] (" __FILE__ \
|
232
|
-
":" FIO_MACRO2STR(__LINE__) "): " __VA_ARGS__); \
|
233
|
-
exit(-1); \
|
234
|
-
}
|
235
|
-
#else
|
236
|
-
#define FIO_LOG_DEBUG(...)
|
237
|
-
#define FIO_ASSERT(...)
|
238
|
-
#endif
|
239
|
-
|
240
209
|
/* *****************************************************************************
|
241
210
|
C++ extern start
|
242
211
|
***************************************************************************** */
|
@@ -260,7 +229,31 @@ typedef struct fio_str_info_s {
|
|
260
229
|
#endif
|
261
230
|
|
262
231
|
/* *****************************************************************************
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
|
236
|
+
|
237
|
+
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
|
263
244
|
Memory pool / custom allocator for short lived objects
|
245
|
+
|
246
|
+
|
247
|
+
|
248
|
+
|
249
|
+
|
250
|
+
|
251
|
+
|
252
|
+
|
253
|
+
|
254
|
+
|
255
|
+
|
256
|
+
|
264
257
|
***************************************************************************** */
|
265
258
|
|
266
259
|
/**
|
@@ -308,10 +301,16 @@ void *fio_realloc2(void *ptr, size_t new_size, size_t copy_length);
|
|
308
301
|
*/
|
309
302
|
void *fio_mmap(size_t size);
|
310
303
|
|
304
|
+
/**
|
305
|
+
* When forking is called manually, call this function to reset the facil.io
|
306
|
+
* memory allocator's locks.
|
307
|
+
*/
|
308
|
+
void fio_malloc_after_fork(void);
|
309
|
+
|
311
310
|
#if FIO_FORCE_MALLOC
|
312
|
-
#define fio_malloc
|
311
|
+
#define fio_malloc(size) calloc(size, 1)
|
313
312
|
#define fio_calloc calloc
|
314
|
-
#define fio_mmap
|
313
|
+
#define fio_mmap(size) calloc(size, 1)
|
315
314
|
#define fio_free free
|
316
315
|
#define fio_realloc realloc
|
317
316
|
#define fio_realloc2(ptr, new_size, old_data_len) realloc((ptr), (new_size))
|
@@ -332,6 +331,100 @@ void *fio_mmap(size_t size);
|
|
332
331
|
|
333
332
|
|
334
333
|
|
334
|
+
Logging and testing helpers
|
335
|
+
|
336
|
+
|
337
|
+
|
338
|
+
|
339
|
+
|
340
|
+
|
341
|
+
|
342
|
+
|
343
|
+
|
344
|
+
|
345
|
+
|
346
|
+
|
347
|
+
***************************************************************************** */
|
348
|
+
|
349
|
+
/** Logging level of zero (no logging). */
|
350
|
+
#define FIO_LOG_LEVEL_NONE 0
|
351
|
+
/** Log fatal errors. */
|
352
|
+
#define FIO_LOG_LEVEL_FATAL 1
|
353
|
+
/** Log errors and fatal errors. */
|
354
|
+
#define FIO_LOG_LEVEL_ERROR 2
|
355
|
+
/** Log warnings, errors and fatal errors. */
|
356
|
+
#define FIO_LOG_LEVEL_WARNING 3
|
357
|
+
/** Log every message (info, warnings, errors and fatal errors). */
|
358
|
+
#define FIO_LOG_LEVEL_INFO 4
|
359
|
+
/** Log everything, including debug messages. */
|
360
|
+
#define FIO_LOG_LEVEL_DEBUG 5
|
361
|
+
|
362
|
+
/** The logging level */
|
363
|
+
extern size_t FIO_LOG_LEVEL;
|
364
|
+
|
365
|
+
#ifndef FIO_LOG_PRINT
|
366
|
+
#define FIO_LOG_PRINT(level, ...) \
|
367
|
+
do { \
|
368
|
+
if (level <= FIO_LOG_LEVEL) \
|
369
|
+
fprintf(stderr, "\n" __VA_ARGS__); \
|
370
|
+
} while (0)
|
371
|
+
#define FIO_LOG_DEBUG(...) \
|
372
|
+
FIO_LOG_PRINT(FIO_LOG_LEVEL_DEBUG, \
|
373
|
+
"[DEBUG ("__FILE__ \
|
374
|
+
":" FIO_MACRO2STR(__LINE__) ")] " __VA_ARGS__)
|
375
|
+
#define FIO_LOG_INFO(...) \
|
376
|
+
FIO_LOG_PRINT(FIO_LOG_LEVEL_INFO, "[INFO] " __VA_ARGS__)
|
377
|
+
#define FIO_LOG_WARNING(...) \
|
378
|
+
FIO_LOG_PRINT(FIO_LOG_LEVEL_WARNING, "[WARNING] " __VA_ARGS__)
|
379
|
+
#define FIO_LOG_ERROR(...) \
|
380
|
+
FIO_LOG_PRINT(FIO_LOG_LEVEL_ERROR, "[ERROR] " __VA_ARGS__)
|
381
|
+
#define FIO_LOG_FATAL(...) \
|
382
|
+
FIO_LOG_PRINT(FIO_LOG_LEVEL_FATAL, "[FATAL] " __VA_ARGS__)
|
383
|
+
#endif
|
384
|
+
|
385
|
+
#if FIO_PRINT_STATE
|
386
|
+
#define FIO_LOG_STATE(...) fprintf(stderr, "\n" __VA_ARGS__)
|
387
|
+
#else
|
388
|
+
#define FIO_LOG_STATE(...)
|
389
|
+
#endif
|
390
|
+
|
391
|
+
#if DEBUG
|
392
|
+
#define FIO_ASSERT(cond, ...) \
|
393
|
+
if (!(cond)) { \
|
394
|
+
FIO_LOG_DEBUG(__VA_ARGS__); \
|
395
|
+
exit(-1); \
|
396
|
+
}
|
397
|
+
#else
|
398
|
+
#define FIO_ASSERT(...)
|
399
|
+
#endif
|
400
|
+
|
401
|
+
#ifndef FIO_ASSERT_ALLOC
|
402
|
+
/** Tests for an allocation failure. The behavior can be overridden. */
|
403
|
+
#define FIO_ASSERT_ALLOC(ptr) \
|
404
|
+
if (!(ptr)) { \
|
405
|
+
fprintf(stderr, \
|
406
|
+
"FATAL ERROR: memory allocation error "__FILE__ \
|
407
|
+
":%d\n", \
|
408
|
+
__LINE__); \
|
409
|
+
perror(" Error details (errno)"); \
|
410
|
+
kill(0, SIGINT); \
|
411
|
+
exit(errno); \
|
412
|
+
}
|
413
|
+
#endif
|
414
|
+
|
415
|
+
/* *****************************************************************************
|
416
|
+
|
417
|
+
|
418
|
+
|
419
|
+
|
420
|
+
|
421
|
+
|
422
|
+
|
423
|
+
|
424
|
+
|
425
|
+
|
426
|
+
|
427
|
+
|
335
428
|
Connection Callback (Protocol) Management
|
336
429
|
|
337
430
|
|
@@ -1082,8 +1175,6 @@ typedef struct fio_rw_hook_s {
|
|
1082
1175
|
ssize_t (*write)(intptr_t uuid, void *udata, const void *buf, size_t count);
|
1083
1176
|
/**
|
1084
1177
|
* The `close` callback should close the underlying socket / file descriptor.
|
1085
|
-
* It should also be used to release any resources associated with the
|
1086
|
-
* connection's read/write hooks.
|
1087
1178
|
*
|
1088
1179
|
* If the function returns a non-zero value, it will be called again after an
|
1089
1180
|
* attempt to flush the socket and any pending outgoing buffer.
|
@@ -1103,6 +1194,10 @@ typedef struct fio_rw_hook_s {
|
|
1103
1194
|
* deadlock might occur.
|
1104
1195
|
*/
|
1105
1196
|
ssize_t (*flush)(intptr_t uuid, void *udata);
|
1197
|
+
/**
|
1198
|
+
* Called to perform cleanup after the socket was closed.
|
1199
|
+
* */
|
1200
|
+
void (*cleanup)(void *udata);
|
1106
1201
|
} fio_rw_hook_s;
|
1107
1202
|
|
1108
1203
|
/** Sets a socket hook state (a pointer to the struct). */
|
@@ -1260,6 +1355,8 @@ typedef enum {
|
|
1260
1355
|
FIO_CALL_AFTER_FORK,
|
1261
1356
|
/** Called by a worker process right after forking. */
|
1262
1357
|
FIO_CALL_IN_CHILD,
|
1358
|
+
/** Called by the master process after spawning a worker (after forking). */
|
1359
|
+
FIO_CALL_IN_MASTER,
|
1263
1360
|
/** Called every time a *Worker* proceess starts. */
|
1264
1361
|
FIO_CALL_ON_START,
|
1265
1362
|
/** Called when facil.io enters idling mode. */
|
@@ -2424,9 +2521,9 @@ C++ extern end
|
|
2424
2521
|
#undef FIO_MEMORY_BLOCK_SIZE
|
2425
2522
|
#undef FIO_MEMORY_BLOCK_MASK
|
2426
2523
|
#undef FIO_MEMORY_BLOCK_SLICES
|
2427
|
-
#define FIO_MEMORY_BLOCK_MASK (FIO_MEMORY_BLOCK_SIZE - 1) /* 0b111... */
|
2428
|
-
#define FIO_MEMORY_BLOCK_SLICES (FIO_MEMORY_BLOCK_SIZE >> 4) /* 16B slices */
|
2429
2524
|
#define FIO_MEMORY_BLOCK_SIZE ((uintptr_t)1 << FIO_MEMORY_BLOCK_SIZE_LOG)
|
2525
|
+
#define FIO_MEMORY_BLOCK_MASK (FIO_MEMORY_BLOCK_SIZE - 1) /* 0b0...1... */
|
2526
|
+
#define FIO_MEMORY_BLOCK_SLICES (FIO_MEMORY_BLOCK_SIZE >> 4) /* 16B slices */
|
2430
2527
|
|
2431
2528
|
#ifndef FIO_MEMORY_BLOCK_ALLOC_LIMIT
|
2432
2529
|
/* defaults to 37.5% of the block, after which `mmap` is used instead */
|
@@ -2515,13 +2612,13 @@ FIO_FUNC inline void fio_lock_dbg(fio_lock_i *lock, const char *file,
|
|
2515
2612
|
while (fio_trylock(lock)) {
|
2516
2613
|
if (lock_cycle_count >= 8 &&
|
2517
2614
|
(lock_cycle_count == 8 || !(lock_cycle_count & 511)))
|
2518
|
-
fprintf(stderr, "
|
2615
|
+
fprintf(stderr, "[DEBUG] fio-spinlock spin %s:%d round %zu\n", file, line,
|
2519
2616
|
lock_cycle_count);
|
2520
2617
|
++lock_cycle_count;
|
2521
2618
|
fio_reschedule_thread();
|
2522
2619
|
}
|
2523
2620
|
if (lock_cycle_count >= 8)
|
2524
|
-
fprintf(stderr, "
|
2621
|
+
fprintf(stderr, "[DEBUG] fio-spinlock spin %s:%d total = %zu\n", file, line,
|
2525
2622
|
lock_cycle_count);
|
2526
2623
|
}
|
2527
2624
|
#define fio_lock(lock) fio_lock_dbg((lock), __FILE__, __LINE__)
|
@@ -2537,7 +2634,7 @@ FIO_FUNC inline int fio_trylock_dbg(fio_lock_i *lock, const char *file,
|
|
2537
2634
|
} else if (line == last_line) {
|
2538
2635
|
++count;
|
2539
2636
|
if (count >= 2)
|
2540
|
-
fprintf(stderr, "
|
2637
|
+
fprintf(stderr, "[DEBUG] trying fio-spinlock %s:%d attempt %zu\n", file,
|
2541
2638
|
line, count);
|
2542
2639
|
} else {
|
2543
2640
|
count = 0;
|
@@ -2834,10 +2931,16 @@ String API - Initialization and Destruction
|
|
2834
2931
|
* used.
|
2835
2932
|
*/
|
2836
2933
|
typedef struct {
|
2934
|
+
#ifndef FIO_STR_NO_REF
|
2837
2935
|
volatile uint32_t ref; /* reference counter for fio_str_dup */
|
2936
|
+
#endif
|
2838
2937
|
uint8_t small; /* Flag indicating the String is small and self-contained */
|
2839
2938
|
uint8_t frozen; /* Flag indicating the String is frozen (don't edit) */
|
2840
|
-
|
2939
|
+
#ifdef FIO_STR_NO_REF
|
2940
|
+
uint8_t reserved[14]; /* Align struct on 16 byte allocator boundary */
|
2941
|
+
#else
|
2942
|
+
uint8_t reserved[10]; /* Align struct on 16 byte allocator boundary */
|
2943
|
+
#endif
|
2841
2944
|
uint64_t capa; /* Known capacity for longer Strings */
|
2842
2945
|
uint64_t len; /* String length for longer Strings */
|
2843
2946
|
void (*dealloc)(void *); /* Data deallocation function (NULL for static) */
|
@@ -2910,6 +3013,9 @@ inline FIO_FUNC fio_str_s *fio_str_new_copy2(fio_str_s *src);
|
|
2910
3013
|
/**
|
2911
3014
|
* Adds a references to the current String object and returns itself.
|
2912
3015
|
*
|
3016
|
+
* If refecrence counting was disabled (FIO_STR_NO_REF was defined), returns a
|
3017
|
+
* copy of the String (free with `fio_str_free2`).
|
3018
|
+
*
|
2913
3019
|
* NOTE: Nothing is copied, reference Strings are referencing the same String.
|
2914
3020
|
* Editing one reference will effect the other.
|
2915
3021
|
*
|
@@ -3145,7 +3251,9 @@ String Implementation - state (data pointers, length, capacity, etc')
|
|
3145
3251
|
***************************************************************************** */
|
3146
3252
|
|
3147
3253
|
typedef struct {
|
3254
|
+
#ifndef FIO_STR_NO_REF
|
3148
3255
|
volatile uint32_t ref; /* reference counter for fio_str_dup */
|
3256
|
+
#endif
|
3149
3257
|
uint8_t small; /* Flag indicating the String is small and self-contained */
|
3150
3258
|
uint8_t frozen; /* Flag indicating the String is frozen (don't edit) */
|
3151
3259
|
} fio_str__small_s;
|
@@ -3199,6 +3307,9 @@ inline FIO_FUNC fio_str_s *fio_str_new_copy2(fio_str_s *src) {
|
|
3199
3307
|
/**
|
3200
3308
|
* Adds a references to the current String object and returns itself.
|
3201
3309
|
*
|
3310
|
+
* If refecrence counting was disabled (FIO_STR_NO_REF was defined), returns a
|
3311
|
+
* copy of the String (free with `fio_str_free2`).
|
3312
|
+
*
|
3202
3313
|
* NOTE: Nothing is copied, reference Strings are referencing the same String.
|
3203
3314
|
* Editing one reference will effect the other.
|
3204
3315
|
*
|
@@ -3207,9 +3318,15 @@ inline FIO_FUNC fio_str_s *fio_str_new_copy2(fio_str_s *src) {
|
|
3207
3318
|
* were freed using `fio_str_free` / `fio_str_free2` or discarded.
|
3208
3319
|
*/
|
3209
3320
|
inline FIO_FUNC fio_str_s *fio_str_dup(fio_str_s *s) {
|
3321
|
+
#ifdef FIO_STR_NO_REF
|
3322
|
+
fio_str_s *s2 = fio_str_new2();
|
3323
|
+
fio_str_concat(s2, s);
|
3324
|
+
return s2;
|
3325
|
+
#else
|
3210
3326
|
if (s)
|
3211
3327
|
fio_atomic_add(&s->ref, 1);
|
3212
3328
|
return s;
|
3329
|
+
#endif
|
3213
3330
|
}
|
3214
3331
|
|
3215
3332
|
/**
|
@@ -3222,13 +3339,14 @@ inline FIO_FUNC fio_str_s *fio_str_dup(fio_str_s *s) {
|
|
3222
3339
|
* references (see fio_str_dup).
|
3223
3340
|
*/
|
3224
3341
|
inline FIO_FUNC int fio_str_free(fio_str_s *s) {
|
3225
|
-
|
3226
|
-
|
3227
|
-
|
3228
|
-
|
3229
|
-
|
3230
|
-
|
3231
|
-
|
3342
|
+
#ifndef FIO_STR_NO_REF
|
3343
|
+
if (!s || fio_atomic_sub(&s->ref, 1) != (uint32_t)-1)
|
3344
|
+
return -1;
|
3345
|
+
#endif
|
3346
|
+
if (!s->small && s->dealloc)
|
3347
|
+
s->dealloc(s->data);
|
3348
|
+
*s = FIO_STR_INIT;
|
3349
|
+
return 0;
|
3232
3350
|
}
|
3233
3351
|
|
3234
3352
|
/**
|
@@ -3323,7 +3441,7 @@ String Implementation - Memory management
|
|
3323
3441
|
* since it uses 16 byte alignment right up until allocations are routed
|
3324
3442
|
* directly to `mmap` (due to their size, usually over 12KB).
|
3325
3443
|
*/
|
3326
|
-
#define
|
3444
|
+
#define ROUND_UP_CAPA2WORDS(num) \
|
3327
3445
|
(((num + 1) & (sizeof(long double) - 1)) \
|
3328
3446
|
? ((num + 1) | (sizeof(long double) - 1)) \
|
3329
3447
|
: (num))
|
@@ -3339,7 +3457,7 @@ FIO_FUNC fio_str_info_s fio_str_capa_assert(fio_str_s *s, size_t needed) {
|
|
3339
3457
|
goto is_small;
|
3340
3458
|
}
|
3341
3459
|
if (needed > s->capa) {
|
3342
|
-
needed =
|
3460
|
+
needed = ROUND_UP_CAPA2WORDS(needed);
|
3343
3461
|
if (s->dealloc == fio_free) {
|
3344
3462
|
tmp = (char *)fio_realloc2(s->data, needed + 1, s->len);
|
3345
3463
|
FIO_ASSERT_ALLOC(tmp);
|
@@ -3364,7 +3482,7 @@ is_small:
|
|
3364
3482
|
.len = (size_t)(s->small >> 1),
|
3365
3483
|
.data = FIO_STR_SMALL_DATA(s)};
|
3366
3484
|
}
|
3367
|
-
needed =
|
3485
|
+
needed = ROUND_UP_CAPA2WORDS(needed);
|
3368
3486
|
tmp = (char *)fio_malloc(needed + 1);
|
3369
3487
|
FIO_ASSERT_ALLOC(tmp);
|
3370
3488
|
const size_t existing_len = (size_t)((s->small >> 1) & 0xFF);
|
@@ -3373,6 +3491,15 @@ is_small:
|
|
3373
3491
|
} else {
|
3374
3492
|
tmp[0] = 0;
|
3375
3493
|
}
|
3494
|
+
#ifdef FIO_STR_NO_REF
|
3495
|
+
*s = (fio_str_s){
|
3496
|
+
.small = 0,
|
3497
|
+
.capa = needed,
|
3498
|
+
.len = existing_len,
|
3499
|
+
.dealloc = fio_free,
|
3500
|
+
.data = tmp,
|
3501
|
+
};
|
3502
|
+
#else
|
3376
3503
|
*s = (fio_str_s){
|
3377
3504
|
.ref = s->ref,
|
3378
3505
|
.small = 0,
|
@@ -3381,6 +3508,7 @@ is_small:
|
|
3381
3508
|
.dealloc = fio_free,
|
3382
3509
|
.data = tmp,
|
3383
3510
|
};
|
3511
|
+
#endif
|
3384
3512
|
return (fio_str_info_s){
|
3385
3513
|
.capa = (s->frozen ? 0 : needed), .len = existing_len, .data = s->data};
|
3386
3514
|
}
|
@@ -3845,11 +3973,9 @@ FIO_FUNC fio_str_info_s fio_str_readfile(fio_str_s *s, const char *filename,
|
|
3845
3973
|
const size_t org_len = fio_str_len(s);
|
3846
3974
|
state = fio_str_resize(s, org_len + limit);
|
3847
3975
|
if (pread(file, state.data + org_len, limit, start_at) != (ssize_t)limit) {
|
3848
|
-
close(file);
|
3849
3976
|
fio_str_resize(s, org_len);
|
3850
3977
|
state.data = NULL;
|
3851
3978
|
state.len = state.capa = 0;
|
3852
|
-
goto finish;
|
3853
3979
|
}
|
3854
3980
|
close(file);
|
3855
3981
|
finish:
|
@@ -3857,7 +3983,7 @@ finish:
|
|
3857
3983
|
return state;
|
3858
3984
|
#else
|
3859
3985
|
/* TODO: consider adding non POSIX implementations. */
|
3860
|
-
|
3986
|
+
FIO_LOG_ERROR("File reading requires a posix system (ignored!).\n");
|
3861
3987
|
return state;
|
3862
3988
|
#endif
|
3863
3989
|
}
|
@@ -3901,8 +4027,9 @@ inline FIO_FUNC ssize_t fio_str_send_free2(const intptr_t uuid,
|
|
3901
4027
|
.after.dealloc = (void (*)(void *))fio_str_free2);
|
3902
4028
|
}
|
3903
4029
|
|
3904
|
-
#undef
|
4030
|
+
#undef ROUND_UP_CAPA2WORDS
|
3905
4031
|
#undef FIO_STR_SMALL_DATA
|
4032
|
+
#undef FIO_STR_NO_REF
|
3906
4033
|
|
3907
4034
|
#endif /* H_FIO_STR_H */
|
3908
4035
|
/* *****************************************************************************
|
@@ -4139,7 +4266,7 @@ FIO_FUNC void FIO_NAME(free)(FIO_NAME(s) * set);
|
|
4139
4266
|
#ifdef FIO_SET_KEY_TYPE
|
4140
4267
|
|
4141
4268
|
/**
|
4142
|
-
*Locates an object in the
|
4269
|
+
* Locates an object in the Hash Map, if it exists.
|
4143
4270
|
*
|
4144
4271
|
* NOTE: This is the function's Hash Map variant. See FIO_SET_KEY_TYPE.
|
4145
4272
|
*/
|
@@ -4148,13 +4275,15 @@ FIO_FUNC inline FIO_SET_OBJ_TYPE *
|
|
4148
4275
|
FIO_SET_KEY_TYPE key);
|
4149
4276
|
|
4150
4277
|
/**
|
4151
|
-
* Inserts an object to the
|
4152
|
-
*
|
4278
|
+
* Inserts an object to the Hash Map, rehashing if required, returning the new
|
4279
|
+
* object's location using a pointer.
|
4153
4280
|
*
|
4154
|
-
* If
|
4155
|
-
*
|
4281
|
+
* If an object already exists in the Hash Map with the same key, it will be
|
4282
|
+
* destroyed.
|
4156
4283
|
*
|
4157
|
-
* NOTE: This is the function's Hash Map variant. See FIO_SET_KEY_TYPE.
|
4284
|
+
* NOTE 1: This is the function's Hash Map variant. See FIO_SET_KEY_TYPE.
|
4285
|
+
*
|
4286
|
+
* NOTE 2: This is equivelant to calling the `insert2` with `old` set to NULL.
|
4158
4287
|
*/
|
4159
4288
|
FIO_FUNC inline void FIO_NAME(insert)(FIO_NAME(s) * set,
|
4160
4289
|
const FIO_SET_HASH_TYPE hash_value,
|
@@ -4162,7 +4291,24 @@ FIO_FUNC inline void FIO_NAME(insert)(FIO_NAME(s) * set,
|
|
4162
4291
|
FIO_SET_OBJ_TYPE obj);
|
4163
4292
|
|
4164
4293
|
/**
|
4165
|
-
*
|
4294
|
+
* Inserts an object to the Hash Map, rehashing if required, returning the new
|
4295
|
+
* object's location using a pointer.
|
4296
|
+
*
|
4297
|
+
* If an object already exists in the Hash Map, it will be destroyed.
|
4298
|
+
*
|
4299
|
+
* If `old` is set, the existing object (if any) will be copied to the location
|
4300
|
+
* pointed to by `old` before it is destroyed.
|
4301
|
+
*
|
4302
|
+
* NOTE: This is the function's Hash Map variant. See FIO_SET_KEY_TYPE.
|
4303
|
+
*/
|
4304
|
+
FIO_FUNC inline void FIO_NAME(insert2)(FIO_NAME(s) * set,
|
4305
|
+
const FIO_SET_HASH_TYPE hash_value,
|
4306
|
+
FIO_SET_KEY_TYPE key,
|
4307
|
+
FIO_SET_OBJ_TYPE obj,
|
4308
|
+
FIO_SET_OBJ_TYPE *old);
|
4309
|
+
|
4310
|
+
/**
|
4311
|
+
* Removes an object from the Hash Map, rehashing if required.
|
4166
4312
|
*
|
4167
4313
|
* Returns 0 on success and -1 if the object wasn't found.
|
4168
4314
|
*
|
@@ -4172,6 +4318,21 @@ FIO_FUNC inline int FIO_NAME(remove)(FIO_NAME(s) * set,
|
|
4172
4318
|
const FIO_SET_HASH_TYPE hash_value,
|
4173
4319
|
FIO_SET_KEY_TYPE key);
|
4174
4320
|
|
4321
|
+
/**
|
4322
|
+
* Removes an object from the Hash Map, rehashing if required.
|
4323
|
+
*
|
4324
|
+
* Returns 0 on success and -1 if the object wasn't found.
|
4325
|
+
*
|
4326
|
+
* If `old` is set, the existing object (if any) will be copied to the location
|
4327
|
+
* pointed to by `old`.
|
4328
|
+
*
|
4329
|
+
* NOTE: This is the function's Hash Map variant. See FIO_SET_KEY_TYPE.
|
4330
|
+
*/
|
4331
|
+
FIO_FUNC inline int FIO_NAME(remove2)(FIO_NAME(s) * set,
|
4332
|
+
const FIO_SET_HASH_TYPE hash_value,
|
4333
|
+
FIO_SET_KEY_TYPE key,
|
4334
|
+
FIO_SET_OBJ_TYPE *old);
|
4335
|
+
|
4175
4336
|
#else
|
4176
4337
|
|
4177
4338
|
/**
|
@@ -4210,6 +4371,17 @@ FIO_FUNC inline FIO_SET_OBJ_TYPE *
|
|
4210
4371
|
FIO_NAME(overwrite)(FIO_NAME(s) * set, const FIO_SET_HASH_TYPE hash_value,
|
4211
4372
|
FIO_SET_OBJ_TYPE obj);
|
4212
4373
|
|
4374
|
+
/**
|
4375
|
+
* The same as `overwrite`, only it copies the old object (if any) to the
|
4376
|
+
* location pointed to by `old`.
|
4377
|
+
*
|
4378
|
+
* When setting `old` to NULL, the function behaves the same as `overwrite`.
|
4379
|
+
*/
|
4380
|
+
FIO_FUNC FIO_SET_OBJ_TYPE *FIO_NAME(replace)(FIO_NAME(s) * set,
|
4381
|
+
const FIO_SET_HASH_TYPE hash_value,
|
4382
|
+
FIO_SET_OBJ_TYPE obj,
|
4383
|
+
FIO_SET_OBJ_TYPE *old);
|
4384
|
+
|
4213
4385
|
/**
|
4214
4386
|
* Removes an object from the Set, rehashing if required.
|
4215
4387
|
*
|
@@ -4337,7 +4509,7 @@ FIO_FUNC inline FIO_NAME(_map_s_) *
|
|
4337
4509
|
if (FIO_SET_HASH_COMPARE(FIO_SET_HASH_INVALID, pos->hash))
|
4338
4510
|
return pos;
|
4339
4511
|
if (FIO_SET_HASH_COMPARE(pos->hash, hash_value)) {
|
4340
|
-
if (!pos->pos ||
|
4512
|
+
if (!pos->pos || FIO_SET_COMPARE(pos->pos->obj, obj))
|
4341
4513
|
return pos;
|
4342
4514
|
set->has_collisions = 1;
|
4343
4515
|
}
|
@@ -4353,7 +4525,7 @@ FIO_FUNC inline FIO_NAME(_map_s_) *
|
|
4353
4525
|
if (FIO_SET_HASH_COMPARE(FIO_SET_HASH_INVALID, pos->hash))
|
4354
4526
|
return pos;
|
4355
4527
|
if (FIO_SET_HASH_COMPARE(pos->hash, hash_value)) {
|
4356
|
-
if (!pos->pos ||
|
4528
|
+
if (!pos->pos || FIO_SET_COMPARE(pos->pos->obj, obj))
|
4357
4529
|
return pos;
|
4358
4530
|
set->has_collisions = 1;
|
4359
4531
|
}
|
@@ -4407,10 +4579,9 @@ FIO_FUNC inline void FIO_NAME(_reallocate_set_mem_)(FIO_NAME(s) * set) {
|
|
4407
4579
|
* If the object already exists in the set, it will be destroyed and
|
4408
4580
|
* overwritten.
|
4409
4581
|
*/
|
4410
|
-
FIO_FUNC inline FIO_SET_TYPE *
|
4411
|
-
FIO_NAME(
|
4412
|
-
|
4413
|
-
FIO_SET_TYPE obj, int overwrite) {
|
4582
|
+
FIO_FUNC inline FIO_SET_TYPE *FIO_NAME(_insert_or_overwrite_)(
|
4583
|
+
FIO_NAME(s) * set, const FIO_SET_HASH_TYPE hash_value, FIO_SET_TYPE obj,
|
4584
|
+
int overwrite, FIO_SET_OBJ_TYPE *old) {
|
4414
4585
|
if (FIO_SET_HASH_COMPARE(hash_value, FIO_SET_HASH_INVALID))
|
4415
4586
|
return NULL;
|
4416
4587
|
|
@@ -4435,11 +4606,17 @@ FIO_NAME(_insert_or_overwrite_)(FIO_NAME(s) * set,
|
|
4435
4606
|
return &pos->pos->obj;
|
4436
4607
|
}
|
4437
4608
|
#ifdef FIO_SET_KEY_TYPE
|
4609
|
+
if (old) {
|
4610
|
+
FIO_SET_OBJ_COPY((*old), pos->pos->obj.obj);
|
4611
|
+
}
|
4438
4612
|
/* no need to recreate the key object, just the value object */
|
4439
4613
|
FIO_SET_OBJ_DESTROY(pos->pos->obj.obj);
|
4440
4614
|
FIO_SET_OBJ_COPY(pos->pos->obj.obj, obj.obj);
|
4441
4615
|
return &pos->pos->obj;
|
4442
4616
|
#else
|
4617
|
+
if (old) {
|
4618
|
+
FIO_SET_COPY((*old), pos->pos->obj);
|
4619
|
+
}
|
4443
4620
|
FIO_SET_DESTROY(pos->pos->obj);
|
4444
4621
|
#endif
|
4445
4622
|
} else {
|
@@ -4484,9 +4661,9 @@ FIO_FUNC void FIO_NAME(free)(FIO_NAME(s) * s) {
|
|
4484
4661
|
*
|
4485
4662
|
* NOTE: This is the function's Hash Map variant. See FIO_SET_KEY_TYPE.
|
4486
4663
|
*/
|
4487
|
-
FIO_FUNC
|
4488
|
-
|
4489
|
-
|
4664
|
+
FIO_FUNC FIO_SET_OBJ_TYPE *FIO_NAME(find)(FIO_NAME(s) * set,
|
4665
|
+
const FIO_SET_HASH_TYPE hash_value,
|
4666
|
+
FIO_SET_KEY_TYPE key) {
|
4490
4667
|
FIO_NAME(_map_s_) *pos =
|
4491
4668
|
FIO_NAME(_find_map_pos_)(set, hash_value, (FIO_SET_TYPE){.key = key});
|
4492
4669
|
if (!pos || !pos->pos)
|
@@ -4495,28 +4672,86 @@ FIO_NAME(find)(FIO_NAME(s) * set, const FIO_SET_HASH_TYPE hash_value,
|
|
4495
4672
|
}
|
4496
4673
|
|
4497
4674
|
/**
|
4498
|
-
* Inserts an object to the
|
4499
|
-
*
|
4675
|
+
* Inserts an object to the Hash Map, rehashing if required, returning the new
|
4676
|
+
* object's location using a pointer.
|
4500
4677
|
*
|
4501
|
-
* If the object already exists in the set,
|
4502
|
-
* object is returned).
|
4678
|
+
* If the object already exists in the set, it will be destroyed.
|
4503
4679
|
*
|
4504
4680
|
* NOTE: This is the function's Hash Map variant. See FIO_SET_KEY_TYPE.
|
4505
4681
|
*/
|
4506
|
-
FIO_FUNC
|
4682
|
+
FIO_FUNC void FIO_NAME(insert)(FIO_NAME(s) * set,
|
4683
|
+
const FIO_SET_HASH_TYPE hash_value,
|
4684
|
+
FIO_SET_KEY_TYPE key, FIO_SET_OBJ_TYPE obj) {
|
4685
|
+
FIO_NAME(_insert_or_overwrite_)
|
4686
|
+
(set, hash_value, (FIO_SET_TYPE){.key = key, .obj = obj}, 1, NULL);
|
4687
|
+
}
|
4688
|
+
|
4689
|
+
/**
|
4690
|
+
* Inserts an object to the Hash Map, rehashing if required, returning the new
|
4691
|
+
* object's location using a pointer.
|
4692
|
+
*
|
4693
|
+
* If an object already exists in the Hash Map, it will be destroyed.
|
4694
|
+
*
|
4695
|
+
* If `old` is set, the existing object (if any) will be copied to the location
|
4696
|
+
* pointed to by `old` before it is destroyed.
|
4697
|
+
*
|
4698
|
+
* NOTE: This is the function's Hash Map variant. See FIO_SET_KEY_TYPE.
|
4699
|
+
*/
|
4700
|
+
FIO_FUNC void FIO_NAME(insert2)(FIO_NAME(s) * set,
|
4701
|
+
const FIO_SET_HASH_TYPE hash_value,
|
4702
|
+
FIO_SET_KEY_TYPE key, FIO_SET_OBJ_TYPE obj,
|
4703
|
+
FIO_SET_OBJ_TYPE *old) {
|
4704
|
+
FIO_NAME(_insert_or_overwrite_)
|
4705
|
+
(set, hash_value, (FIO_SET_TYPE){.key = key, .obj = obj}, 1, old);
|
4706
|
+
}
|
4707
|
+
|
4708
|
+
/**
|
4709
|
+
* Removes an object from the Hash Map, rehashing if required.
|
4710
|
+
*
|
4711
|
+
* Returns 0 on success and -1 if the object wasn't found.
|
4712
|
+
*
|
4713
|
+
* If `old` is set, the existing object (if any) will be copied to the location
|
4714
|
+
* pointed to by `old`.
|
4715
|
+
*
|
4716
|
+
* NOTE: This is the function's Hash Map variant. See FIO_SET_KEY_TYPE.
|
4717
|
+
*/
|
4718
|
+
FIO_FUNC inline int FIO_NAME(remove2)(FIO_NAME(s) * set,
|
4507
4719
|
const FIO_SET_HASH_TYPE hash_value,
|
4508
4720
|
FIO_SET_KEY_TYPE key,
|
4509
|
-
FIO_SET_OBJ_TYPE
|
4510
|
-
|
4511
|
-
|
4721
|
+
FIO_SET_OBJ_TYPE *old) {
|
4722
|
+
if (FIO_SET_HASH_COMPARE(hash_value, FIO_SET_HASH_INVALID))
|
4723
|
+
return -1;
|
4724
|
+
FIO_NAME(_map_s_) *pos =
|
4725
|
+
FIO_NAME(_find_map_pos_)(set, hash_value, (FIO_SET_TYPE){.key = key});
|
4726
|
+
if (!pos || !pos->pos)
|
4727
|
+
return -1;
|
4728
|
+
if (old)
|
4729
|
+
FIO_SET_OBJ_COPY((*old), pos->pos->obj.obj);
|
4730
|
+
FIO_SET_DESTROY(pos->pos->obj);
|
4731
|
+
--set->count;
|
4732
|
+
pos->pos->hash = FIO_SET_HASH_INVALID;
|
4733
|
+
if (pos->pos == set->pos + set->ordered - 1) {
|
4734
|
+
do {
|
4735
|
+
--set->pos;
|
4736
|
+
} while (set->pos && FIO_SET_HASH_COMPARE(set->ordered[set->pos - 1].hash,
|
4737
|
+
FIO_SET_HASH_INVALID));
|
4738
|
+
}
|
4739
|
+
pos->pos = NULL; /* leave pos->hash set to mark "hole" */
|
4740
|
+
return 0;
|
4741
|
+
}
|
4742
|
+
|
4743
|
+
FIO_FUNC inline int FIO_NAME(remove)(FIO_NAME(s) * set,
|
4744
|
+
const FIO_SET_HASH_TYPE hash_value,
|
4745
|
+
FIO_SET_KEY_TYPE key) {
|
4746
|
+
return FIO_NAME(remove2)(set, hash_value, key, NULL);
|
4512
4747
|
}
|
4513
4748
|
|
4514
4749
|
#else
|
4515
4750
|
|
4516
4751
|
/** Locates an object in the Set, if it exists. */
|
4517
|
-
FIO_FUNC
|
4518
|
-
|
4519
|
-
|
4752
|
+
FIO_FUNC FIO_SET_OBJ_TYPE *FIO_NAME(find)(FIO_NAME(s) * set,
|
4753
|
+
const FIO_SET_HASH_TYPE hash_value,
|
4754
|
+
FIO_SET_OBJ_TYPE obj) {
|
4520
4755
|
FIO_NAME(_map_s_) *pos = FIO_NAME(_find_map_pos_)(set, hash_value, obj);
|
4521
4756
|
if (!pos || !pos->pos)
|
4522
4757
|
return NULL;
|
@@ -4530,10 +4765,10 @@ FIO_NAME(find)(FIO_NAME(s) * set, const FIO_SET_HASH_TYPE hash_value,
|
|
4530
4765
|
* If the object already exists in the set, than the new object will be
|
4531
4766
|
* destroyed and the old object's address will be returned.
|
4532
4767
|
*/
|
4533
|
-
FIO_FUNC
|
4534
|
-
|
4535
|
-
|
4536
|
-
return FIO_NAME(_insert_or_overwrite_)(set, hash_value, obj, 0);
|
4768
|
+
FIO_FUNC FIO_SET_OBJ_TYPE *FIO_NAME(insert)(FIO_NAME(s) * set,
|
4769
|
+
const FIO_SET_HASH_TYPE hash_value,
|
4770
|
+
FIO_SET_OBJ_TYPE obj) {
|
4771
|
+
return FIO_NAME(_insert_or_overwrite_)(set, hash_value, obj, 0, NULL);
|
4537
4772
|
}
|
4538
4773
|
|
4539
4774
|
/**
|
@@ -4543,35 +4778,34 @@ FIO_NAME(insert)(FIO_NAME(s) * set, const FIO_SET_HASH_TYPE hash_value,
|
|
4543
4778
|
* If the object already exists in the set, it will be destroyed and
|
4544
4779
|
* overwritten.
|
4545
4780
|
*/
|
4546
|
-
FIO_FUNC
|
4781
|
+
FIO_FUNC FIO_SET_OBJ_TYPE *
|
4547
4782
|
FIO_NAME(overwrite)(FIO_NAME(s) * set, const FIO_SET_HASH_TYPE hash_value,
|
4548
4783
|
FIO_SET_OBJ_TYPE obj) {
|
4549
|
-
return FIO_NAME(_insert_or_overwrite_)(set, hash_value, obj, 1);
|
4784
|
+
return FIO_NAME(_insert_or_overwrite_)(set, hash_value, obj, 1, NULL);
|
4550
4785
|
}
|
4551
4786
|
|
4552
|
-
|
4787
|
+
/**
|
4788
|
+
* The same as `overwrite`, only it copies the old object (if any) to the
|
4789
|
+
* location pointed to by `old`.
|
4790
|
+
*
|
4791
|
+
* When setting `old` to NULL, the function behaves the same as `overwrite`.
|
4792
|
+
*/
|
4793
|
+
FIO_FUNC FIO_SET_OBJ_TYPE *FIO_NAME(replace)(FIO_NAME(s) * set,
|
4794
|
+
const FIO_SET_HASH_TYPE hash_value,
|
4795
|
+
FIO_SET_OBJ_TYPE obj,
|
4796
|
+
FIO_SET_OBJ_TYPE *old) {
|
4797
|
+
return FIO_NAME(_insert_or_overwrite_)(set, hash_value, obj, 1, old);
|
4798
|
+
}
|
4553
4799
|
|
4554
4800
|
/**
|
4555
4801
|
* Removes an object from the Set, rehashing if required.
|
4556
4802
|
*/
|
4557
|
-
|
4558
|
-
|
4559
|
-
|
4560
|
-
const FIO_SET_HASH_TYPE hash_value,
|
4561
|
-
FIO_SET_KEY_TYPE key) {
|
4562
|
-
#else
|
4563
|
-
FIO_FUNC inline int FIO_NAME(remove)(FIO_NAME(s) * set,
|
4564
|
-
const FIO_SET_HASH_TYPE hash_value,
|
4565
|
-
FIO_SET_OBJ_TYPE obj) {
|
4566
|
-
#endif
|
4803
|
+
FIO_FUNC int FIO_NAME(remove)(FIO_NAME(s) * set,
|
4804
|
+
const FIO_SET_HASH_TYPE hash_value,
|
4805
|
+
FIO_SET_OBJ_TYPE obj) {
|
4567
4806
|
if (FIO_SET_HASH_COMPARE(hash_value, FIO_SET_HASH_INVALID))
|
4568
4807
|
return -1;
|
4569
|
-
#ifdef FIO_SET_KEY_TYPE
|
4570
|
-
FIO_NAME(_map_s_) *pos =
|
4571
|
-
FIO_NAME(_find_map_pos_)(set, hash_value, (FIO_SET_TYPE){.key = key});
|
4572
|
-
#else
|
4573
4808
|
FIO_NAME(_map_s_) *pos = FIO_NAME(_find_map_pos_)(set, hash_value, obj);
|
4574
|
-
#endif
|
4575
4809
|
if (!pos || !pos->pos)
|
4576
4810
|
return -1;
|
4577
4811
|
FIO_SET_DESTROY(pos->pos->obj);
|
@@ -4587,6 +4821,8 @@ FIO_FUNC inline int FIO_NAME(remove)(FIO_NAME(s) * set,
|
|
4587
4821
|
return 0;
|
4588
4822
|
}
|
4589
4823
|
|
4824
|
+
#endif
|
4825
|
+
|
4590
4826
|
/**
|
4591
4827
|
* Allows a peak at the Set's last element.
|
4592
4828
|
*
|
@@ -4638,7 +4874,7 @@ FIO_FUNC inline size_t FIO_NAME(capa_require)(FIO_NAME(s) * set,
|
|
4638
4874
|
if (min_capa <= FIO_NAME(capa)(set))
|
4639
4875
|
return FIO_NAME(capa)(set);
|
4640
4876
|
set->mask = 1;
|
4641
|
-
while (min_capa
|
4877
|
+
while (min_capa > set->mask) {
|
4642
4878
|
set->mask = (set->mask << 1) | 1;
|
4643
4879
|
}
|
4644
4880
|
FIO_NAME(rehash)(set);
|