-
Notifications
You must be signed in to change notification settings - Fork 35
/
dyn0dyn.inl
219 lines (165 loc) · 3.97 KB
/
dyn0dyn.inl
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#define DYN_BLOCK_MAGIC_N 375767
#define DYN_BLOCK_FULL_FLAG 0x1000000
dyn_block_t* dyn_array_add_block(dyn_array_t* arr);
UNIV_INLINE dyn_block_t* dyn_array_get_first_block(dyn_array_t* arr)
{
return arr;
}
UNIV_INLINE dyn_block_t* dyn_array_get_last_block(dyn_array_t* arr)
{
if(arr->heap == NULL)
return arr;
return UT_LIST_GET_LAST(arr->base);
}
UNIV_INLINE dyn_block_t* dyn_array_get_next_block(dyn_array_t* arr, dyn_block_t* block)
{
ut_ad(arr && block);
if(arr->heap == NULL){
ut_ad(arr == block);
return NULL;
}
return UT_LIST_GET_NEXT(list, block);
}
UNIV_INLINE ulint dyn_block_get_used(dyn_block_t* block)
{
ut_ad(block);
return ((block->used) & ~DYN_BLOCK_FULL_FLAG);
}
UNIV_INLINE byte* dyn_block_get_data(dyn_block_t* block)
{
ut_ad(block);
return block->data;
}
UNIV_INLINE dyn_array_t* dyn_array_create(dyn_array_t* arr)
{
ut_ad(arr);
ut_ad(DYN_ARRAY_DATA_SIZE < DYN_BLOCK_FULL_FLAG);
arr->heap = NULL;
arr->used = 0;
#ifdef UNIV_DEBUG
arr->buf_end = 0;
arr->magic_n = DYN_BLOCK_MAGIC_N;
#endif
return arr;
}
UNIV_INLINE void dyn_array_free(dyn_array_t* arr)
{
if(arr->heap != NULL)
mem_heap_free(arr->heap);
#ifdef UNIV_DEBUG
arr->magic_n = 0;
#endif
}
UNIV_INLINE void* dyn_array_push(dyn_array_t* arr, ulint size)
{
dyn_block_t* block;
ulint used;
ut_ad(arr);
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
ut_ad(size <= DYN_ARRAY_DATA_SIZE);
ut_ad(size);
block = arr;
used = block->used;
if (used + size > DYN_ARRAY_DATA_SIZE) {
/* Get the last array block */
block = dyn_array_get_last_block(arr);
used = block->used;
if (used + size > DYN_ARRAY_DATA_SIZE) {
block = dyn_array_add_block(arr);
used = block->used;
}
}
block->used = used + size;
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
return((block->data) + used);
}
UNIV_INLINE byte* dyn_array_open(dyn_array_t* arr, ulint size)
{
dyn_block_t* block;
ulint used;
ut_ad(arr);
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
ut_ad(size <= DYN_ARRAY_DATA_SIZE);
ut_ad(size);
block = arr;
used = block->used;
if (used + size > DYN_ARRAY_DATA_SIZE) {
/* Get the last array block */
block = dyn_array_get_last_block(arr);
used = block->used;
if (used + size > DYN_ARRAY_DATA_SIZE) {
block = dyn_array_add_block(arr);
used = block->used;
ut_a(size <= DYN_ARRAY_DATA_SIZE);
}
}
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
#ifdef UNIV_DEBUG
ut_ad(arr->buf_end == 0);
arr->buf_end = user + size;
#endif
return ((block->data) + used);
}
UNIV_INLINE void dyn_array_close(dyn_array_t* arr, byte* ptr)
{
dyn_block_t* block;
ut_ad(arr);
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
block = dyn_array_get_last_block(arr);
ut_ad(arr->buf_end + block->data >= ptr);
block->used = ptr - block->data;
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
#ifdef UNIV_DEBUG
arr->buf_end = 0;
#endif
}
UNIV_INLINE void* dyn_array_get_element(dyn_array_t* arr, ulint pos)
{
dyn_block_t* arr;
ulint used;
ut_ad(arr);
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
block = dyn_array_get_first_block(arr);
if(arr->heap != NULL){
used = dyn_block_get_used(arr);
while(pos >= used){
pos -= used;
block = UT_LIST_GET_NEXT(list, block);
ut_ad(block);
used = dyn_block_get_used(block);
}
}
ut_ad(block);
ut_ad(dyn_block_get_used(block) >= pos);
return block->data + pos;
}
UNIV_INLINE ulint dyn_array_get_data_size(dyn_array_t* arr)
{
dyn_block_t* block;
ulint sum = 0;
ut_ad(arr);
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
if(arr->heap == NULL)
return arr->used;
block = dyn_array_get_first_block(arr);
while(block != NULL){
sum += dyn_block_get_used(block);
block = dyn_array_get_next_block(arr, block);
}
return sum;
}
UNIV_INLINE void dyn_push_string(dyn_array_t* arr, byte* str, ulint len)
{
byte* ptr;
ulint n_copied;
while(len > 0){
if(len > DYN_ARRAY_DATA_SIZE)
n_copied = DYN_ARRAY_DATA_SIZE;
else
n_copied = len;
}
ptr = (byte *)dyn_array_push(arr, n_copied);
ut_memcpy(ptr, str, n_copied);
str += n_copied;
len -= n_copied;
}