summaryrefslogtreecommitdiff
path: root/util/xc_vector.h
blob: 15e9ef7d2d2317e1d53b6895fd2999760b67ecd3 (plain)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#ifndef XC_VECTOR_H_0957AC4E1A44E838C7B8DBECFF9C4B3B
#define XC_VECTOR_H_0957AC4E1A44E838C7B8DBECFF9C4B3B

#if _MSC_VER > 1000
#pragma once
#endif /* _MSC_VER > 1000 */

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

typedef struct {
	void *data_;
	size_t size_;
	size_t capacity_;

	size_t data_size_;
	int persistent_;
} xc_vector_t;

#define xc_vector_initializer(type, persistent) { \
	NULL, \
	0, \
	0, \
\
	sizeof(type), \
	persistent, \
}

#define xc_vector_init_ex(type, vector, data, size, persistent) do { \
	(vector)->data_ = data; \
	(vector)->size_ = (vector)->capacity_ = size; \
	(vector)->data_size_ = sizeof(type); \
	(vector)->persistent_ = persistent; \
} while (0)

#define xc_vector_init(type, vector) xc_vector_init_ex(type, vector, NULL, 0, 0)
#define xc_vector_init_persistent(type, vector) xc_vector_init_ex(type, vector, NULL, 0, 1)

static inline void xc_vector_destroy_impl(xc_vector_t *vector TSRMLS_DC)
{
	vector->size_ = 0;
	if (vector->data_) {
		pefree(vector->data_, vector->persistent_);
		vector->data_ = NULL;
	}
	vector->capacity_ = 0;
	vector->data_size_ = 0;
}

#define xc_vector_destroy(vector) xc_vector_destroy_impl(vector TSRMLS_CC)
#define xc_vector_clear(vector) do { (vector)->size_ = 0; } while (0)

#define xc_vector_size(vector) ((vector)->size_)
#define xc_vector_initialized(vector) ((vector)->data_size_ != 0)
#define xc_vector_element_ptr_(vector, index) ( \
	(void *) ( \
		((char *) (vector)->data_) + (index) * (vector)->data_size_ \
	) \
)

static inline xc_vector_t *xc_vector_check_type_(xc_vector_t *vector, size_t data_size)
{
	assert(vector->data_size_ = data_size);
	return vector;
}

#define xc_vector_data(type, vector) ((type *) xc_vector_check_type_(vector, sizeof(type))->data_)

static void xc_vector_reserve_impl(xc_vector_t *vector, size_t capacity TSRMLS_DC)
{
	assert(capacity);
	if (!vector->capacity_) {
		vector->capacity_ = 8;
	}
	while (vector->capacity_ <= capacity) {
		vector->capacity_ <<= 1;
	}
	vector->data_ = perealloc(vector->data_, vector->data_size_ * vector->capacity_, vector->persistent_);
}
#define xc_vector_reserve(vector, capacity) xc_vector_reserve_impl(vector, capacity TSRMLS_CC)

static void xc_vector_resize_impl(xc_vector_t *vector, size_t size TSRMLS_DC)
{
	assert(size);
	xc_vector_reserve(vector, size);
	vector->size_ = size;
}
#define xc_vector_resize(vector, size) xc_vector_resize_impl(vector, size TSRMLS_CC)

static inline void xc_vector_check_reserve_(xc_vector_t *vector TSRMLS_DC)
{
	if (vector->size_ == vector->capacity_) {
		if (vector->capacity_) {
			vector->capacity_ <<= 1;
		}
		else {
			vector->capacity_ = 8;
		}
		vector->data_ = perealloc(vector->data_, vector->data_size_ * vector->capacity_, vector->persistent_);
	}
}

#define xc_vector_push_back(vector, value_ptr) do { \
	xc_vector_check_reserve_(vector TSRMLS_CC); \
	memcpy(xc_vector_element_ptr_(vector, (vector)->size_++), value_ptr, (vector)->data_size_); \
} while (0)

static inline void *xc_vector_detach_impl(xc_vector_t *vector)
{
	void *data = vector->data_;

	vector->data_ = NULL;
	vector->capacity_ = 0;
	vector->size_ = 0;
	return data;
}

#define xc_vector_detach(type, vector) ((type *) xc_vector_detach_impl(xc_vector_check_type_(vector, sizeof(type))))

static inline xc_vector_t *xc_vector_pop_back_check_(xc_vector_t *vector, size_t data_size)
{
	assert(vector);
	assert(vector->data_size_ == data_size);
	assert(vector->capacity_ > 0);
	return vector;
}

#define xc_vector_pop_back(type, vector) xc_vector_data(type, \
	xc_vector_pop_back_check_(vector, sizeof(type)) \
)[--(vector)->size_]

static inline void xc_vector_reverse(xc_vector_t *vector)
{
	char *left, *right;
	void *tmp;

	assert(vector);
	assert(vector->data_size_);
	tmp = alloca(vector->data_size_);
	for (left = vector->data_, right = xc_vector_element_ptr_(vector, vector->size_ - 1); left < right; left += vector->data_size_, right -= vector->data_size_) {
		memcpy(tmp, left, vector->data_size_);
		memcpy(left, right, vector->data_size_);
		memcpy(right, tmp, vector->data_size_);
	}
}

#endif /* XC_VECTOR_H_0957AC4E1A44E838C7B8DBECFF9C4B3B */