~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/include/dyn0dyn.ic

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}