diff options
Diffstat (limited to 'storage/innobase/include/dyn0dyn.ic')
-rw-r--r-- | storage/innobase/include/dyn0dyn.ic | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/storage/innobase/include/dyn0dyn.ic b/storage/innobase/include/dyn0dyn.ic new file mode 100644 index 00000000000..b6c4808398b --- /dev/null +++ b/storage/innobase/include/dyn0dyn.ic @@ -0,0 +1,347 @@ +/****************************************************** +The dynamically allocated array + +(c) 1996 Innobase Oy + +Created 2/5/1996 Heikki Tuuri +*******************************************************/ + +#define DYN_BLOCK_MAGIC_N 375767 +#define DYN_BLOCK_FULL_FLAG 0x1000000UL + +/**************************************************************** +Adds a new block to a dyn array. */ + +dyn_block_t* +dyn_array_add_block( +/*================*/ + /* out: created block */ + dyn_array_t* arr); /* in: dyn array */ + + +/**************************************************************** +Gets the first block in a dyn array. */ +UNIV_INLINE +dyn_block_t* +dyn_array_get_first_block( +/*======================*/ + dyn_array_t* arr) /* in: dyn array */ +{ + return(arr); +} + +/**************************************************************** +Gets the last block in a dyn array. */ +UNIV_INLINE +dyn_block_t* +dyn_array_get_last_block( +/*=====================*/ + dyn_array_t* arr) /* in: dyn array */ +{ + if (arr->heap == NULL) { + + return(arr); + } + + return(UT_LIST_GET_LAST(arr->base)); +} + +/************************************************************************ +Gets the next block in a dyn array. */ +UNIV_INLINE +dyn_block_t* +dyn_array_get_next_block( +/*=====================*/ + /* out: pointer to next, NULL if end of list */ + dyn_array_t* arr, /* in: dyn array */ + dyn_block_t* block) /* in: dyn array block */ +{ + ut_ad(arr && block); + + if (arr->heap == NULL) { + ut_ad(arr == block); + + return(NULL); + } + + return(UT_LIST_GET_NEXT(list, block)); +} + +/************************************************************************ +Gets the number of used bytes in a dyn array block. */ +UNIV_INLINE +ulint +dyn_block_get_used( +/*===============*/ + /* out: number of bytes used */ + dyn_block_t* block) /* in: dyn array block */ +{ + ut_ad(block); + + return((block->used) & ~DYN_BLOCK_FULL_FLAG); +} + +/************************************************************************ +Gets pointer to the start of data in a dyn array block. */ +UNIV_INLINE +byte* +dyn_block_get_data( +/*===============*/ + /* out: pointer to data */ + dyn_block_t* block) /* in: dyn array block */ +{ + ut_ad(block); + + return(block->data); +} + +/************************************************************************* +Initializes a dynamic array. */ +UNIV_INLINE +dyn_array_t* +dyn_array_create( +/*=============*/ + /* out: initialized dyn array */ + dyn_array_t* arr) /* in: pointer to a memory buffer of + size sizeof(dyn_array_t) */ +{ + 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); +} + +/**************************************************************** +Frees a dynamic array. */ +UNIV_INLINE +void +dyn_array_free( +/*===========*/ + dyn_array_t* arr) /* in: dyn array */ +{ + if (arr->heap != NULL) { + mem_heap_free(arr->heap); + } + +#ifdef UNIV_DEBUG + arr->magic_n = 0; +#endif +} + +/************************************************************************* +Makes room on top of a dyn array and returns a pointer to the added element. +The caller must copy the element to the pointer returned. */ +UNIV_INLINE +void* +dyn_array_push( +/*===========*/ + /* out: pointer to the element */ + dyn_array_t* arr, /* in: dynamic array */ + ulint size) /* in: size in bytes of the element */ +{ + 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); +} + +/************************************************************************* +Makes room on top of a dyn array and returns a pointer to a buffer in it. +After copying the elements, the caller must close the buffer using +dyn_array_close. */ +UNIV_INLINE +byte* +dyn_array_open( +/*===========*/ + /* out: pointer to the buffer */ + dyn_array_t* arr, /* in: dynamic array */ + ulint size) /* in: size in bytes of the buffer; MUST be + smaller than DYN_ARRAY_DATA_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 = used + size; +#endif + return((block->data) + used); +} + +/************************************************************************* +Closes the buffer returned by dyn_array_open. */ +UNIV_INLINE +void +dyn_array_close( +/*============*/ + dyn_array_t* arr, /* in: dynamic array */ + byte* ptr) /* in: buffer space from ptr up was not used */ +{ + 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 +} + +/**************************************************************** +Returns pointer to an element in dyn array. */ +UNIV_INLINE +void* +dyn_array_get_element( +/*==================*/ + /* out: pointer to element */ + dyn_array_t* arr, /* in: dyn array */ + ulint pos) /* in: position of element as bytes + from array start */ +{ + dyn_block_t* block; + ulint used; + + ut_ad(arr); + ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N); + + /* Get the first array block */ + block = dyn_array_get_first_block(arr); + + if (arr->heap != NULL) { + used = dyn_block_get_used(block); + + 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); +} + +/**************************************************************** +Returns the size of stored data in a dyn array. */ +UNIV_INLINE +ulint +dyn_array_get_data_size( +/*====================*/ + /* out: data size in bytes */ + dyn_array_t* arr) /* in: dyn array */ +{ + 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); + } + + /* Get the first array block */ + 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); +} + +/************************************************************ +Pushes n bytes to a dyn array. */ +UNIV_INLINE +void +dyn_push_string( +/*============*/ + dyn_array_t* arr, /* in: dyn array */ + byte* str, /* in: string to write */ + ulint len) /* in: string length */ +{ + 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; + } +} |