summaryrefslogtreecommitdiff
path: root/util/xc_vector.h
blob: aab8a0ceed0c61a3f00555c057681ae01c505c80 (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
#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_pinit(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 inline void xc_vector_check_reserve_(xc_vector_t *vector TSRMLS_DC)
{
	if (vector->size_ == vector->capacity_) {
		if (vector->capacity_) {
			vector->capacity_ <<= 1;
			vector->data_ = perealloc(vector->data_, vector->data_size_ * vector->capacity_, vector->persistent_);
		}
		else {
			vector->capacity_ = 8;
			vector->data_ = pemalloc(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 */