~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/******************************************************
2
The dynamically allocated array
3
4
(c) 1996 Innobase Oy
5
6
Created 2/5/1996 Heikki Tuuri
7
*******************************************************/
8
9
#define DYN_BLOCK_MAGIC_N	375767
10
#define DYN_BLOCK_FULL_FLAG	0x1000000UL
11
12
/****************************************************************
13
Adds a new block to a dyn array. */
14
15
dyn_block_t*
16
dyn_array_add_block(
17
/*================*/
18
				/* out: created block */
19
	dyn_array_t*	arr);	/* in: dyn array */
20
21
22
/****************************************************************
23
Gets the first block in a dyn array. */
24
UNIV_INLINE
25
dyn_block_t*
26
dyn_array_get_first_block(
27
/*======================*/
28
	dyn_array_t*	arr)	/* in: dyn array */
29
{
30
	return(arr);
31
}
32
33
/****************************************************************
34
Gets the last block in a dyn array. */
35
UNIV_INLINE
36
dyn_block_t*
37
dyn_array_get_last_block(
38
/*=====================*/
39
	dyn_array_t*	arr)	/* in: dyn array */
40
{
41
	if (arr->heap == NULL) {
42
43
		return(arr);
44
	}
45
46
	return(UT_LIST_GET_LAST(arr->base));
47
}
48
49
/************************************************************************
50
Gets the next block in a dyn array. */
51
UNIV_INLINE
52
dyn_block_t*
53
dyn_array_get_next_block(
54
/*=====================*/
55
				/* out: pointer to next, NULL if end of list */
56
	dyn_array_t*	arr,	/* in: dyn array */
57
	dyn_block_t*	block)	/* in: dyn array block */
58
{
59
	ut_ad(arr && block);
60
61
	if (arr->heap == NULL) {
62
		ut_ad(arr == block);
63
64
		return(NULL);
65
	}
66
67
	return(UT_LIST_GET_NEXT(list, block));
68
}
69
70
/************************************************************************
71
Gets the number of used bytes in a dyn array block. */
72
UNIV_INLINE
73
ulint
74
dyn_block_get_used(
75
/*===============*/
76
				/* out: number of bytes used */
77
	dyn_block_t*	block)	/* in: dyn array block */
78
{
79
	ut_ad(block);
80
81
	return((block->used) & ~DYN_BLOCK_FULL_FLAG);
82
}
83
84
/************************************************************************
85
Gets pointer to the start of data in a dyn array block. */
86
UNIV_INLINE
87
byte*
88
dyn_block_get_data(
89
/*===============*/
90
				/* out: pointer to data */
91
	dyn_block_t*	block)	/* in: dyn array block */
92
{
93
	ut_ad(block);
94
95
	return(block->data);
96
}
97
98
/*************************************************************************
99
Initializes a dynamic array. */
100
UNIV_INLINE
101
dyn_array_t*
102
dyn_array_create(
103
/*=============*/
104
				/* out: initialized dyn array */
105
	dyn_array_t*	arr)	/* in: pointer to a memory buffer of
106
				size sizeof(dyn_array_t) */
107
{
108
	ut_ad(arr);
109
#if DYN_ARRAY_DATA_SIZE >= DYN_BLOCK_FULL_FLAG
110
# error "DYN_ARRAY_DATA_SIZE >= DYN_BLOCK_FULL_FLAG"
111
#endif
112
113
	arr->heap = NULL;
114
	arr->used = 0;
115
116
#ifdef UNIV_DEBUG
117
	arr->buf_end = 0;
118
	arr->magic_n = DYN_BLOCK_MAGIC_N;
119
#endif
120
	return(arr);
121
}
122
123
/****************************************************************
124
Frees a dynamic array. */
125
UNIV_INLINE
126
void
127
dyn_array_free(
128
/*===========*/
129
	dyn_array_t*	arr)	/* in: dyn array */
130
{
131
	if (arr->heap != NULL) {
132
		mem_heap_free(arr->heap);
133
	}
134
135
#ifdef UNIV_DEBUG
136
	arr->magic_n = 0;
137
#endif
138
}
139
140
/*************************************************************************
141
Makes room on top of a dyn array and returns a pointer to the added element.
142
The caller must copy the element to the pointer returned. */
143
UNIV_INLINE
144
void*
145
dyn_array_push(
146
/*===========*/
147
				/* out: pointer to the element */
148
	dyn_array_t*	arr,	/* in: dynamic array */
149
	ulint		size)	/* in: size in bytes of the element */
150
{
151
	dyn_block_t*	block;
152
	ulint		used;
153
154
	ut_ad(arr);
155
	ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
156
	ut_ad(size <= DYN_ARRAY_DATA_SIZE);
157
	ut_ad(size);
158
159
	block = arr;
160
	used = block->used;
161
162
	if (used + size > DYN_ARRAY_DATA_SIZE) {
163
		/* Get the last array block */
164
165
		block = dyn_array_get_last_block(arr);
166
		used = block->used;
167
168
		if (used + size > DYN_ARRAY_DATA_SIZE) {
169
			block = dyn_array_add_block(arr);
170
			used = block->used;
171
		}
172
	}
173
174
	block->used = used + size;
175
	ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
176
177
	return((block->data) + used);
178
}
179
180
/*************************************************************************
181
Makes room on top of a dyn array and returns a pointer to a buffer in it.
182
After copying the elements, the caller must close the buffer using
183
dyn_array_close. */
184
UNIV_INLINE
185
byte*
186
dyn_array_open(
187
/*===========*/
188
				/* out: pointer to the buffer */
189
	dyn_array_t*	arr,	/* in: dynamic array */
190
	ulint		size)	/* in: size in bytes of the buffer; MUST be
191
				smaller than DYN_ARRAY_DATA_SIZE! */
192
{
193
	dyn_block_t*	block;
194
	ulint		used;
195
196
	ut_ad(arr);
197
	ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
198
	ut_ad(size <= DYN_ARRAY_DATA_SIZE);
199
	ut_ad(size);
200
201
	block = arr;
202
	used = block->used;
203
204
	if (used + size > DYN_ARRAY_DATA_SIZE) {
205
		/* Get the last array block */
206
207
		block = dyn_array_get_last_block(arr);
208
		used = block->used;
209
210
		if (used + size > DYN_ARRAY_DATA_SIZE) {
211
			block = dyn_array_add_block(arr);
212
			used = block->used;
213
			ut_a(size <= DYN_ARRAY_DATA_SIZE);
214
		}
215
	}
216
217
	ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
218
#ifdef UNIV_DEBUG
219
	ut_ad(arr->buf_end == 0);
220
221
	arr->buf_end = used + size;
222
#endif
223
	return((block->data) + used);
224
}
225
226
/*************************************************************************
227
Closes the buffer returned by dyn_array_open. */
228
UNIV_INLINE
229
void
230
dyn_array_close(
231
/*============*/
232
	dyn_array_t*	arr,	/* in: dynamic array */
233
	byte*		ptr)	/* in: buffer space from ptr up was not used */
234
{
235
	dyn_block_t*	block;
236
237
	ut_ad(arr);
238
	ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
239
240
	block = dyn_array_get_last_block(arr);
241
242
	ut_ad(arr->buf_end + block->data >= ptr);
243
244
	block->used = ptr - block->data;
245
246
	ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
247
248
#ifdef UNIV_DEBUG
249
	arr->buf_end = 0;
250
#endif
251
}
252
253
/****************************************************************
254
Returns pointer to an element in dyn array. */
255
UNIV_INLINE
256
void*
257
dyn_array_get_element(
258
/*==================*/
259
				/* out: pointer to element */
260
	dyn_array_t*	arr,	/* in: dyn array */
261
	ulint		pos)	/* in: position of element as bytes
262
				from array start */
263
{
264
	dyn_block_t*	block;
265
	ulint		used;
266
267
	ut_ad(arr);
268
	ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
269
270
	/* Get the first array block */
271
	block = dyn_array_get_first_block(arr);
272
273
	if (arr->heap != NULL) {
274
		used = dyn_block_get_used(block);
275
276
		while (pos >= used) {
277
			pos -= used;
278
			block = UT_LIST_GET_NEXT(list, block);
279
			ut_ad(block);
280
281
			used = dyn_block_get_used(block);
282
		}
283
	}
284
285
	ut_ad(block);
286
	ut_ad(dyn_block_get_used(block) >= pos);
287
288
	return(block->data + pos);
289
}
290
291
/****************************************************************
292
Returns the size of stored data in a dyn array. */
293
UNIV_INLINE
294
ulint
295
dyn_array_get_data_size(
296
/*====================*/
297
				/* out: data size in bytes */
298
	dyn_array_t*	arr)	/* in: dyn array */
299
{
300
	dyn_block_t*	block;
301
	ulint		sum	= 0;
302
303
	ut_ad(arr);
304
	ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
305
306
	if (arr->heap == NULL) {
307
308
		return(arr->used);
309
	}
310
311
	/* Get the first array block */
312
	block = dyn_array_get_first_block(arr);
313
314
	while (block != NULL) {
315
		sum += dyn_block_get_used(block);
316
		block = dyn_array_get_next_block(arr, block);
317
	}
318
319
	return(sum);
320
}
321
322
/************************************************************
323
Pushes n bytes to a dyn array. */
324
UNIV_INLINE
325
void
326
dyn_push_string(
327
/*============*/
328
	dyn_array_t*	arr,	/* in: dyn array */
329
	const byte*	str,	/* in: string to write */
330
	ulint		len)	/* in: string length */
331
{
332
	ulint	n_copied;
333
334
	while (len > 0) {
335
		if (len > DYN_ARRAY_DATA_SIZE) {
336
			n_copied = DYN_ARRAY_DATA_SIZE;
337
		} else {
338
			n_copied = len;
339
		}
340
341
		memcpy(dyn_array_push(arr, n_copied), str, n_copied);
342
343
		str += n_copied;
344
		len -= n_copied;
345
	}
346
}