mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / innobase / include / dyn0dyn.ic
blobfcb3c17287aa9ac1ff291e1173d21839fe5580c7
1 /******************************************************
2 The dynamically allocated array
4 (c) 1996 Innobase Oy
6 Created 2/5/1996 Heikki Tuuri
7 *******************************************************/
9 #define DYN_BLOCK_MAGIC_N       375767
10 #define DYN_BLOCK_FULL_FLAG     0x1000000UL
12 /****************************************************************
13 Adds a new block to a dyn array. */
15 dyn_block_t*
16 dyn_array_add_block(
17 /*================*/
18                                 /* out: created block */
19         dyn_array_t*    arr);   /* in: dyn array */
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 */
30         return(arr);
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 */
41         if (arr->heap == NULL) {
43                 return(arr);
44         }
46         return(UT_LIST_GET_LAST(arr->base));
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 */
59         ut_ad(arr && block);
61         if (arr->heap == NULL) {
62                 ut_ad(arr == block);
64                 return(NULL);
65         }
67         return(UT_LIST_GET_NEXT(list, block));
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 */
79         ut_ad(block);
81         return((block->used) & ~DYN_BLOCK_FULL_FLAG);
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 */
93         ut_ad(block);
95         return(block->data);
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) */
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
113         arr->heap = NULL;
114         arr->used = 0;
116 #ifdef UNIV_DEBUG
117         arr->buf_end = 0;
118         arr->magic_n = DYN_BLOCK_MAGIC_N;
119 #endif
120         return(arr);
123 /****************************************************************
124 Frees a dynamic array. */
125 UNIV_INLINE
126 void
127 dyn_array_free(
128 /*===========*/
129         dyn_array_t*    arr)    /* in: dyn array */
131         if (arr->heap != NULL) {
132                 mem_heap_free(arr->heap);
133         }
135 #ifdef UNIV_DEBUG
136         arr->magic_n = 0;
137 #endif
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 */
151         dyn_block_t*    block;
152         ulint           used;
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);
159         block = arr;
160         used = block->used;
162         if (used + size > DYN_ARRAY_DATA_SIZE) {
163                 /* Get the last array block */
165                 block = dyn_array_get_last_block(arr);
166                 used = block->used;
168                 if (used + size > DYN_ARRAY_DATA_SIZE) {
169                         block = dyn_array_add_block(arr);
170                         used = block->used;
171                 }
172         }
174         block->used = used + size;
175         ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
177         return((block->data) + used);
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! */
193         dyn_block_t*    block;
194         ulint           used;
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);
201         block = arr;
202         used = block->used;
204         if (used + size > DYN_ARRAY_DATA_SIZE) {
205                 /* Get the last array block */
207                 block = dyn_array_get_last_block(arr);
208                 used = block->used;
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         }
217         ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
218 #ifdef UNIV_DEBUG
219         ut_ad(arr->buf_end == 0);
221         arr->buf_end = used + size;
222 #endif
223         return((block->data) + used);
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 */
235         dyn_block_t*    block;
237         ut_ad(arr);
238         ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
240         block = dyn_array_get_last_block(arr);
242         ut_ad(arr->buf_end + block->data >= ptr);
244         block->used = ptr - block->data;
246         ut_ad(block->used <= DYN_ARRAY_DATA_SIZE);
248 #ifdef UNIV_DEBUG
249         arr->buf_end = 0;
250 #endif
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 */
264         dyn_block_t*    block;
265         ulint           used;
267         ut_ad(arr);
268         ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
270         /* Get the first array block */
271         block = dyn_array_get_first_block(arr);
273         if (arr->heap != NULL) {
274                 used = dyn_block_get_used(block);
276                 while (pos >= used) {
277                         pos -= used;
278                         block = UT_LIST_GET_NEXT(list, block);
279                         ut_ad(block);
281                         used = dyn_block_get_used(block);
282                 }
283         }
285         ut_ad(block);
286         ut_ad(dyn_block_get_used(block) >= pos);
288         return(block->data + pos);
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 */
300         dyn_block_t*    block;
301         ulint           sum     = 0;
303         ut_ad(arr);
304         ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
306         if (arr->heap == NULL) {
308                 return(arr->used);
309         }
311         /* Get the first array block */
312         block = dyn_array_get_first_block(arr);
314         while (block != NULL) {
315                 sum += dyn_block_get_used(block);
316                 block = dyn_array_get_next_block(arr, block);
317         }
319         return(sum);
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 */
332         ulint   n_copied;
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                 }
341                 memcpy(dyn_array_push(arr, n_copied), str, n_copied);
343                 str += n_copied;
344                 len -= n_copied;
345         }