~q3cpma/misc-tools

ref: 83ab8697d906e731ee6598145243b0e0909c117d misc-tools/array.h -rw-r--r-- 3.8 KiB
83ab8697q3cpma Fix a leak in array.h and add -fsanitize=leak in CONFIG=debug 3 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* Generic array with length and capacity stored in the first 2 *
 * sizeof(size_t) bytes.
 *
 * Inspired by https://github.com/eteran/c-vector, but without all the NULL
 * checking and the PTR_GARRAY functions added */
#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "misc.h"

#define GARRAY_GROWTH_FACTOR 2
#define GARRAY_START_CAPA    16

#define GARRAY_SIZE(a)       ((size_t *)(a))[-2]
#define GARRAY_CAPA(a)       ((size_t *)(a))[-1]
#define GARRAY_PTR(a)        (((size_t *)(a)) - 2)
#define GARRAY_ALLOC_SIZE(a) (sizeof(size_t) * 2 + GARRAY_CAPA(a) * sizeof(*(a)))

#define GARRAY_INIT(a)													\
	do																	\
	{																	\
	    (a) = xmalloc(sizeof(size_t) * 2 + GARRAY_START_CAPA * sizeof(*(a))); \
	    (a) = (void *) (((size_t *)(a)) + 2);							\
	    GARRAY_SIZE(a) = 0;												\
	    GARRAY_CAPA(a) = GARRAY_START_CAPA;								\
	}																	\
	while (0)

#define GARRAY_FREE(a)							\
	do                                          \
	{                                           \
	    if (a)                                  \
	        free(GARRAY_PTR(a));				\
	}                                           \
	while (0)

#define GARRAY_GROW(a)							\
	do											\
	{											\
	    (a) = xreallocarray(					\
			GARRAY_PTR(a),						\
			GARRAY_ALLOC_SIZE(a),				\
	        GARRAY_GROWTH_FACTOR				\
		);										\
	    (a) = (void *) (((size_t *)(a)) + 2);	\
	    GARRAY_CAPA(a) *= GARRAY_GROWTH_FACTOR;	\
	}											\
	while (0)

#define GARRAY_APPEND(a, e)						\
	do                                          \
	{                                           \
	    if (GARRAY_SIZE(a) == GARRAY_CAPA(a))   \
	        GARRAY_GROW(a);						\
	    (a)[GARRAY_SIZE(a)] = e;				\
	    ++GARRAY_SIZE(a);						\
	}                                           \
	while (0)

#define GARRAY_EXTEND(a, b, bnmemb)							\
	do														\
	{														\
	    while (GARRAY_CAPA(a) - GARRAY_SIZE(a) < bnmemb)	\
	        GARRAY_GROW(a);									\
	    memcpy(a + GARRAY_SIZE(a), b, bnmemb * sizeof(*b));	\
	    GARRAY_SIZE(a) += bnmemb;							\
	}														\
	while (0)

#define GARRAY_POP(a)							\
	do                                          \
	{                                           \
	    if (GARRAY_SIZE(a))						\
	        --GARRAY_SIZE(a);					\
	}                                           \
	while (0)

#define GARRAY_PRINT(stream, fmt, a)									\
	do																	\
	{																	\
	    if (GARRAY_SIZE(a))												\
	    {																\
	        for (size_t GENSYM(0) = 0; GENSYM(0) < GARRAY_SIZE(a) - 1; ++GENSYM(0)) \
	            fprintf(stream, fmt ", ", (a)[GENSYM(0)]);				\
	        fprintf(stream, fmt "\n", (a)[GARRAY_SIZE(a) - 1]);			\
	    }																\
	}																	\
	while (0)

#define PTR_GARRAY_POP(a, free)					\
	do                                          \
	{                                           \
	    if (GARRAY_SIZE(a))						\
	        free((a)[--GARRAY_SIZE(a)]);		\
	}                                           \
	while (0)

#define PTR_GARRAY_PRINT(stream, print, a)								\
	do																	\
	{																	\
	    if (GARRAY_SIZE(a))												\
	    {																\
	        for (size_t GENSYM(0) = 0; GENSYM(0) < GARRAY_SIZE(a) - 1; ++GENSYM(0)) \
	        {															\
	            print(stream, (a)[GENSYM(0)]);							\
	            fprintf(stream, ", ");									\
	        }															\
	        print(stream, (a)[GARRAY_SIZE(a) - 1]);						\
	        fprintf(stream, "\n");										\
	    }																\
	}																	\
	while (0)

#define PTR_GARRAY_FREE(a, free)										\
	do																	\
	{																	\
		for (size_t GENSYM(0) = 0; GENSYM(0) < GARRAY_SIZE(a); ++GENSYM(0)) \
			free((a)[GENSYM(0)]);										\
		GARRAY_FREE(a);													\
	}																	\
	while (0)