mathematical 1.6.20 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2007-2016, Troy D. Hanson http://troydhanson.github.com/uthash/
2
+ Copyright (c) 2007-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
3
3
  All rights reserved.
4
4
 
5
5
  Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
24
  #ifndef UTLIST_H
25
25
  #define UTLIST_H
26
26
 
27
- #define UTLIST_VERSION 2.0.1
27
+ #define UTLIST_VERSION 2.3.0
28
28
 
29
29
  #include <assert.h>
30
30
 
@@ -61,19 +61,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61
61
 
62
62
  /* These macros use decltype or the earlier __typeof GNU extension.
63
63
  As decltype is only available in newer compilers (VS2010 or gcc 4.3+
64
- when compiling c++ code), this code uses whatever method is needed
64
+ when compiling c++ source) this code uses whatever method is needed
65
65
  or, for VS2008 where neither is available, uses casting workarounds. */
66
- #ifdef _MSC_VER /* MS compiler */
66
+ #if !defined(LDECLTYPE) && !defined(NO_DECLTYPE)
67
+ #if defined(_MSC_VER) /* MS compiler */
67
68
  #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
68
69
  #define LDECLTYPE(x) decltype(x)
69
- #else /* VS2008 or older (or VS2010 in C mode) */
70
+ #else /* VS2008 or older (or VS2010 in C mode) */
70
71
  #define NO_DECLTYPE
71
72
  #endif
72
- #elif defined(__ICCARM__)
73
+ #elif defined(__MCST__) /* Elbrus C Compiler */
74
+ #define LDECLTYPE(x) __typeof(x)
75
+ #elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
73
76
  #define NO_DECLTYPE
74
- #else /* GNU, Sun and other compilers */
77
+ #else /* GNU, Sun and other compilers */
75
78
  #define LDECLTYPE(x) __typeof(x)
76
79
  #endif
80
+ #endif
77
81
 
78
82
  /* for VS2008 we use some workarounds to get around the lack of decltype,
79
83
  * namely, we always reassign our tmp variable to the list head if we need
@@ -81,22 +85,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
81
85
  #ifdef NO_DECLTYPE
82
86
  #define IF_NO_DECLTYPE(x) x
83
87
  #define LDECLTYPE(x) char*
84
- #define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
85
- #define _NEXT(elt,list,next) ((char*)((list)->next))
86
- #define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
87
- /* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
88
- #define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
89
- #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
90
- #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
88
+ #define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
89
+ #define UTLIST_NEXT(elt,list,next) ((char*)((list)->next))
90
+ #define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
91
+ /* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */
92
+ #define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
93
+ #define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
94
+ #define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
91
95
  #else
92
96
  #define IF_NO_DECLTYPE(x)
93
- #define _SV(elt,list)
94
- #define _NEXT(elt,list,next) ((elt)->next)
95
- #define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
96
- /* #define _PREV(elt,list,prev) ((elt)->prev) */
97
- #define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
98
- #define _RS(list)
99
- #define _CASTASGN(a,b) (a)=(b)
97
+ #define UTLIST_SV(elt,list)
98
+ #define UTLIST_NEXT(elt,list,next) ((elt)->next)
99
+ #define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
100
+ /* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */
101
+ #define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
102
+ #define UTLIST_RS(list)
103
+ #define UTLIST_CASTASGN(a,b) (a)=(b)
100
104
  #endif
101
105
 
102
106
  /******************************************************************************
@@ -118,7 +122,7 @@ do {
118
122
  _ls_insize = 1; \
119
123
  _ls_looping = 1; \
120
124
  while (_ls_looping) { \
121
- _CASTASGN(_ls_p,list); \
125
+ UTLIST_CASTASGN(_ls_p,list); \
122
126
  (list) = NULL; \
123
127
  _ls_tail = NULL; \
124
128
  _ls_nmerges = 0; \
@@ -128,35 +132,35 @@ do {
128
132
  _ls_psize = 0; \
129
133
  for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
130
134
  _ls_psize++; \
131
- _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
135
+ UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \
132
136
  if (!_ls_q) break; \
133
137
  } \
134
138
  _ls_qsize = _ls_insize; \
135
139
  while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
136
140
  if (_ls_psize == 0) { \
137
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
138
- _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
141
+ _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
142
+ UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
139
143
  } else if (_ls_qsize == 0 || !_ls_q) { \
140
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
141
- _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
144
+ _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
145
+ UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
142
146
  } else if (cmp(_ls_p,_ls_q) <= 0) { \
143
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
144
- _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
147
+ _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
148
+ UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
145
149
  } else { \
146
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
147
- _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
150
+ _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
151
+ UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
148
152
  } \
149
153
  if (_ls_tail) { \
150
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
154
+ UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
151
155
  } else { \
152
- _CASTASGN(list,_ls_e); \
156
+ UTLIST_CASTASGN(list,_ls_e); \
153
157
  } \
154
158
  _ls_tail = _ls_e; \
155
159
  } \
156
160
  _ls_p = _ls_q; \
157
161
  } \
158
162
  if (_ls_tail) { \
159
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
163
+ UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \
160
164
  } \
161
165
  if (_ls_nmerges <= 1) { \
162
166
  _ls_looping=0; \
@@ -182,7 +186,7 @@ do {
182
186
  _ls_insize = 1; \
183
187
  _ls_looping = 1; \
184
188
  while (_ls_looping) { \
185
- _CASTASGN(_ls_p,list); \
189
+ UTLIST_CASTASGN(_ls_p,list); \
186
190
  (list) = NULL; \
187
191
  _ls_tail = NULL; \
188
192
  _ls_nmerges = 0; \
@@ -192,36 +196,36 @@ do {
192
196
  _ls_psize = 0; \
193
197
  for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
194
198
  _ls_psize++; \
195
- _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
199
+ UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \
196
200
  if (!_ls_q) break; \
197
201
  } \
198
202
  _ls_qsize = _ls_insize; \
199
203
  while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \
200
204
  if (_ls_psize == 0) { \
201
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
202
- _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
205
+ _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
206
+ UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
203
207
  } else if ((_ls_qsize == 0) || (!_ls_q)) { \
204
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
205
- _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
208
+ _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
209
+ UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
206
210
  } else if (cmp(_ls_p,_ls_q) <= 0) { \
207
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
208
- _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
211
+ _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
212
+ UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
209
213
  } else { \
210
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
211
- _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
214
+ _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
215
+ UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
212
216
  } \
213
217
  if (_ls_tail) { \
214
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
218
+ UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
215
219
  } else { \
216
- _CASTASGN(list,_ls_e); \
220
+ UTLIST_CASTASGN(list,_ls_e); \
217
221
  } \
218
- _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
222
+ UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \
219
223
  _ls_tail = _ls_e; \
220
224
  } \
221
225
  _ls_p = _ls_q; \
222
226
  } \
223
- _CASTASGN((list)->prev, _ls_tail); \
224
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
227
+ UTLIST_CASTASGN((list)->prev, _ls_tail); \
228
+ UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \
225
229
  if (_ls_nmerges <= 1) { \
226
230
  _ls_looping=0; \
227
231
  } \
@@ -246,8 +250,8 @@ do {
246
250
  _ls_insize = 1; \
247
251
  _ls_looping = 1; \
248
252
  while (_ls_looping) { \
249
- _CASTASGN(_ls_p,list); \
250
- _CASTASGN(_ls_oldhead,list); \
253
+ UTLIST_CASTASGN(_ls_p,list); \
254
+ UTLIST_CASTASGN(_ls_oldhead,list); \
251
255
  (list) = NULL; \
252
256
  _ls_tail = NULL; \
253
257
  _ls_nmerges = 0; \
@@ -257,47 +261,47 @@ do {
257
261
  _ls_psize = 0; \
258
262
  for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
259
263
  _ls_psize++; \
260
- _SV(_ls_q,list); \
261
- if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \
264
+ UTLIST_SV(_ls_q,list); \
265
+ if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \
262
266
  _ls_q = NULL; \
263
267
  } else { \
264
- _ls_q = _NEXT(_ls_q,list,next); \
268
+ _ls_q = UTLIST_NEXT(_ls_q,list,next); \
265
269
  } \
266
- _RS(list); \
270
+ UTLIST_RS(list); \
267
271
  if (!_ls_q) break; \
268
272
  } \
269
273
  _ls_qsize = _ls_insize; \
270
274
  while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
271
275
  if (_ls_psize == 0) { \
272
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
273
- _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
276
+ _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
277
+ UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
274
278
  if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
275
279
  } else if (_ls_qsize == 0 || !_ls_q) { \
276
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
277
- _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
280
+ _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
281
+ UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
278
282
  if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
279
283
  } else if (cmp(_ls_p,_ls_q) <= 0) { \
280
- _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
281
- _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
284
+ _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
285
+ UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
282
286
  if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
283
287
  } else { \
284
- _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
285
- _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
288
+ _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
289
+ UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
286
290
  if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
287
291
  } \
288
292
  if (_ls_tail) { \
289
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
293
+ UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
290
294
  } else { \
291
- _CASTASGN(list,_ls_e); \
295
+ UTLIST_CASTASGN(list,_ls_e); \
292
296
  } \
293
- _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
297
+ UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \
294
298
  _ls_tail = _ls_e; \
295
299
  } \
296
300
  _ls_p = _ls_q; \
297
301
  } \
298
- _CASTASGN((list)->prev,_ls_tail); \
299
- _CASTASGN(_tmp,list); \
300
- _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \
302
+ UTLIST_CASTASGN((list)->prev,_ls_tail); \
303
+ UTLIST_CASTASGN(_tmp,list); \
304
+ UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list); \
301
305
  if (_ls_nmerges <= 1) { \
302
306
  _ls_looping=0; \
303
307
  } \
@@ -349,6 +353,37 @@ do {
349
353
  } \
350
354
  } while (0)
351
355
 
356
+ #define LL_INSERT_INORDER(head,add,cmp) \
357
+ LL_INSERT_INORDER2(head,add,cmp,next)
358
+
359
+ #define LL_INSERT_INORDER2(head,add,cmp,next) \
360
+ do { \
361
+ LDECLTYPE(head) _tmp; \
362
+ if (head) { \
363
+ LL_LOWER_BOUND2(head, _tmp, add, cmp, next); \
364
+ LL_APPEND_ELEM2(head, _tmp, add, next); \
365
+ } else { \
366
+ (head) = (add); \
367
+ (head)->next = NULL; \
368
+ } \
369
+ } while (0)
370
+
371
+ #define LL_LOWER_BOUND(head,elt,like,cmp) \
372
+ LL_LOWER_BOUND2(head,elt,like,cmp,next)
373
+
374
+ #define LL_LOWER_BOUND2(head,elt,like,cmp,next) \
375
+ do { \
376
+ if ((head) == NULL || (cmp(head, like)) >= 0) { \
377
+ (elt) = NULL; \
378
+ } else { \
379
+ for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \
380
+ if (cmp((elt)->next, like) >= 0) { \
381
+ break; \
382
+ } \
383
+ } \
384
+ } \
385
+ } while (0)
386
+
352
387
  #define LL_DELETE(head,del) \
353
388
  LL_DELETE2(head,del,next)
354
389
 
@@ -484,7 +519,7 @@ do {
484
519
  _tmp = (char*)(head1); \
485
520
  while ((head1)->next) { (head1) = (head1)->next; } \
486
521
  (head1)->next = (head2); \
487
- _RS(head1); \
522
+ UTLIST_RS(head1); \
488
523
  } else { \
489
524
  (head1)=(head2); \
490
525
  } \
@@ -503,6 +538,23 @@ do {
503
538
  (add)->next=NULL; \
504
539
  } while (0)
505
540
 
541
+ #undef LL_INSERT_INORDER2
542
+ #define LL_INSERT_INORDER2(head,add,cmp,next) \
543
+ do { \
544
+ if ((head) == NULL || (cmp(head, add)) >= 0) { \
545
+ (add)->next = (head); \
546
+ (head) = (add); \
547
+ } else { \
548
+ char *_tmp = (char*)(head); \
549
+ while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \
550
+ (head) = (head)->next; \
551
+ } \
552
+ (add)->next = (head)->next; \
553
+ (head)->next = (add); \
554
+ UTLIST_RS(head); \
555
+ } \
556
+ } while (0)
557
+
506
558
  #undef LL_DELETE2
507
559
  #define LL_DELETE2(head,del,next) \
508
560
  do { \
@@ -516,7 +568,7 @@ do {
516
568
  if ((head)->next) { \
517
569
  (head)->next = ((del)->next); \
518
570
  } \
519
- _RS(head); \
571
+ UTLIST_RS(head); \
520
572
  } \
521
573
  } while (0)
522
574
 
@@ -600,6 +652,38 @@ do {
600
652
  } \
601
653
  } while (0)
602
654
 
655
+ #define DL_INSERT_INORDER(head,add,cmp) \
656
+ DL_INSERT_INORDER2(head,add,cmp,prev,next)
657
+
658
+ #define DL_INSERT_INORDER2(head,add,cmp,prev,next) \
659
+ do { \
660
+ LDECLTYPE(head) _tmp; \
661
+ if (head) { \
662
+ DL_LOWER_BOUND2(head, _tmp, add, cmp, next); \
663
+ DL_APPEND_ELEM2(head, _tmp, add, prev, next); \
664
+ } else { \
665
+ (head) = (add); \
666
+ (head)->prev = (head); \
667
+ (head)->next = NULL; \
668
+ } \
669
+ } while (0)
670
+
671
+ #define DL_LOWER_BOUND(head,elt,like,cmp) \
672
+ DL_LOWER_BOUND2(head,elt,like,cmp,next)
673
+
674
+ #define DL_LOWER_BOUND2(head,elt,like,cmp,next) \
675
+ do { \
676
+ if ((head) == NULL || (cmp(head, like)) >= 0) { \
677
+ (elt) = NULL; \
678
+ } else { \
679
+ for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \
680
+ if ((cmp((elt)->next, like)) >= 0) { \
681
+ break; \
682
+ } \
683
+ } \
684
+ } \
685
+ } while (0)
686
+
603
687
  #define DL_CONCAT(head1,head2) \
604
688
  DL_CONCAT2(head1,head2,prev,next)
605
689
 
@@ -608,10 +692,10 @@ do {
608
692
  LDECLTYPE(head1) _tmp; \
609
693
  if (head2) { \
610
694
  if (head1) { \
611
- _CASTASGN(_tmp, (head2)->prev); \
695
+ UTLIST_CASTASGN(_tmp, (head2)->prev); \
612
696
  (head2)->prev = (head1)->prev; \
613
697
  (head1)->prev->next = (head2); \
614
- _CASTASGN((head1)->prev, _tmp); \
698
+ UTLIST_CASTASGN((head1)->prev, _tmp); \
615
699
  } else { \
616
700
  (head1)=(head2); \
617
701
  } \
@@ -623,10 +707,12 @@ do {
623
707
 
624
708
  #define DL_DELETE2(head,del,prev,next) \
625
709
  do { \
710
+ assert((head) != NULL); \
626
711
  assert((del)->prev != NULL); \
627
712
  if ((del)->prev == (del)) { \
628
713
  (head)=NULL; \
629
- } else if ((del)==(head)) { \
714
+ } else if ((del) == (head)) { \
715
+ assert((del)->next != NULL); \
630
716
  (del)->next->prev = (del)->prev; \
631
717
  (head) = (del)->next; \
632
718
  } else { \
@@ -738,6 +824,39 @@ do {
738
824
  #define DL_APPEND_ELEM(head, el, add) \
739
825
  DL_APPEND_ELEM2(head, el, add, prev, next)
740
826
 
827
+ #ifdef NO_DECLTYPE
828
+ /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
829
+
830
+ #undef DL_INSERT_INORDER2
831
+ #define DL_INSERT_INORDER2(head,add,cmp,prev,next) \
832
+ do { \
833
+ if ((head) == NULL) { \
834
+ (add)->prev = (add); \
835
+ (add)->next = NULL; \
836
+ (head) = (add); \
837
+ } else if ((cmp(head, add)) >= 0) { \
838
+ (add)->prev = (head)->prev; \
839
+ (add)->next = (head); \
840
+ (head)->prev = (add); \
841
+ (head) = (add); \
842
+ } else { \
843
+ char *_tmp = (char*)(head); \
844
+ while ((head)->next && (cmp((head)->next, add)) < 0) { \
845
+ (head) = (head)->next; \
846
+ } \
847
+ (add)->prev = (head); \
848
+ (add)->next = (head)->next; \
849
+ (head)->next = (add); \
850
+ UTLIST_RS(head); \
851
+ if ((add)->next) { \
852
+ (add)->next->prev = (add); \
853
+ } else { \
854
+ (head)->prev = (add); \
855
+ } \
856
+ } \
857
+ } while (0)
858
+ #endif /* NO_DECLTYPE */
859
+
741
860
  /******************************************************************************
742
861
  * circular doubly linked list macros *
743
862
  *****************************************************************************/
@@ -775,6 +894,38 @@ do {
775
894
  (head) = (add); \
776
895
  } while (0)
777
896
 
897
+ #define CDL_INSERT_INORDER(head,add,cmp) \
898
+ CDL_INSERT_INORDER2(head,add,cmp,prev,next)
899
+
900
+ #define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \
901
+ do { \
902
+ LDECLTYPE(head) _tmp; \
903
+ if (head) { \
904
+ CDL_LOWER_BOUND2(head, _tmp, add, cmp, next); \
905
+ CDL_APPEND_ELEM2(head, _tmp, add, prev, next); \
906
+ } else { \
907
+ (head) = (add); \
908
+ (head)->next = (head); \
909
+ (head)->prev = (head); \
910
+ } \
911
+ } while (0)
912
+
913
+ #define CDL_LOWER_BOUND(head,elt,like,cmp) \
914
+ CDL_LOWER_BOUND2(head,elt,like,cmp,next)
915
+
916
+ #define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \
917
+ do { \
918
+ if ((head) == NULL || (cmp(head, like)) >= 0) { \
919
+ (elt) = NULL; \
920
+ } else { \
921
+ for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \
922
+ if ((cmp((elt)->next, like)) >= 0) { \
923
+ break; \
924
+ } \
925
+ } \
926
+ } \
927
+ } while (0)
928
+
778
929
  #define CDL_DELETE(head,del) \
779
930
  CDL_DELETE2(head,del,prev,next)
780
931
 
@@ -892,4 +1043,34 @@ do {
892
1043
  #define CDL_APPEND_ELEM(head, el, add) \
893
1044
  CDL_APPEND_ELEM2(head, el, add, prev, next)
894
1045
 
1046
+ #ifdef NO_DECLTYPE
1047
+ /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
1048
+
1049
+ #undef CDL_INSERT_INORDER2
1050
+ #define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \
1051
+ do { \
1052
+ if ((head) == NULL) { \
1053
+ (add)->prev = (add); \
1054
+ (add)->next = (add); \
1055
+ (head) = (add); \
1056
+ } else if ((cmp(head, add)) >= 0) { \
1057
+ (add)->prev = (head)->prev; \
1058
+ (add)->next = (head); \
1059
+ (add)->prev->next = (add); \
1060
+ (head)->prev = (add); \
1061
+ (head) = (add); \
1062
+ } else { \
1063
+ char *_tmp = (char*)(head); \
1064
+ while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \
1065
+ (head) = (head)->next; \
1066
+ } \
1067
+ (add)->prev = (head); \
1068
+ (add)->next = (head)->next; \
1069
+ (add)->next->prev = (add); \
1070
+ (head)->next = (add); \
1071
+ UTLIST_RS(head); \
1072
+ } \
1073
+ } while (0)
1074
+ #endif /* NO_DECLTYPE */
1075
+
895
1076
  #endif /* UTLIST_H */
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2008-2016, Troy D. Hanson http://troydhanson.github.com/uthash/
2
+ Copyright (c) 2015-2022, Troy D. Hanson https://troydhanson.github.io/uthash/
3
3
  All rights reserved.
4
4
 
5
5
  Redistribution and use in source and binary forms, with or without
@@ -26,12 +26,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
26
  #ifndef UTRINGBUFFER_H
27
27
  #define UTRINGBUFFER_H
28
28
 
29
- #define UTRINGBUFFER_VERSION 2.0.1
30
-
29
+ #define UTRINGBUFFER_VERSION 2.3.0
30
+
31
31
  #include <stdlib.h>
32
32
  #include <string.h>
33
33
  #include "utarray.h" // for "UT_icd"
34
-
34
+
35
35
  typedef struct {
36
36
  unsigned i; /* index of next available slot; wraps at n */
37
37
  unsigned n; /* capacity */
@@ -39,14 +39,14 @@ typedef struct {
39
39
  UT_icd icd; /* initializer, copy and destructor functions */
40
40
  char *d; /* n slots of size icd->sz */
41
41
  } UT_ringbuffer;
42
-
42
+
43
43
  #define utringbuffer_init(a, _n, _icd) do { \
44
44
  memset(a, 0, sizeof(UT_ringbuffer)); \
45
45
  (a)->icd = *(_icd); \
46
46
  (a)->n = (_n); \
47
47
  if ((a)->n) { (a)->d = (char*)malloc((a)->n * (_icd)->sz); } \
48
48
  } while(0)
49
-
49
+
50
50
  #define utringbuffer_clear(a) do { \
51
51
  if ((a)->icd.dtor) { \
52
52
  if ((a)->f) { \
@@ -64,42 +64,42 @@ typedef struct {
64
64
  (a)->i = 0; \
65
65
  (a)->f = 0; \
66
66
  } while(0)
67
-
67
+
68
68
  #define utringbuffer_done(a) do { \
69
69
  utringbuffer_clear(a); \
70
70
  free((a)->d); (a)->d = NULL; \
71
71
  (a)->n = 0; \
72
72
  } while(0)
73
-
73
+
74
74
  #define utringbuffer_new(a,n,_icd) do { \
75
75
  a = (UT_ringbuffer*)malloc(sizeof(UT_ringbuffer)); \
76
76
  utringbuffer_init(a, n, _icd); \
77
77
  } while(0)
78
-
78
+
79
79
  #define utringbuffer_free(a) do { \
80
80
  utringbuffer_done(a); \
81
81
  free(a); \
82
82
  } while(0)
83
-
83
+
84
84
  #define utringbuffer_push_back(a,p) do { \
85
85
  if ((a)->icd.dtor && (a)->f) { (a)->icd.dtor(_utringbuffer_internalptr(a,(a)->i)); } \
86
86
  if ((a)->icd.copy) { (a)->icd.copy( _utringbuffer_internalptr(a,(a)->i), p); } \
87
87
  else { memcpy(_utringbuffer_internalptr(a,(a)->i), p, (a)->icd.sz); }; \
88
88
  if (++(a)->i == (a)->n) { (a)->i = 0; (a)->f = 1; } \
89
89
  } while(0)
90
-
90
+
91
91
  #define utringbuffer_len(a) ((a)->f ? (a)->n : (a)->i)
92
92
  #define utringbuffer_empty(a) ((a)->i == 0 && !(a)->f)
93
93
  #define utringbuffer_full(a) ((a)->f != 0)
94
-
94
+
95
95
  #define _utringbuffer_real_idx(a,j) ((a)->f ? ((j) + (a)->i) % (a)->n : (j))
96
96
  #define _utringbuffer_internalptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j))))
97
97
  #define utringbuffer_eltptr(a,j) ((0 <= (j) && (j) < utringbuffer_len(a)) ? _utringbuffer_internalptr(a,_utringbuffer_real_idx(a,j)) : NULL)
98
-
98
+
99
99
  #define _utringbuffer_fake_idx(a,j) ((a)->f ? ((j) + (a)->n - (a)->i) % (a)->n : (j))
100
100
  #define _utringbuffer_internalidx(a,e) (((char*)(e) >= (a)->d) ? (((char*)(e) - (a)->d)/(a)->icd.sz) : -1)
101
101
  #define utringbuffer_eltidx(a,e) _utringbuffer_fake_idx(a, _utringbuffer_internalidx(a,e))
102
-
102
+
103
103
  #define utringbuffer_front(a) utringbuffer_eltptr(a,0)
104
104
  #define utringbuffer_next(a,e) ((e)==NULL ? utringbuffer_front(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)+1))
105
105
  #define utringbuffer_prev(a,e) ((e)==NULL ? utringbuffer_back(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)-1))