~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/include/mem0mem.ic

  • Committer: Monty Taylor
  • Date: 2008-08-02 00:06:32 UTC
  • mto: (236.1.42 codestyle)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: monty@inaugust.com-20080802000632-jsse0zdd9r6ic5ku
Actually turn gettext on...

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
4
 
 
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.
8
 
 
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.
12
 
 
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., 59 Temple
15
 
Place, Suite 330, Boston, MA 02111-1307 USA
16
 
 
17
 
*****************************************************************************/
18
 
 
19
 
/********************************************************************//**
20
 
@file include/mem0mem.ic
21
 
The memory management
22
 
 
23
 
Created 6/8/1994 Heikki Tuuri
24
 
*************************************************************************/
25
 
 
26
 
#include "mem0dbg.ic"
27
 
#ifndef UNIV_HOTBACKUP
28
 
# include "mem0pool.h"
29
 
#endif /* !UNIV_HOTBACKUP */
30
 
 
31
 
/***************************************************************//**
32
 
Creates a memory heap block where data can be allocated.
33
 
@return own: memory heap block, NULL if did not succeed (only possible
34
 
for MEM_HEAP_BTR_SEARCH type heaps) */
35
 
UNIV_INTERN
36
 
mem_block_t*
37
 
mem_heap_create_block(
38
 
/*==================*/
39
 
        mem_heap_t*     heap,   /*!< in: memory heap or NULL if first block
40
 
                                should be created */
41
 
        ulint           n,      /*!< in: number of bytes needed for user data */
42
 
        ulint           type,   /*!< in: type of heap: MEM_HEAP_DYNAMIC or
43
 
                                MEM_HEAP_BUFFER */
44
 
        const char*     file_name,/*!< in: file name where created */
45
 
        ulint           line);  /*!< in: line where created */
46
 
/******************************************************************//**
47
 
Frees a block from a memory heap. */
48
 
UNIV_INTERN
49
 
void
50
 
mem_heap_block_free(
51
 
/*================*/
52
 
        mem_heap_t*     heap,   /*!< in: heap */
53
 
        mem_block_t*    block); /*!< in: block to free */
54
 
#ifndef UNIV_HOTBACKUP
55
 
/******************************************************************//**
56
 
Frees the free_block field from a memory heap. */
57
 
UNIV_INTERN
58
 
void
59
 
mem_heap_free_block_free(
60
 
/*=====================*/
61
 
        mem_heap_t*     heap);  /*!< in: heap */
62
 
#endif /* !UNIV_HOTBACKUP */
63
 
/***************************************************************//**
64
 
Adds a new block to a memory heap.
65
 
@return created block, NULL if did not succeed (only possible for
66
 
MEM_HEAP_BTR_SEARCH type heaps) */
67
 
UNIV_INTERN
68
 
mem_block_t*
69
 
mem_heap_add_block(
70
 
/*===============*/
71
 
        mem_heap_t*     heap,   /*!< in: memory heap */
72
 
        ulint           n);     /*!< in: number of bytes user needs */
73
 
 
74
 
UNIV_INLINE
75
 
void
76
 
mem_block_set_len(mem_block_t* block, ulint len)
77
 
{
78
 
        ut_ad(len > 0);
79
 
 
80
 
        block->len = len;
81
 
}
82
 
 
83
 
UNIV_INLINE
84
 
ulint
85
 
mem_block_get_len(mem_block_t* block)
86
 
{
87
 
        return(block->len);
88
 
}
89
 
 
90
 
UNIV_INLINE
91
 
void
92
 
mem_block_set_type(mem_block_t* block, ulint type)
93
 
{
94
 
        ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
95
 
              || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
96
 
 
97
 
        block->type = type;
98
 
}
99
 
 
100
 
UNIV_INLINE
101
 
ulint
102
 
mem_block_get_type(mem_block_t* block)
103
 
{
104
 
        return(block->type);
105
 
}
106
 
 
107
 
UNIV_INLINE
108
 
void
109
 
mem_block_set_free(mem_block_t* block, ulint free)
110
 
{
111
 
        ut_ad(free > 0);
112
 
        ut_ad(free <= mem_block_get_len(block));
113
 
 
114
 
        block->free = free;
115
 
}
116
 
 
117
 
UNIV_INLINE
118
 
ulint
119
 
mem_block_get_free(mem_block_t* block)
120
 
{
121
 
        return(block->free);
122
 
}
123
 
 
124
 
UNIV_INLINE
125
 
void
126
 
mem_block_set_start(mem_block_t* block, ulint start)
127
 
{
128
 
        ut_ad(start > 0);
129
 
 
130
 
        block->start = start;
131
 
}
132
 
 
133
 
UNIV_INLINE
134
 
ulint
135
 
mem_block_get_start(mem_block_t* block)
136
 
{
137
 
        return(block->start);
138
 
}
139
 
 
140
 
/***************************************************************//**
141
 
Allocates and zero-fills n bytes of memory from a memory heap.
142
 
@return allocated, zero-filled storage */
143
 
UNIV_INLINE
144
 
void*
145
 
mem_heap_zalloc(
146
 
/*============*/
147
 
        mem_heap_t*     heap,   /*!< in: memory heap */
148
 
        ulint           n)      /*!< in: number of bytes; if the heap is allowed
149
 
                                to grow into the buffer pool, this must be
150
 
                                <= MEM_MAX_ALLOC_IN_BUF */
151
 
{
152
 
        ut_ad(heap);
153
 
        ut_ad(!(heap->type & MEM_HEAP_BTR_SEARCH));
154
 
        return(memset(mem_heap_alloc(heap, n), 0, n));
155
 
}
156
 
 
157
 
/***************************************************************//**
158
 
Allocates n bytes of memory from a memory heap.
159
 
@return allocated storage, NULL if did not succeed (only possible for
160
 
MEM_HEAP_BTR_SEARCH type heaps) */
161
 
UNIV_INLINE
162
 
void*
163
 
mem_heap_alloc(
164
 
/*===========*/
165
 
        mem_heap_t*     heap,   /*!< in: memory heap */
166
 
        ulint           n)      /*!< in: number of bytes; if the heap is allowed
167
 
                                to grow into the buffer pool, this must be
168
 
                                <= MEM_MAX_ALLOC_IN_BUF */
169
 
{
170
 
        mem_block_t*    block;
171
 
        void*           buf;
172
 
        ulint           free;
173
 
 
174
 
        ut_ad(mem_heap_check(heap));
175
 
 
176
 
        block = UT_LIST_GET_LAST(heap->base);
177
 
 
178
 
        ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF));
179
 
 
180
 
        /* Check if there is enough space in block. If not, create a new
181
 
        block to the heap */
182
 
 
183
 
        if (mem_block_get_len(block)
184
 
            < mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) {
185
 
 
186
 
                block = mem_heap_add_block(heap, n);
187
 
 
188
 
                if (block == NULL) {
189
 
 
190
 
                        return(NULL);
191
 
                }
192
 
        }
193
 
 
194
 
        free = mem_block_get_free(block);
195
 
 
196
 
        buf = (byte*)block + free;
197
 
 
198
 
        mem_block_set_free(block, free + MEM_SPACE_NEEDED(n));
199
 
 
200
 
#ifdef UNIV_MEM_DEBUG
201
 
        UNIV_MEM_ALLOC(buf,
202
 
                       n + MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE);
203
 
 
204
 
        /* In the debug version write debugging info to the field */
205
 
        mem_field_init((byte*)buf, n);
206
 
 
207
 
        /* Advance buf to point at the storage which will be given to the
208
 
        caller */
209
 
        buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
210
 
 
211
 
#endif
212
 
#ifdef UNIV_SET_MEM_TO_ZERO
213
 
        UNIV_MEM_ALLOC(buf, n);
214
 
        memset(buf, '\0', n);
215
 
#endif
216
 
        UNIV_MEM_ALLOC(buf, n);
217
 
        return(buf);
218
 
}
219
 
 
220
 
/*****************************************************************//**
221
 
Returns a pointer to the heap top.
222
 
@return pointer to the heap top */
223
 
UNIV_INLINE
224
 
byte*
225
 
mem_heap_get_heap_top(
226
 
/*==================*/
227
 
        mem_heap_t*     heap)   /*!< in: memory heap */
228
 
{
229
 
        mem_block_t*    block;
230
 
        byte*           buf;
231
 
 
232
 
        ut_ad(mem_heap_check(heap));
233
 
 
234
 
        block = UT_LIST_GET_LAST(heap->base);
235
 
 
236
 
        buf = (byte*)block + mem_block_get_free(block);
237
 
 
238
 
        return(buf);
239
 
}
240
 
 
241
 
/*****************************************************************//**
242
 
Frees the space in a memory heap exceeding the pointer given. The
243
 
pointer must have been acquired from mem_heap_get_heap_top. The first
244
 
memory block of the heap is not freed. */
245
 
UNIV_INLINE
246
 
void
247
 
mem_heap_free_heap_top(
248
 
/*===================*/
249
 
        mem_heap_t*     heap,   /*!< in: heap from which to free */
250
 
        byte*           old_top)/*!< in: pointer to old top of heap */
251
 
{
252
 
        mem_block_t*    block;
253
 
        mem_block_t*    prev_block;
254
 
#ifdef UNIV_MEM_DEBUG
255
 
        ibool           error;
256
 
        ulint           total_size;
257
 
        ulint           size;
258
 
#endif
259
 
 
260
 
        ut_ad(mem_heap_check(heap));
261
 
 
262
 
#ifdef UNIV_MEM_DEBUG
263
 
 
264
 
        /* Validate the heap and get its total allocated size */
265
 
        mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size,
266
 
                                   NULL, NULL);
267
 
        ut_a(!error);
268
 
 
269
 
        /* Get the size below top pointer */
270
 
        mem_heap_validate_or_print(heap, old_top, FALSE, &error, &size, NULL,
271
 
                                   NULL);
272
 
        ut_a(!error);
273
 
 
274
 
#endif
275
 
 
276
 
        block = UT_LIST_GET_LAST(heap->base);
277
 
 
278
 
        while (block != NULL) {
279
 
                if (((byte*)block + mem_block_get_free(block) >= old_top)
280
 
                    && ((byte*)block <= old_top)) {
281
 
                        /* Found the right block */
282
 
 
283
 
                        break;
284
 
                }
285
 
 
286
 
                /* Store prev_block value before freeing the current block
287
 
                (the current block will be erased in freeing) */
288
 
 
289
 
                prev_block = UT_LIST_GET_PREV(list, block);
290
 
 
291
 
                mem_heap_block_free(heap, block);
292
 
 
293
 
                block = prev_block;
294
 
        }
295
 
 
296
 
        ut_ad(block);
297
 
 
298
 
        /* Set the free field of block */
299
 
        mem_block_set_free(block, old_top - (byte*)block);
300
 
 
301
 
#ifdef UNIV_MEM_DEBUG
302
 
        ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
303
 
 
304
 
        /* In the debug version erase block from top up */
305
 
        mem_erase_buf(old_top, (byte*)block + block->len - old_top);
306
 
 
307
 
        /* Update allocated memory count */
308
 
        mutex_enter(&mem_hash_mutex);
309
 
        mem_current_allocated_memory -= (total_size - size);
310
 
        mutex_exit(&mem_hash_mutex);
311
 
#else /* UNIV_MEM_DEBUG */
312
 
        UNIV_MEM_ASSERT_W(old_top, (byte*)block + block->len - old_top);
313
 
#endif /* UNIV_MEM_DEBUG */
314
 
        UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top);
315
 
 
316
 
        /* If free == start, we may free the block if it is not the first
317
 
        one */
318
 
 
319
 
        if ((heap != block) && (mem_block_get_free(block)
320
 
                                == mem_block_get_start(block))) {
321
 
                mem_heap_block_free(heap, block);
322
 
        }
323
 
}
324
 
 
325
 
/*****************************************************************//**
326
 
Empties a memory heap. The first memory block of the heap is not freed. */
327
 
UNIV_INLINE
328
 
void
329
 
mem_heap_empty(
330
 
/*===========*/
331
 
        mem_heap_t*     heap)   /*!< in: heap to empty */
332
 
{
333
 
        mem_heap_free_heap_top(heap, (byte*)heap + mem_block_get_start(heap));
334
 
#ifndef UNIV_HOTBACKUP
335
 
        if (heap->free_block) {
336
 
                mem_heap_free_block_free(heap);
337
 
        }
338
 
#endif /* !UNIV_HOTBACKUP */
339
 
}
340
 
 
341
 
/*****************************************************************//**
342
 
Returns a pointer to the topmost element in a memory heap. The size of the
343
 
element must be given.
344
 
@return pointer to the topmost element */
345
 
UNIV_INLINE
346
 
void*
347
 
mem_heap_get_top(
348
 
/*=============*/
349
 
        mem_heap_t*     heap,   /*!< in: memory heap */
350
 
        ulint           n)      /*!< in: size of the topmost element */
351
 
{
352
 
        mem_block_t*    block;
353
 
        void*           buf;
354
 
 
355
 
        ut_ad(mem_heap_check(heap));
356
 
 
357
 
        block = UT_LIST_GET_LAST(heap->base);
358
 
 
359
 
        buf = (byte*)block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
360
 
 
361
 
#ifdef UNIV_MEM_DEBUG
362
 
        ut_ad(mem_block_get_start(block) <=(ulint)((byte*)buf - (byte*)block));
363
 
 
364
 
        /* In the debug version, advance buf to point at the storage which
365
 
        was given to the caller in the allocation*/
366
 
 
367
 
        buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
368
 
 
369
 
        /* Check that the field lengths agree */
370
 
        ut_ad(n == (ulint)mem_field_header_get_len(buf));
371
 
#endif
372
 
 
373
 
        return(buf);
374
 
}
375
 
 
376
 
/*****************************************************************//**
377
 
Frees the topmost element in a memory heap. The size of the element must be
378
 
given. */
379
 
UNIV_INLINE
380
 
void
381
 
mem_heap_free_top(
382
 
/*==============*/
383
 
        mem_heap_t*     heap,   /*!< in: memory heap */
384
 
        ulint           n)      /*!< in: size of the topmost element */
385
 
{
386
 
        mem_block_t*    block;
387
 
 
388
 
        ut_ad(mem_heap_check(heap));
389
 
 
390
 
        block = UT_LIST_GET_LAST(heap->base);
391
 
 
392
 
        /* Subtract the free field of block */
393
 
        mem_block_set_free(block, mem_block_get_free(block)
394
 
                           - MEM_SPACE_NEEDED(n));
395
 
        UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n);
396
 
#ifdef UNIV_MEM_DEBUG
397
 
 
398
 
        ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
399
 
 
400
 
        /* In the debug version check the consistency, and erase field */
401
 
        mem_field_erase((byte*)block + mem_block_get_free(block), n);
402
 
#endif
403
 
 
404
 
        /* If free == start, we may free the block if it is not the first
405
 
        one */
406
 
 
407
 
        if ((heap != block) && (mem_block_get_free(block)
408
 
                                == mem_block_get_start(block))) {
409
 
                mem_heap_block_free(heap, block);
410
 
        } else {
411
 
                /* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a
412
 
                subsequent invocation of mem_heap_free_top().
413
 
                Originally, this was UNIV_MEM_FREE(), to catch writes
414
 
                to freed memory. */
415
 
                UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n);
416
 
        }
417
 
}
418
 
 
419
 
/*****************************************************************//**
420
 
NOTE: Use the corresponding macros instead of this function. Creates a
421
 
memory heap. For debugging purposes, takes also the file name and line as
422
 
argument.
423
 
@return own: memory heap, NULL if did not succeed (only possible for
424
 
MEM_HEAP_BTR_SEARCH type heaps) */
425
 
UNIV_INLINE
426
 
mem_heap_t*
427
 
mem_heap_create_func(
428
 
/*=================*/
429
 
        ulint           n,              /*!< in: desired start block size,
430
 
                                        this means that a single user buffer
431
 
                                        of size n will fit in the block,
432
 
                                        0 creates a default size block */
433
 
        ulint           type,           /*!< in: heap type */
434
 
        const char*     file_name,      /*!< in: file name where created */
435
 
        ulint           line)           /*!< in: line where created */
436
 
{
437
 
        mem_block_t*   block;
438
 
 
439
 
        if (!n) {
440
 
                n = MEM_BLOCK_START_SIZE;
441
 
        }
442
 
 
443
 
        block = mem_heap_create_block(NULL, n, type, file_name, line);
444
 
 
445
 
        if (block == NULL) {
446
 
 
447
 
                return(NULL);
448
 
        }
449
 
 
450
 
        UT_LIST_INIT(block->base);
451
 
 
452
 
        /* Add the created block itself as the first block in the list */
453
 
        UT_LIST_ADD_FIRST(list, block->base, block);
454
 
 
455
 
#ifdef UNIV_MEM_DEBUG
456
 
 
457
 
        mem_hash_insert(block, file_name, line);
458
 
 
459
 
#endif
460
 
 
461
 
        return(block);
462
 
}
463
 
 
464
 
/*****************************************************************//**
465
 
NOTE: Use the corresponding macro instead of this function. Frees the space
466
 
occupied by a memory heap. In the debug version erases the heap memory
467
 
blocks. */
468
 
UNIV_INLINE
469
 
void
470
 
mem_heap_free_func(
471
 
/*===============*/
472
 
        mem_heap_t*     heap,           /*!< in, own: heap to be freed */
473
 
        const char*     file_name __attribute__((unused)),
474
 
                                        /*!< in: file name where freed */
475
 
        ulint           line  __attribute__((unused)))
476
 
{
477
 
        (void) file_name;
478
 
        (void) line;
479
 
        mem_block_t*    block;
480
 
        mem_block_t*    prev_block;
481
 
 
482
 
        ut_ad(mem_heap_check(heap));
483
 
 
484
 
        block = UT_LIST_GET_LAST(heap->base);
485
 
 
486
 
#ifdef UNIV_MEM_DEBUG
487
 
 
488
 
        /* In the debug version remove the heap from the hash table of heaps
489
 
        and check its consistency */
490
 
 
491
 
        mem_hash_remove(heap, file_name, line);
492
 
 
493
 
#endif
494
 
#ifndef UNIV_HOTBACKUP
495
 
        if (heap->free_block) {
496
 
                mem_heap_free_block_free(heap);
497
 
        }
498
 
#endif /* !UNIV_HOTBACKUP */
499
 
 
500
 
        while (block != NULL) {
501
 
                /* Store the contents of info before freeing current block
502
 
                (it is erased in freeing) */
503
 
 
504
 
                prev_block = UT_LIST_GET_PREV(list, block);
505
 
 
506
 
                mem_heap_block_free(heap, block);
507
 
 
508
 
                block = prev_block;
509
 
        }
510
 
}
511
 
 
512
 
/***************************************************************//**
513
 
NOTE: Use the corresponding macro instead of this function.
514
 
Allocates a single buffer of memory from the dynamic memory of
515
 
the C compiler. Is like malloc of C. The buffer must be freed
516
 
with mem_free.
517
 
@return own: free storage */
518
 
UNIV_INLINE
519
 
void*
520
 
mem_alloc_func(
521
 
/*===========*/
522
 
        ulint           n,              /*!< in: desired number of bytes */
523
 
        ulint*          size,           /*!< out: allocated size in bytes,
524
 
                                        or NULL */
525
 
        const char*     file_name,      /*!< in: file name where created */
526
 
        ulint           line)           /*!< in: line where created */
527
 
{
528
 
        mem_heap_t*     heap;
529
 
        void*           buf;
530
 
 
531
 
        heap = mem_heap_create_func(n, MEM_HEAP_DYNAMIC, file_name, line);
532
 
 
533
 
        /* Note that as we created the first block in the heap big enough
534
 
        for the buffer requested by the caller, the buffer will be in the
535
 
        first block and thus we can calculate the pointer to the heap from
536
 
        the pointer to the buffer when we free the memory buffer. */
537
 
 
538
 
        if (UNIV_LIKELY_NULL(size)) {
539
 
                /* Adjust the allocation to the actual size of the
540
 
                memory block. */
541
 
                ulint   m = mem_block_get_len(heap)
542
 
                        - mem_block_get_free(heap);
543
 
#ifdef UNIV_MEM_DEBUG
544
 
                m -= MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE;
545
 
#endif /* UNIV_MEM_DEBUG */
546
 
                ut_ad(m >= n);
547
 
                *size = n = m;
548
 
        }
549
 
 
550
 
        buf = mem_heap_alloc(heap, n);
551
 
 
552
 
        ut_a((byte*)heap == (byte*)buf - MEM_BLOCK_HEADER_SIZE
553
 
             - MEM_FIELD_HEADER_SIZE);
554
 
        return(buf);
555
 
}
556
 
 
557
 
/***************************************************************//**
558
 
NOTE: Use the corresponding macro instead of this function. Frees a single
559
 
buffer of storage from the dynamic memory of the C compiler. Similar to the
560
 
free of C. */
561
 
UNIV_INLINE
562
 
void
563
 
mem_free_func(
564
 
/*==========*/
565
 
        void*           ptr,            /*!< in, own: buffer to be freed */
566
 
        const char*     file_name,      /*!< in: file name where created */
567
 
        ulint           line)           /*!< in: line where created */
568
 
{
569
 
        mem_heap_t*   heap;
570
 
 
571
 
        heap = (mem_heap_t*)((byte*)ptr - MEM_BLOCK_HEADER_SIZE
572
 
                             - MEM_FIELD_HEADER_SIZE);
573
 
        mem_heap_free_func(heap, file_name, line);
574
 
}
575
 
 
576
 
/*****************************************************************//**
577
 
Returns the space in bytes occupied by a memory heap. */
578
 
UNIV_INLINE
579
 
ulint
580
 
mem_heap_get_size(
581
 
/*==============*/
582
 
        mem_heap_t*     heap)   /*!< in: heap */
583
 
{
584
 
        mem_block_t*    block;
585
 
        ulint           size    = 0;
586
 
 
587
 
        ut_ad(mem_heap_check(heap));
588
 
 
589
 
        block = heap;
590
 
 
591
 
        while (block != NULL) {
592
 
 
593
 
                size += mem_block_get_len(block);
594
 
                block = UT_LIST_GET_NEXT(list, block);
595
 
        }
596
 
#ifndef UNIV_HOTBACKUP
597
 
        if (heap->free_block) {
598
 
                size += UNIV_PAGE_SIZE;
599
 
        }
600
 
#endif /* !UNIV_HOTBACKUP */
601
 
 
602
 
        return(size);
603
 
}
604
 
 
605
 
/**********************************************************************//**
606
 
Duplicates a NUL-terminated string.
607
 
@return own: a copy of the string, must be deallocated with mem_free */
608
 
UNIV_INLINE
609
 
char*
610
 
mem_strdup(
611
 
/*=======*/
612
 
        const char*     str)    /*!< in: string to be copied */
613
 
{
614
 
        ulint   len = strlen(str) + 1;
615
 
        return((char*) memcpy(mem_alloc(len), str, len));
616
 
}
617
 
 
618
 
/**********************************************************************//**
619
 
Makes a NUL-terminated copy of a nonterminated string.
620
 
@return own: a copy of the string, must be deallocated with mem_free */
621
 
UNIV_INLINE
622
 
char*
623
 
mem_strdupl(
624
 
/*========*/
625
 
        const char*     str,    /*!< in: string to be copied */
626
 
        ulint           len)    /*!< in: length of str, in bytes */
627
 
{
628
 
        char*   s = (char*) mem_alloc(len + 1);
629
 
        s[len] = 0;
630
 
        return((char*) memcpy(s, str, len));
631
 
}
632
 
 
633
 
/**********************************************************************//**
634
 
Makes a NUL-terminated copy of a nonterminated string,
635
 
allocated from a memory heap.
636
 
@return own: a copy of the string */
637
 
UNIV_INLINE
638
 
char*
639
 
mem_heap_strdupl(
640
 
/*=============*/
641
 
        mem_heap_t*     heap,   /*!< in: memory heap where string is allocated */
642
 
        const char*     str,    /*!< in: string to be copied */
643
 
        ulint           len)    /*!< in: length of str, in bytes */
644
 
{
645
 
        char*   s = (char*) mem_heap_alloc(heap, len + 1);
646
 
        s[len] = 0;
647
 
        return((char*) memcpy(s, str, len));
648
 
}