1
/*****************************************************************************
3
Copyright (C) 1996, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file include/dyn0dyn.ic
21
The dynamically allocated array
23
Created 2/5/1996 Heikki Tuuri
24
*******************************************************/
26
/** Value of dyn_block_struct::magic_n */
27
#define DYN_BLOCK_MAGIC_N 375767
28
/** Flag for dyn_block_struct::used that indicates a full block */
29
#define DYN_BLOCK_FULL_FLAG 0x1000000UL
31
/************************************************************//**
32
Adds a new block to a dyn array.
33
@return created block */
38
dyn_array_t* arr); /*!< in: dyn array */
41
/************************************************************//**
42
Gets the first block in a dyn array. */
45
dyn_array_get_first_block(
46
/*======================*/
47
dyn_array_t* arr) /*!< in: dyn array */
52
/************************************************************//**
53
Gets the last block in a dyn array. */
56
dyn_array_get_last_block(
57
/*=====================*/
58
dyn_array_t* arr) /*!< in: dyn array */
60
if (arr->heap == NULL) {
65
return(UT_LIST_GET_LAST(arr->base));
68
/********************************************************************//**
69
Gets the next block in a dyn array.
70
@return pointer to next, NULL if end of list */
73
dyn_array_get_next_block(
74
/*=====================*/
75
dyn_array_t* arr, /*!< in: dyn array */
76
dyn_block_t* block) /*!< in: dyn array block */
80
if (arr->heap == NULL) {
86
return(UT_LIST_GET_NEXT(list, block));
89
/********************************************************************//**
90
Gets the number of used bytes in a dyn array block.
91
@return number of bytes used */
96
dyn_block_t* block) /*!< in: dyn array block */
100
return((block->used) & ~DYN_BLOCK_FULL_FLAG);
103
/********************************************************************//**
104
Gets pointer to the start of data in a dyn array block.
105
@return pointer to data */
110
dyn_block_t* block) /*!< in: dyn array block */
117
/*********************************************************************//**
118
Initializes a dynamic array.
119
@return initialized dyn array */
124
dyn_array_t* arr) /*!< in: pointer to a memory buffer of
125
size sizeof(dyn_array_t) */
128
#if DYN_ARRAY_DATA_SIZE >= DYN_BLOCK_FULL_FLAG
129
# error "DYN_ARRAY_DATA_SIZE >= DYN_BLOCK_FULL_FLAG"
137
arr->magic_n = DYN_BLOCK_MAGIC_N;
142
/************************************************************//**
143
Frees a dynamic array. */
148
dyn_array_t* arr) /*!< in: dyn array */
150
if (arr->heap != NULL) {
151
mem_heap_free(arr->heap);
159
/*********************************************************************//**
160
Makes room on top of a dyn array and returns a pointer to the added element.
161
The caller must copy the element to the pointer returned.
162
@return pointer to the element */
167
dyn_array_t* arr, /*!< in: dynamic array */
168
ulint size) /*!< in: size in bytes of the element */
174
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
175
ut_ad(size <= DYN_ARRAY_DATA_SIZE);
181
if (used + size > DYN_ARRAY_DATA_SIZE) {
182
/* Get the last array block */
184
block = dyn_array_get_last_block(arr);
187
if (used + size > DYN_ARRAY_DATA_SIZE) {
188
block = dyn_array_add_block(arr);
193
block->used = used + size;
194
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
196
return((block->data) + used);
199
/*********************************************************************//**
200
Makes room on top of a dyn array and returns a pointer to a buffer in it.
201
After copying the elements, the caller must close the buffer using
203
@return pointer to the buffer */
208
dyn_array_t* arr, /*!< in: dynamic array */
209
ulint size) /*!< in: size in bytes of the buffer; MUST be
210
smaller than DYN_ARRAY_DATA_SIZE! */
216
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
217
ut_ad(size <= DYN_ARRAY_DATA_SIZE);
223
if (used + size > DYN_ARRAY_DATA_SIZE) {
224
/* Get the last array block */
226
block = dyn_array_get_last_block(arr);
229
if (used + size > DYN_ARRAY_DATA_SIZE) {
230
block = dyn_array_add_block(arr);
232
ut_a(size <= DYN_ARRAY_DATA_SIZE);
236
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
238
ut_ad(arr->buf_end == 0);
240
arr->buf_end = used + size;
242
return((block->data) + used);
245
/*********************************************************************//**
246
Closes the buffer returned by dyn_array_open. */
251
dyn_array_t* arr, /*!< in: dynamic array */
252
byte* ptr) /*!< in: buffer space from ptr up was not used */
257
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
259
block = dyn_array_get_last_block(arr);
261
ut_ad(arr->buf_end + block->data >= ptr);
263
block->used = ptr - block->data;
265
ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
272
/************************************************************//**
273
Returns pointer to an element in dyn array.
274
@return pointer to element */
277
dyn_array_get_element(
278
/*==================*/
279
dyn_array_t* arr, /*!< in: dyn array */
280
ulint pos) /*!< in: position of element as bytes
287
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
289
/* Get the first array block */
290
block = dyn_array_get_first_block(arr);
292
if (arr->heap != NULL) {
293
used = dyn_block_get_used(block);
295
while (pos >= used) {
297
block = UT_LIST_GET_NEXT(list, block);
300
used = dyn_block_get_used(block);
305
ut_ad(dyn_block_get_used(block) >= pos);
307
return(block->data + pos);
310
/************************************************************//**
311
Returns the size of stored data in a dyn array.
312
@return data size in bytes */
315
dyn_array_get_data_size(
316
/*====================*/
317
dyn_array_t* arr) /*!< in: dyn array */
323
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
325
if (arr->heap == NULL) {
330
/* Get the first array block */
331
block = dyn_array_get_first_block(arr);
333
while (block != NULL) {
334
sum += dyn_block_get_used(block);
335
block = dyn_array_get_next_block(arr, block);
341
/********************************************************//**
342
Pushes n bytes to a dyn array. */
347
dyn_array_t* arr, /*!< in: dyn array */
348
const byte* str, /*!< in: string to write */
349
ulint len) /*!< in: string length */
354
if (len > DYN_ARRAY_DATA_SIZE) {
355
n_copied = DYN_ARRAY_DATA_SIZE;
360
memcpy(dyn_array_push(arr, n_copied), str, n_copied);