CVector  4.1.0
A C++ style vector library in strict ANSI C (C89)
cvector_f_struct.h
Go to the documentation of this file.
1 /*
2 
3 CVector 4.1.0 MIT Licensed vector (dynamic array) library in strict C89
4 http://www.robertwinkler.com/projects/cvector.html
5 http://www.robertwinkler.com/projects/cvector/
6 
7 Besides the docs and all the Doxygen comments, see cvector_tests.c for
8 examples of how to use it or look at any of these other projects for
9 more practical examples:
10 
11 https://github.com/rswinkle/C_Interpreter
12 https://github.com/rswinkle/CPIM2
13 https://github.com/rswinkle/spelling_game
14 https://github.com/rswinkle/c_bigint
15 http://portablegl.com/
16 
17 The MIT License (MIT)
18 
19 Copyright (c) 2011-2023 Robert Winkler
20 
21 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
22 documentation files (the "Software"), to deal in the Software without restriction, including without limitation
23 the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
24 to permit persons to whom the Software is furnished to do so, subject to the following conditions:
25 
26 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
27 
28 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
29 TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
31 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
32 IN THE SOFTWARE.
33 */
34 
35 #ifndef CVECTOR_f_struct_H
36 #define CVECTOR_f_struct_H
37 
38 #include <stdlib.h>
39 
40 #ifndef CVEC_SIZE_T
41 #define CVEC_SIZE_T size_t
42 #endif
43 
44 #ifndef CVEC_SZ
45 #define CVEC_SZ
47 #endif
48 
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52 
53 
54 typedef struct cvector_f_struct
55 {
59  void (*elem_free)(void*);
60  int (*elem_init)(void*, void*);
62 
64 
65 int cvec_f_struct(cvector_f_struct* vec, cvec_sz size, cvec_sz capacity, void(*elem_free)(void*), int(*elem_init)(void*, void*));
66 int cvec_init_f_struct(cvector_f_struct* vec, f_struct* vals, cvec_sz num, void(*elem_free)(void*), int(*elem_init)(void*, void*));
67 
68 cvector_f_struct* cvec_f_struct_heap(cvec_sz size, cvec_sz capacity, void (*elem_free)(void*), int(*elem_init)(void*, void*));
69 cvector_f_struct* cvec_init_f_struct_heap(f_struct* vals, cvec_sz num, void (*elem_free)(void*), int(*elem_init)(void*, void*));
70 
71 int cvec_copyc_f_struct(void* dest, void* src);
73 
76 
82 
93 
95 
97 void cvec_free_f_struct_heap(void* vec);
98 void cvec_free_f_struct(void* vec);
99 
100 #ifdef __cplusplus
101 }
102 #endif
103 
104 /* CVECTOR_f_struct_H */
105 #endif
106 
107 
108 #ifdef CVECTOR_f_struct_IMPLEMENTATION
109 
111 
112 #define CVEC_f_struct_ALLOCATOR(x) ((x+1) * 2)
113 
114 #if defined(CVEC_MALLOC) && defined(CVEC_FREE) && defined(CVEC_REALLOC)
115 /* ok */
116 #elif !defined(CVEC_MALLOC) && !defined(CVEC_FREE) && !defined(CVEC_REALLOC)
117 /* ok */
118 #else
119 #error "Must define all or none of CVEC_MALLOC, CVEC_FREE, and CVEC_REALLOC."
120 #endif
121 
122 #ifndef CVEC_MALLOC
123 #define CVEC_MALLOC(sz) malloc(sz)
124 #define CVEC_REALLOC(p, sz) realloc(p, sz)
125 #define CVEC_FREE(p) free(p)
126 #endif
127 
128 #ifndef CVEC_MEMMOVE
129 #include <string.h>
130 #define CVEC_MEMMOVE(dst, src, sz) memmove(dst, src, sz)
131 #endif
132 
133 #ifndef CVEC_ASSERT
134 #include <assert.h>
135 #define CVEC_ASSERT(x) assert(x)
136 #endif
137 
138 
139 /* general vector */
140 
141 cvector_f_struct* cvec_f_struct_heap(cvec_sz size, cvec_sz capacity, void(*elem_free)(void*), int(*elem_init)(void*, void*))
142 {
143  cvector_f_struct* vec;
144  if (!(vec = (cvector_f_struct*)CVEC_MALLOC(sizeof(cvector_f_struct)))) {
145  CVEC_ASSERT(vec != NULL);
146  return NULL;
147  }
148 
149  vec->size = size;
150  vec->capacity = (capacity > vec->size || (vec->size && capacity == vec->size)) ? capacity : vec->size + CVEC_f_struct_SZ;
151 
152  if (!(vec->a = (f_struct*)CVEC_MALLOC(vec->capacity * sizeof(f_struct)))) {
153  CVEC_ASSERT(vec->a != NULL);
154  CVEC_FREE(vec);
155  return NULL;
156  }
157 
158  vec->elem_free = elem_free;
159  vec->elem_init = elem_init;
160 
161  return vec;
162 }
163 
164 cvector_f_struct* cvec_init_f_struct_heap(f_struct* vals, cvec_sz num, void(*elem_free)(void*), int(*elem_init)(void*, void*))
165 {
166  cvector_f_struct* vec;
167  cvec_sz i;
168 
169  if (!(vec = (cvector_f_struct*)CVEC_MALLOC(sizeof(cvector_f_struct)))) {
170  CVEC_ASSERT(vec != NULL);
171  return NULL;
172  }
173 
174  vec->capacity = num + CVEC_f_struct_SZ;
175  vec->size = num;
176  if (!(vec->a = (f_struct*)CVEC_MALLOC(vec->capacity * sizeof(f_struct)))) {
177  CVEC_ASSERT(vec->a != NULL);
178  CVEC_FREE(vec);
179  return NULL;
180  }
181 
182  if (elem_init) {
183  for (i=0; i<num; ++i) {
184  if (!elem_init(&vec->a[i], &vals[i])) {
185  CVEC_ASSERT(0);
186  CVEC_FREE(vec->a);
187  CVEC_FREE(vec);
188  return NULL;
189  }
190  }
191  } else {
192  CVEC_MEMMOVE(vec->a, vals, sizeof(f_struct)*num);
193  }
194 
195  vec->elem_free = elem_free;
196  vec->elem_init = elem_init;
197 
198  return vec;
199 }
200 
201 int cvec_f_struct(cvector_f_struct* vec, cvec_sz size, cvec_sz capacity, void(*elem_free)(void*), int(*elem_init)(void*, void*))
202 {
203  vec->size = size;
204  vec->capacity = (capacity > vec->size || (vec->size && capacity == vec->size)) ? capacity : vec->size + CVEC_f_struct_SZ;
205 
206  if (!(vec->a = (f_struct*)CVEC_MALLOC(vec->capacity * sizeof(f_struct)))) {
207  CVEC_ASSERT(vec->a != NULL);
208  vec->size = vec->capacity = 0;
209  return 0;
210  }
211 
212  vec->elem_free = elem_free;
213  vec->elem_init = elem_init;
214 
215  return 1;
216 }
217 
218 int cvec_init_f_struct(cvector_f_struct* vec, f_struct* vals, cvec_sz num, void(*elem_free)(void*), int(*elem_init)(void*, void*))
219 {
220  cvec_sz i;
221 
222  vec->capacity = num + CVEC_f_struct_SZ;
223  vec->size = num;
224  if (!(vec->a = (f_struct*)CVEC_MALLOC(vec->capacity * sizeof(f_struct)))) {
225  CVEC_ASSERT(vec->a != NULL);
226  vec->size = vec->capacity = 0;
227  return 0;
228  }
229 
230  if (elem_init) {
231  for (i=0; i<num; ++i) {
232  if (!elem_init(&vec->a[i], &vals[i])) {
233  CVEC_ASSERT(0);
234  return 0;
235  }
236  }
237  } else {
238  CVEC_MEMMOVE(vec->a, vals, sizeof(f_struct)*num);
239  }
240 
241  vec->elem_free = elem_free;
242  vec->elem_init = elem_init;
243 
244  return 1;
245 }
246 
247 int cvec_copyc_f_struct(void* dest, void* src)
248 {
249  cvector_f_struct* vec1 = (cvector_f_struct*)dest;
250  cvector_f_struct* vec2 = (cvector_f_struct*)src;
251 
252  vec1->a = NULL;
253  vec1->size = 0;
254  vec1->capacity = 0;
255 
256  return cvec_copy_f_struct(vec1, vec2);
257 }
258 
260 {
261  int i;
262  f_struct* tmp = NULL;
263  if (!(tmp = (f_struct*)CVEC_REALLOC(dest->a, src->capacity*sizeof(f_struct)))) {
264  CVEC_ASSERT(tmp != NULL);
265  return 0;
266  }
267  dest->a = tmp;
268 
269  if (src->elem_init) {
270  for (i=0; i<src->size; ++i) {
271  if (!src->elem_init(&dest->a[i], &src->a[i])) {
272  CVEC_ASSERT(0);
273  return 0;
274  }
275  }
276  } else {
277  /* could use memcpy here since we know we just allocated dest->a */
278  CVEC_MEMMOVE(dest->a, src->a, src->size*sizeof(f_struct));
279  }
280 
281  dest->size = src->size;
282  dest->capacity = src->capacity;
283  dest->elem_free = src->elem_free;
284  dest->elem_init = src->elem_init;
285  return 1;
286 }
287 
289 {
290  f_struct* tmp;
291  cvec_sz tmp_sz;
292  if (vec->capacity == vec->size) {
293  tmp_sz = CVEC_f_struct_ALLOCATOR(vec->capacity);
294  if (!(tmp = (f_struct*)CVEC_REALLOC(vec->a, sizeof(f_struct)*tmp_sz))) {
295  CVEC_ASSERT(tmp != NULL);
296  return 0;
297  }
298  vec->a = tmp;
299  vec->capacity = tmp_sz;
300  }
301  if (vec->elem_init) {
302  if (!vec->elem_init(&vec->a[vec->size], a)) {
303  CVEC_ASSERT(0);
304  return 0;
305  }
306  } else {
307  CVEC_MEMMOVE(&vec->a[vec->size], a, sizeof(f_struct));
308  }
309 
310  vec->size++;
311  return 1;
312 }
313 
315 {
316  f_struct* tmp;
317  cvec_sz tmp_sz;
318  if (vec->capacity == vec->size) {
319  tmp_sz = CVEC_f_struct_ALLOCATOR(vec->capacity);
320  if (!(tmp = (f_struct*)CVEC_REALLOC(vec->a, sizeof(f_struct)*tmp_sz))) {
321  CVEC_ASSERT(tmp != NULL);
322  return 0;
323  }
324  vec->a = tmp;
325  vec->capacity = tmp_sz;
326  }
327  CVEC_MEMMOVE(&vec->a[vec->size], a, sizeof(f_struct));
328 
329  vec->size++;
330  return 1;
331 }
332 
334 {
335  vec->size--;
336  if (ret) {
337  CVEC_MEMMOVE(ret, &vec->a[vec->size], sizeof(f_struct));
338  }
339 
340  if (vec->elem_free) {
341  vec->elem_free(&vec->a[vec->size]);
342  }
343 }
344 
346 {
347  vec->size--;
348  if (ret) {
349  CVEC_MEMMOVE(ret, &vec->a[vec->size], sizeof(f_struct));
350  }
351 }
352 
355 {
356  return &vec->a[vec->size-1];
357 }
358 
360 {
361  f_struct* tmp;
362  cvec_sz tmp_sz;
363  if (vec->capacity < vec->size + num) {
364  tmp_sz = vec->capacity + num + CVEC_f_struct_SZ;
365  if (!(tmp = (f_struct*)CVEC_REALLOC(vec->a, sizeof(f_struct)*tmp_sz))) {
366  CVEC_ASSERT(tmp != NULL);
367  return 0;
368  }
369  vec->a = tmp;
370  vec->capacity = tmp_sz;
371  }
372 
373  vec->size += num;
374  return 1;
375 }
376 
378 {
379  f_struct* tmp;
380  cvec_sz tmp_sz;
381  if (vec->capacity == vec->size) {
382  tmp_sz = CVEC_f_struct_ALLOCATOR(vec->capacity);
383  if (!(tmp = (f_struct*)CVEC_REALLOC(vec->a, sizeof(f_struct)*tmp_sz))) {
384  CVEC_ASSERT(tmp != NULL);
385  return 0;
386  }
387 
388  vec->a = tmp;
389  vec->capacity = tmp_sz;
390  }
391  CVEC_MEMMOVE(&vec->a[i+1], &vec->a[i], (vec->size-i)*sizeof(f_struct));
392 
393  if (vec->elem_init) {
394  if (!vec->elem_init(&vec->a[i], a)) {
395  CVEC_ASSERT(0);
396  return 0;
397  }
398  } else {
399  CVEC_MEMMOVE(&vec->a[i], a, sizeof(f_struct));
400  }
401 
402  vec->size++;
403  return 1;
404 }
405 
407 {
408  f_struct* tmp;
409  cvec_sz tmp_sz;
410  if (vec->capacity == vec->size) {
411  tmp_sz = CVEC_f_struct_ALLOCATOR(vec->capacity);
412  if (!(tmp = (f_struct*)CVEC_REALLOC(vec->a, sizeof(f_struct)*tmp_sz))) {
413  CVEC_ASSERT(tmp != NULL);
414  return 0;
415  }
416 
417  vec->a = tmp;
418  vec->capacity = tmp_sz;
419  }
420  CVEC_MEMMOVE(&vec->a[i+1], &vec->a[i], (vec->size-i)*sizeof(f_struct));
421 
422  CVEC_MEMMOVE(&vec->a[i], a, sizeof(f_struct));
423 
424  vec->size++;
425  return 1;
426 }
427 
429 {
430  f_struct* tmp;
431  cvec_sz tmp_sz, j;
432  if (vec->capacity < vec->size + num) {
433  tmp_sz = vec->capacity + num + CVEC_f_struct_SZ;
434  if (!(tmp = (f_struct*)CVEC_REALLOC(vec->a, sizeof(f_struct)*tmp_sz))) {
435  CVEC_ASSERT(tmp != NULL);
436  return 0;
437  }
438  vec->a = tmp;
439  vec->capacity = tmp_sz;
440  }
441 
442  CVEC_MEMMOVE(&vec->a[i+num], &vec->a[i], (vec->size-i)*sizeof(f_struct));
443  if (vec->elem_init) {
444  for (j=0; j<num; ++j) {
445  if (!vec->elem_init(&vec->a[j+i], &a[j])) {
446  CVEC_ASSERT(0);
447  return 0;
448  }
449  }
450  } else {
451  CVEC_MEMMOVE(&vec->a[i], a, num*sizeof(f_struct));
452  }
453  vec->size += num;
454  return 1;
455 }
456 
458 {
459  f_struct* tmp;
460  cvec_sz tmp_sz;
461  if (vec->capacity < vec->size + num) {
462  tmp_sz = vec->capacity + num + CVEC_VOID_START_SZ;
463  if (!(tmp = (f_struct*)CVEC_REALLOC(vec->a, sizeof(f_struct)*tmp_sz))) {
464  CVEC_ASSERT(tmp != NULL);
465  return 0;
466  }
467  vec->a = tmp;
468  vec->capacity = tmp_sz;
469  }
470 
471  CVEC_MEMMOVE(&vec->a[i+num], &vec->a[i], (vec->size-i)*sizeof(f_struct));
472 
473  CVEC_MEMMOVE(&vec->a[i], a, num*sizeof(f_struct));
474  vec->size += num;
475  return 1;
476 }
477 
479 {
480  if (ret) {
481  CVEC_MEMMOVE(ret, &vec->a[i], sizeof(f_struct));
482  } else if (vec->elem_free) {
483  vec->elem_free(&vec->a[i]);
484  }
485 
486  if (vec->elem_init) {
487  if (!vec->elem_init(&vec->a[i], a)) {
488  CVEC_ASSERT(0);
489  return 0;
490  }
491  } else {
492  CVEC_MEMMOVE(&vec->a[i], a, sizeof(f_struct));
493  }
494  return 1;
495 }
496 
498 {
499  if (ret) {
500  CVEC_MEMMOVE(ret, &vec->a[i], sizeof(f_struct));
501  }
502 
503  CVEC_MEMMOVE(&vec->a[i], a, sizeof(f_struct));
504 }
505 
507 {
508  cvec_sz i;
509  cvec_sz d = end - start + 1;
510  if (vec->elem_free) {
511  for (i=start; i<=end; i++) {
512  vec->elem_free(&vec->a[i]);
513  }
514  }
515  CVEC_MEMMOVE(&vec->a[start], &vec->a[end+1], (vec->size-1-end)*sizeof(f_struct));
516  vec->size -= d;
517 }
518 
520 {
521  cvec_sz d = end - start + 1;
522  CVEC_MEMMOVE(&vec->a[start], &vec->a[end+1], (vec->size-1-end)*sizeof(f_struct));
523  vec->size -= d;
524 }
525 
527 {
528  f_struct* tmp;
529  if (vec->capacity < size) {
530  if (!(tmp = (f_struct*)CVEC_REALLOC(vec->a, sizeof(f_struct)*(size+CVEC_f_struct_SZ)))) {
531  CVEC_ASSERT(tmp != NULL);
532  return 0;
533  }
534  vec->a = tmp;
535  vec->capacity = size + CVEC_f_struct_SZ;
536  }
537  return 1;
538 }
539 
541 {
542  cvec_sz i;
543  f_struct* tmp;
544  if (size < vec->size) {
545  if (vec->elem_free) {
546  for (i=vec->size-1; i>=size; i--) {
547  vec->elem_free(&vec->a[i]);
548  }
549  }
550  vec->size = size;
551  }
552 
553  vec->capacity = size;
554 
555  if (!(tmp = (f_struct*)CVEC_REALLOC(vec->a, sizeof(f_struct)*size))) {
556  CVEC_ASSERT(tmp != NULL);
557  return 0;
558  }
559  vec-> a = tmp;
560  return 1;
561 }
562 
564 {
565  cvec_sz i;
566 
567  if (vec->elem_free) {
568  for(i=0; i<vec->size; i++) {
569  vec->elem_free(&vec->a[i]);
570  }
571  }
572 
573  if (vec->elem_init) {
574  for (i=0; i<vec->size; i++) {
575  if (!vec->elem_init(&vec->a[i], val)) {
576  CVEC_ASSERT(0);
577  return 0;
578  }
579  }
580  } else {
581  for (i=0; i<vec->size; i++) {
582  CVEC_MEMMOVE(&vec->a[i], val, sizeof(f_struct));
583  }
584  }
585  return 1;
586 }
587 
589 {
590  cvec_sz i;
591  if (vec->elem_free) {
592  for (i=0; i<vec->size; i++) {
593  vec->elem_free(&vec->a[i]);
594  }
595  vec->size = vec->capacity;
596  }
597 
598  if (vec->elem_init) {
599  for (i=0; i<vec->capacity; i++) {
600  if (!vec->elem_init(&vec->a[i], val)) {
601  CVEC_ASSERT(0);
602  return 0;
603  }
604  }
605  } else {
606  for (i=0; i<vec->capacity; i++) {
607  CVEC_MEMMOVE(&vec->a[i], val, sizeof(f_struct));
608  }
609  }
610  return 1;
611 }
612 
614 {
615  cvec_sz i;
616  if (vec->elem_free) {
617  for (i=0; i<vec->size; ++i) {
618  vec->elem_free(&vec->a[i]);
619  }
620  }
621  vec->size = 0;
622 }
623 
624 void cvec_free_f_struct_heap(void* vec)
625 {
626  cvec_sz i;
627  cvector_f_struct* tmp = (cvector_f_struct*)vec;
628  if (!tmp) return;
629  if (tmp->elem_free) {
630  for (i=0; i<tmp->size; i++) {
631  tmp->elem_free(&tmp->a[i]);
632  }
633  }
634  CVEC_FREE(tmp->a);
635  CVEC_FREE(tmp);
636 }
637 
638 void cvec_free_f_struct(void* vec)
639 {
640  cvec_sz i;
641  cvector_f_struct* tmp = (cvector_f_struct*)vec;
642  if (tmp->elem_free) {
643  for (i=0; i<tmp->size; i++) {
644  tmp->elem_free(&tmp->a[i]);
645  }
646  }
647 
648  CVEC_FREE(tmp->a);
649 
650  tmp->size = 0;
651  tmp->capacity = 0;
652 }
653 
654 
655 #endif
#define CVEC_FREE(p)
Definition: cvector.h:71
#define CVEC_REALLOC(p, sz)
Definition: cvector.h:70
#define CVEC_MEMMOVE(dst, src, sz)
Definition: cvector.h:76
#define CVEC_MALLOC(sz)
Definition: cvector.h:69
#define CVEC_ASSERT(x)
Definition: cvector.h:81
CVEC_SIZE_T cvec_sz
Definition: cvector.h:88
cvec_sz CVEC_VOID_START_SZ
Definition: cvector_void.c:29
int cvec_copyc_f_struct(void *dest, void *src)
int cvec_replace_f_struct(cvector_f_struct *vec, cvec_sz i, f_struct *a, f_struct *ret)
cvector_f_struct * cvec_f_struct_heap(cvec_sz size, cvec_sz capacity, void(*elem_free)(void *), int(*elem_init)(void *, void *))
int cvec_set_val_sz_f_struct(cvector_f_struct *vec, f_struct *val)
int cvec_f_struct(cvector_f_struct *vec, cvec_sz size, cvec_sz capacity, void(*elem_free)(void *), int(*elem_init)(void *, void *))
void cvec_pop_f_struct(cvector_f_struct *vec, f_struct *ret)
void cvec_erase_f_struct(cvector_f_struct *vec, cvec_sz start, cvec_sz end)
int cvec_init_f_struct(cvector_f_struct *vec, f_struct *vals, cvec_sz num, void(*elem_free)(void *), int(*elem_init)(void *, void *))
f_struct * cvec_back_f_struct(cvector_f_struct *vec)
void cvec_clear_f_struct(cvector_f_struct *vec)
void cvec_popm_f_struct(cvector_f_struct *vec, f_struct *ret)
void cvec_free_f_struct(void *vec)
int cvec_insert_array_f_struct(cvector_f_struct *vec, cvec_sz i, f_struct *a, cvec_sz num)
int cvec_copy_f_struct(cvector_f_struct *dest, cvector_f_struct *src)
int cvec_insert_f_struct(cvector_f_struct *vec, cvec_sz i, f_struct *a)
void cvec_replacem_f_struct(cvector_f_struct *vec, cvec_sz i, f_struct *a, f_struct *ret)
CVEC_SIZE_T cvec_sz
int cvec_set_cap_f_struct(cvector_f_struct *vec, cvec_sz size)
void cvec_remove_f_struct(cvector_f_struct *vec, cvec_sz start, cvec_sz end)
int cvec_insert_arraym_f_struct(cvector_f_struct *vec, cvec_sz i, f_struct *a, cvec_sz num)
int cvec_push_f_struct(cvector_f_struct *vec, f_struct *val)
cvector_f_struct * cvec_init_f_struct_heap(f_struct *vals, cvec_sz num, void(*elem_free)(void *), int(*elem_init)(void *, void *))
int cvec_set_val_cap_f_struct(cvector_f_struct *vec, f_struct *val)
int cvec_extend_f_struct(cvector_f_struct *vec, cvec_sz num)
int cvec_pushm_f_struct(cvector_f_struct *vec, f_struct *a)
void cvec_free_f_struct_heap(void *vec)
cvec_sz CVEC_f_struct_SZ
#define CVEC_SIZE_T
int cvec_reserve_f_struct(cvector_f_struct *vec, cvec_sz size)
int cvec_insertm_f_struct(cvector_f_struct *vec, cvec_sz i, f_struct *a)
void(* elem_free)(void *)
int(* elem_init)(void *, void *)
Structure used to test generic vector.
Definition: test_types.h:14