diff --git a/qse/include/qse/cmn/fma.h b/qse/include/qse/cmn/fma.h index d2224e4e..e8e0c143 100644 --- a/qse/include/qse/cmn/fma.h +++ b/qse/include/qse/cmn/fma.h @@ -22,20 +22,21 @@ #define _QSE_CMN_FMA_H_ /** @file - * This file defines a fixed-size block memory allocator. As the block size - * is known in advance, it achieves block allocation with little overhead. + * This file defines a fixed-size block memory allocator. + * As the block size is known in advance, it achieves block allocation + * with little overhead. * *
* chunk head(cnkhead) - * | chunk + * | * | +---------------------------------------------+ - * +--> | | f1 | f2 | | | + * +--> | | f1 | f2 | | | chunk #2 * +--|---------^------|----^--------------------+ * | | | | - * | +------+ +---+ +--------------+ chunk + * | +------+ +---+ +--------------+ * | | | | * | +-----------------|----V--------------|-------+ - * +---> | | | f3 | | f4 | + * +---> | | | f3 | | f4 | chunk #1 * +---------------------------------------^-----+ * | * free block head (freeblk) @@ -44,8 +45,122 @@ * The diagram above assumes that f1, f2, f3, and f4 are free blocks. * The chaining order depends on the allocation and deallocation order. * - * See #qse_fma_t for more information. Use #qse_xma_t for variable-size block - * allocation. + * See an example below. Note that it omits error handling. + * + * @code + * #include+ * int main () + * { + * qse_fma_t* fma; + * int* ptr1, * ptr2; + * + * // create a memory allocator for integer blocks up to 50. + * fma = qse_fma_open (QSE_NULL, 0, sizeof(int), 10, 5); + * + * // allocate two integer blocks + * ptr1 = (int*) qse_fma_alloc (fma, sizeof(int)); + * ptr2 = (int*) qse_fma_alloc (fma, sizeof(int)); + * + * *ptr1 = 20; *ptr2 = 99; + * + * // free the two blocks. + * qse_fma_free (fma, ptr1); + * qse_fma_free (fma, ptr2); + * + * // destroy the memory allocator + * qse_fma_close (fma); + * } + * @endcode + * + * The following example shows how to use the fixed-size block + * allocator for a dynamic data structure allocating fixed-size nodes. + * + * @code + * #include + * #include + * #include + * #include + * + * static qse_rbt_walk_t walk (qse_rbt_t* rbt, qse_rbt_pair_t* pair, void* ctx) + * { + * qse_printf (QSE_T("key = %lld, value = %lld\n"), + * *(long*)QSE_RBT_KPTR(pair), *(long*)QSE_RBT_VPTR(pair)); + * return QSE_RBT_WALK_FORWARD; + * } + * + * int main () + * { + * qse_fma_t* fma; + * qse_rbt_t rbt; + * qse_size_t blksize; + * long x; + * + * // prepare the fixed-size block allocator into the qse_mmgr_t interface + * qse_mmgr_t mmgr = + * { + * (qse_mmgr_alloc_t) qse_fma_alloc, + * (qse_mmgr_realloc_t) qse_fma_realloc, + * (qse_mmgr_free_t) qse_fma_free, + * QSE_NULL + * }; + * + * // the block size of a red-black tree is fixed to be: + * // key size + value size + internal node size. + * blksize = sizeof(long) + sizeof(long) + sizeof(qse_rbt_pair_t); + * + * // create a fixed-size block allocator which is created + * // with the default memory allocator. + * fma = qse_fma_open (QSE_MMGR_GETDFL(), 0, blksize, 10, 0); + * if (fma == QSE_NULL) + * { + * qse_printf (QSE_T("cannot open a memory allocator\n")); + * return -1; + * } + * + * // complete the qse_mmgr_t interface by providing the allocator. + * mmgr.udd = fma; + * + * // initializes the statically declared red-black tree. + * // can not call qse_rbt_open() which allocates the qse_rbt_t object. + * // as its size differs from the block size calculated above. + * if (qse_rbt_init (&rbt, &mmgr) == QSE_NULL) + * { + * qse_printf (QSE_T("cannot initialize a tree\n")); + * qse_fma_close (fma); + * return -1; + * } + * + * // perform more initializations for keys and values. + * qse_rbt_setcopier (&rbt, QSE_RBT_KEY, QSE_RBT_COPIER_INLINE); + * qse_rbt_setcopier (&rbt, QSE_RBT_VAL, QSE_RBT_COPIER_INLINE); + * qse_rbt_setscale (&rbt, QSE_RBT_KEY, QSE_SIZEOF(long)); + * qse_rbt_setscale (&rbt, QSE_RBT_VAL, QSE_SIZEOF(long)); + * + * // insert numbers into the red-black tree + * for (x = 10; x < 100; x++) + * { + * long y = x * x; + * if (qse_rbt_insert (&rbt, &x, 1, &y, 1) == QSE_NULL) + * { + * qse_printf (QSE_T("failed to insert. out of memory\n")); + * break; + * } + * } + * + * // print the tree contents + * qse_rbt_walk (&rbt, walk, QSE_NULL); + * + * // finalize the tree. + * qse_rbt_fini (&rbt); + * + * // destroy the memory allocator. + * qse_fma_close (fma); + * + * return 0; + * } + * @endcode + * + * Use #qse_xma_t for variable-size block allocation. */ #include @@ -73,27 +188,6 @@ struct qse_fma_blk_t /** @struct qse_fma_t * The qse_fma_t type defines a fixed-size block memory allocator. - * See the example below. Note that it omits error handling. - * @code - * qse_fma_t* fma; - * int* ptr1, * ptr2; - * - * // create a memory allocator for integer blocks up to 50. - * fma = qse_fma_open (QSE_NULL, 0, sizeof(int), 10, 5); - * - * // allocate two integer blocks - * ptr1 = (int*) qse_fma_alloc (fma); - * ptr2 = (int*) qse_fma_alloc (fma); - * - * *ptr1 = 20; *ptr2 = 99; - * - * // free the two blocks. - * qse_fma_free (fma, ptr1); - * qse_fma_free (fma, ptr2); - * - * // destroy the memory allocator - * qse_fma_close (fma); - * @endcode */ typedef struct qse_fma_t qse_fma_t; struct qse_fma_t @@ -122,9 +216,9 @@ QSE_DEFINE_COMMON_FUNCTIONS (fma) qse_fma_t* qse_fma_open ( qse_mmgr_t* mmgr, /**< outer memory manager */ qse_size_t xtnsize, /**< extension size in bytes */ - qse_size_t blksize, /**< block size in bytes */ + qse_size_t blksize, /**< fixed block size in bytes */ qse_size_t maxblks, /**< maximum numbers of blocks in a chunk */ - qse_size_t maxcnks /**< maximum numbers of chunks */ + qse_size_t maxcnks /**< maximum numbers of chunks. 0 for no limit */ ); /** @@ -135,14 +229,15 @@ void qse_fma_close ( ); /** - * The qse_fma_init() function initializes an memory allocator. + * The qse_fma_init() function initializes an memory allocator statically + * declared. */ qse_fma_t* qse_fma_init ( qse_fma_t* fma, /**< memory allocator */ qse_mmgr_t* mmgr, /**< outer memory manager */ - qse_size_t blksize, /**< block size in bytes */ + qse_size_t blksize, /**< fixed block size in bytes */ qse_size_t maxblks, /**< maximum numbers of blocks in a chunk */ - qse_size_t maxcnks /**< maximum numbers of chunks */ + qse_size_t maxcnks /**< maximum numbers of chunks. 0 for no limit */ ); /** @@ -153,15 +248,41 @@ void qse_fma_fini ( ); /** - * The qse_fma_alloc() function allocates a block. - * @return block pointer on success, QSE_NULL on failure + * The qse_fma_alloc() function allocates a block of the fixed block size + * specified during initialization regardless of the block size @a size + * requested so long as it is not greater than the fixed size. The function + * fails if it is greater. + * + * @return block pointer on success, #QSE_NULL on failure */ void* qse_fma_alloc ( - qse_fma_t* fma /**< memory allocator */ + qse_fma_t* fma, /**< memory allocator */ + qse_size_t size /**< block size in bytes*/ ); /** - * The qse_fma_alloc() function deallocates a block. + * The qse_fma_realloc() function is provided for consistency with other + * generic memory allocator which provides a reallocation function. + * Block resizing is meaningless for #qse_fma_t as it deals with fixed-size + * blocks. + * + * If the @a size requested is greater than the fixed block size of the memory + * allocator @a fma, the function fails; If the block @a blk is #QSE_NULL and + * the @a size requested is not greater than the fixed block size of the memory + * allocator @a fma, it allocates a block of the fixed size; If the block + * @a blk is not #QSE_NULL and the @a size requested is not greater than the + * fixed block size of the memory allocator @a fma, it returns the block @blk. + * + * @return block pointer on success, #QSE_NULL on failure + */ +void* qse_fma_realloc ( + qse_fma_t* fma, /**< memory allocator */ + void* blk, /**< memory block */ + qse_size_t size /**< block size in bytes*/ +); + +/** + * The qse_fma_free() function deallocates a block. */ void qse_fma_free ( qse_fma_t* fma, /**< memory allocator */ diff --git a/qse/include/qse/cmn/mem.h b/qse/include/qse/cmn/mem.h index 4a48fc66..953f6915 100644 --- a/qse/include/qse/cmn/mem.h +++ b/qse/include/qse/cmn/mem.h @@ -1,5 +1,5 @@ /* - * $Id: mem.h 287 2009-09-15 10:01:02Z hyunghwan.chung $ + * $Id: mem.h 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -21,13 +21,21 @@ #ifndef _QSE_CMN_MEM_H_ #define _QSE_CMN_MEM_H_ +/** @file + * This file defines functions and macros for memory manipulation. + */ + #include #include -/* gets a pointer to the default memory manager */ +/** + * The QSE_MMGR_GETDFL() macro returns the default memory manager. + */ #define QSE_MMGR_GETDFL() (qse_mmgr) -/* sets a pointer to the default memory manager */ +/** + * The QSE_MMGR_SETDFL() macro changes the default memory manager. + */ #define QSE_MMGR_SETDFL(m) ((qse_mmgr)=(m)) /* allocate a memory block */ @@ -46,163 +54,128 @@ extern "C" { #endif -/* - * NAME: holds a pointer to the default memory manager - * - * DESCRIPTION: - * The QSE_MMGR_GETDFL() macro returns the default memory manager. - * You may use QSE_MMGR_SETDFL() to change the default memory manager. +/** + * The qse_mmgr global variable holds a pointer to the default memory + * manager. Use QSE_MMGR_GETDFL() and QSE_MMGR_SETDFL() to manipulate it. */ extern qse_mmgr_t* qse_mmgr; -/* - * NAME: copy a memory block +/** + * The qse_memcpy() functions copies @a n bytes from the source memory block + * @a src to the destinaion memory block @a dst. The memory blocks must not + * overlap. Use qse_memmove() if they overlap. * - * DESCRIPTION: - * The qse_memcpy() functions copies n bytes from the source memory block src - * to the destinaion memory block dst. - * - * RETURNS: the destination memory block dst. - * - * WARNING: - * The memory blocks should not overlap. Use the qse_memmove() function if - * they overlap. + * @return destination memory block @a dst. */ - void* qse_memcpy ( - void* dst /* a pointer to the destination memory block */ , - const void* src /* a pointer to the source memory block */ , - qse_size_t n /* the number of bytes to copy */ + void* dst, /**< destination memory block */ + const void* src, /**< source memory block */ + qse_size_t n /**< number of bytes to copy */ ); -/* - * NAME: copy a memory block with more care +/** + * The qse_memmove() functions copies @a n bytes from the source memory block + * @a src to the destinaion memory block @a dst without corrupting overlapping + * zone. * - * DESCRIPTION: - * The qse_memmove() functions copies n bytes from the source memory block src - * to the destinaion memory block dst without corrupting overlapping zone. - * - * RETURNS: the destination memory block dst. + * @return destination memory block @a dst. */ void* qse_memmove ( - void* dst /* a pointer to the destination memory block */, - const void* src /* a pointer to the source memory block */, - qse_size_t n /* the number of bytes to copy */ + void* dst, /**< destination memory block */ + const void* src, /**< source memory block */ + qse_size_t n /**< number of bytes to copy */ ); /* - * NAME: fill a memory block + * The qse_memset() function fills leading @a n bytes of the destination + * memory block @a dst with the byte @a val. * - * DESCRIPTION: - * The qse_memset() function fills leading n bytes of the destination - * memory block dst with the byte val. - * - * RETURNS: the destination memory block dst + * @return destination memory block @a dst. */ void* qse_memset ( - void* dst /* a pointer to the destination memory block */, - int val /* the byte to fill the memory block with */, - qse_size_t n /* the number of bytes to fill */ + void* dst, /**< destination memory block */ + int val, /**< value fill the memory block with */ + qse_size_t n /**< number of bytes to fill */ ); -/* - * NAME: compare memory blocks - * - * DESCRIPTION: - * The qse_memcmp() function compares leading n bytes of two memory blocks - * s1 and s2. +/** + * The qse_memcmp() function compares leading *a n bytes of two memory blocks + * @a s1 and @a s2. * - * RETURNS: - * 0 if two memory ares have the same leadning n bytes. - * a positive number if the first different byte of s1 is greater than that - * of s2. - * a negative number if the first different byte of s1 is less than that of s2. + * @return + * 0 if two memory ares have the same leadning @a n bytes. + * positive number if the first different byte of s1 is greater than that of s2. + * negative number if the first different byte of s1 is less than that of s2. */ int qse_memcmp ( - const void* s1 /* a pointer to the first memory block to compare */, - const void* s2 /* a pointer to the second memory block to compare */, - qse_size_t n /* the number of bytes to compare */ + const void* s1, /**< first memory block to compare */ + const void* s2, /**< second memory block to compare */ + qse_size_t n /**< the number of bytes to compare */ ); -/* - * NAME: find a byte forward in a memory block - * - * DESCRIPTION: - * The qse_membyte() function scans the memory block s from the first byte - * up to the nth byte in search of the byte val. If it finds a match, - * it aborts scanning the memory block and returns the pointer to the matching - * location. +/** + * The qse_membyte() function scans the memory block @a s from the first byte + * up to the nth byte in search of the byte @a val. If it finds a match, + * it aborts scanning the memory block and returns the pointer to the matching + * location. * - * RETURNS: - * QSE_NULL if the byte val is not found. - * The pointer to the location in the memory block s matching the byte val + * @return + * #QSE_NULL if the byte @a val is not found. + * pointer to the location in the memory block @a s matching the byte @a val * if a match is found. */ void* qse_membyte ( - const void* s /* a pointer to the memory block to scan */, - int val /* a byte to find */, - qse_size_t n /* the number of bytes to scan */ + const void* s, /**< memory block to scan */ + int val, /**< byte to find */ + qse_size_t n /**< number of bytes to scan */ ); /* - * NAME: find a byte backward in a memory block - * - * DESCRIPTION: - * The qse_memrbyte() function scans the memory block s from the nth byte - * backward to the first byte in search of the byte val. If it finds a match, - * it aborts scanning the memory block and returns the pointer to the matching - * location. + * The qse_memrbyte() function scans the memory block @a s from the nth byte + * backward to the first byte in search of the byte @a val. If it finds a match, + * it aborts scanning the memory block and returns the pointer to the matching + * location. * - * RETURNS: - * QSE_NULL if the byte val is not found. - * The pointer to the location in the memory block s matching the byte val + * @return + * #QSE_NULL if the byte val is not found. + * pointer to the location in the memory block s matching the byte val * if a match is found. */ void* qse_memrbyte ( - const void* s /* a pointer to the memory block to scan */, - int val /* a byte to find */, - qse_size_t n /* the number of bytes to scan */ + const void* s, /**< memory block to scan */ + int val, /**< byte to find */ + qse_size_t n /**< number of bytes to scan */ ); -/* - * NAME: find a block of bytes forward in a memory block - * - * DESCRIPTION: - * The qse_memmem() functions scans the first hl bytes of the memory block hs - * in search of the byte block nd of the length nl bytes. +/** + * The qse_memmem() functions scans the first @a hl bytes of the memory + * block @a hs in search of the byte block @a nd of the length @a nl bytes. * - * RETURNS: - * QSE_NULL if the byte val is not found. - * The pointer to the location in the memory block s matching the byte val - * if a match is found. - * - * RETURNS: - * QSE_NULL if no match is found. - * The pointer to the start of the matching location if a match is found. + * @return + * #QSE_NULL if no match is found. + * pointer to the start of the matching location if a match is found. */ void* qse_memmem ( - const void* hs /* a pointer to the memory block to scan */, - qse_size_t hl /* the number of bytes to scan */, - const void* nd /* a pointer to the byte block to find */, - qse_size_t nl /* the number of bytes in the block */ + const void* hs, /**< memory block to scan */ + qse_size_t hl, /**< number of bytes to scan */ + const void* nd, /**< byte block to find */ + qse_size_t nl /**< number of bytes in the block */ ); /* - * NAME: find a block of bytes backward in a memory block + * The qse_memrmem() functions scans the first @a hl bytes of the memory + * block @a hs backward in search of the byte block @a nd of the length + * @a nl bytes. * - * DESCRIPTION: - * The qse_memrmem() functions scans the first hl bytes of the memory block hs - * backward in search of the byte block nd of the length nl bytes. - * - * RETURNS: - * QSE_NULL if no match is found. - * The pointer to the start of the matching location if a match is found. + * @return + * #QSE_NULL if no match is found. + * pointer to the start of the matching location if a match is found. */ void* qse_memrmem ( - const void* hs /* a pointer to the memory block to scan */, - qse_size_t hl /* the number of bytes to scan */, - const void* nd /* a pointer to the byte block to find */, - qse_size_t nl /* the number of bytes in the block */ + const void* hs, /**< memory block to scan */ + qse_size_t hl, /**< number of bytes to scan */ + const void* nd, /**< byte block to find */ + qse_size_t nl /**< number of bytes in the block */ ); #ifdef __cplusplus diff --git a/qse/include/qse/cmn/opt.h b/qse/include/qse/cmn/opt.h index 120ff821..e805b249 100644 --- a/qse/include/qse/cmn/opt.h +++ b/qse/include/qse/cmn/opt.h @@ -1,5 +1,5 @@ /* - * $Id: opt.h 287 2009-09-15 10:01:02Z hyunghwan.chung $ + * $Id: opt.h 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -25,7 +25,7 @@ #include /** @file - * defines functions and data structures to process + * This file defines functions and data structures to process * command-line arguments. */ diff --git a/qse/include/qse/cmn/stdio.h b/qse/include/qse/cmn/stdio.h index 7255068d..35f0348b 100644 --- a/qse/include/qse/cmn/stdio.h +++ b/qse/include/qse/cmn/stdio.h @@ -22,8 +22,7 @@ #define _QSE_CMN_STDIO_H_ /** @file - * #qse_char_t friendly stdio wrapper functions are defined in this file. - * + * This file defines stdio wrapper functions for #qse_char_t. */ #include @@ -89,6 +88,9 @@ QSE_FILE* qse_fopen (const qse_char_t* path, const qse_char_t* mode); QSE_FILE* qse_popen (const qse_char_t* cmd, const qse_char_t* mode); /** + * The qse_getline() function read a line from a file pointer @a fp + * until a new line character is met. + * * @return -2 on error, -1 on eof, length of data read on success */ qse_ssize_t qse_getline (qse_char_t **buf, qse_size_t *n, QSE_FILE *fp); diff --git a/qse/include/qse/cmn/xma.h b/qse/include/qse/cmn/xma.h index f9360e67..09c52906 100644 --- a/qse/include/qse/cmn/xma.h +++ b/qse/include/qse/cmn/xma.h @@ -27,7 +27,36 @@ * larger memory chunk allocated with an outer memory allocator. * Typically, an outer memory allocator is a standard memory allocator * like malloc(). You can isolate memory blocks into a particular chunk. - * See #qse_xma_t for an example. + * + * See the example below. Note it omits error handling. + * + * @code + * #include + * #include + * int main () + * { + * qse_xma_t* xma; + * void* ptr1, * ptr2; + * + * // create a new memory allocator obtaining a 100K byte zone + * // with the default memory allocator + * xma = qse_xma_open (QSE_NULL, 0, 100000L); + * + * ptr1 = qse_xma_alloc (xma, 5000); // allocate a 5K block from the zone + * ptr2 = qse_xma_alloc (xma, 1000); // allocate a 1K block from the zone + * ptr1 = qse_xma_realloc (xma, ptr1, 6000); // resize the 5K block to 6K. + * + * qse_xma_dump (xma, qse_printf); // dump memory blocks + * + * // the following two lines are not actually needed as the allocator + * // is closed after them. + * qse_xma_free (xma, ptr2); // dispose of the 1K block + * qse_xma_free (xma, ptr1); // dispose of the 6K block + * + * qse_xma_close (xma); // destroy the memory allocator + * return 0; + * } + * @endcode */ #include #include @@ -39,28 +68,6 @@ /** @struct qse_xma_t * The qse_xma_t type defines a simple memory allocator over a memory zone. * It can obtain a relatively large zone of memory and manage it. - * - * @code - * qse_xma_t* xma; - * void* ptr1, * ptr2; - * - * // create a new memory allocator obtaining a 100K byte zone - * // with the default memory allocator - * xma = qse_xma_open (QSE_NULL, 0, 100000L); - * - * ptr1 = qse_xma_alloc (xma, 5000); // allocate a 5K block from the zone - * ptr2 = qse_xma_alloc (xma, 1000); // allocate a 1K block from the zone - * ptr1 = qse_xma_realloc (xma, ptr1, 6000); // resize the 5K block to 6K. - * - * qse_xma_dump (xma, qse_printf); // dump memory blocks - * - * // the following two lines are not actually needed as the allocator - * // is closed after them. - * qse_xma_free (xma, ptr2); // dispose of the 1K block - * qse_xma_free (xma, ptr1); // dispose of the 6K block - * - * qse_xma_close (xma); // destroy the memory allocator - * @endcode */ typedef struct qse_xma_t qse_xma_t; diff --git a/qse/include/qse/macros.h b/qse/include/qse/macros.h index 93af813e..179d3eaf 100644 --- a/qse/include/qse/macros.h +++ b/qse/include/qse/macros.h @@ -1,5 +1,5 @@ /* - * $Id: macros.h 338 2010-07-30 13:24:19Z hyunghwan.chung $ + * $Id: macros.h 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -24,7 +24,7 @@ #include /** @file - * contains various useful macro definitions. + * This file contains various useful macro definitions. */ #if defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L) diff --git a/qse/include/qse/types.h b/qse/include/qse/types.h index 7662d813..a0d5e12e 100644 --- a/qse/include/qse/types.h +++ b/qse/include/qse/types.h @@ -1,5 +1,5 @@ /* - * $Id: types.h 338 2010-07-30 13:24:19Z hyunghwan.chung $ + * $Id: types.h 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -22,7 +22,7 @@ #define _QSE_TYPES_H_ /**@file - * defines various common basic types designed to be + * This file defines various common basic types designed to be * cross-platform. These types are preferred over native data types. */ diff --git a/qse/lib/cmn/fio.c b/qse/lib/cmn/fio.c index f835ba50..45569cfb 100644 --- a/qse/lib/cmn/fio.c +++ b/qse/lib/cmn/fio.c @@ -1,5 +1,5 @@ /* - * $Id: fio.c 323 2010-04-05 12:50:01Z hyunghwan.chung $ + * $Id: fio.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -81,6 +81,8 @@ qse_fio_t* qse_fio_init ( { qse_fio_hnd_t handle; + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + QSE_MEMSET (fio, 0, QSE_SIZEOF(*fio)); fio->mmgr = mmgr; diff --git a/qse/lib/cmn/fma.c b/qse/lib/cmn/fma.c index 6e5c7eb1..f17dc9ac 100644 --- a/qse/lib/cmn/fma.c +++ b/qse/lib/cmn/fma.c @@ -29,7 +29,7 @@ qse_fma_t* qse_fma_open ( { qse_fma_t* fma; - if (mmgr == QSE_NULL) + if (mmgr == QSE_NULL) { mmgr = QSE_MMGR_GETDFL(); @@ -61,13 +61,14 @@ qse_fma_t* qse_fma_init ( qse_fma_t* fma, qse_mmgr_t* mmgr, qse_size_t blksize, qse_size_t maxblks, qse_size_t maxcnks) { + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + QSE_MEMSET (fma, 0, QSE_SIZEOF(*fma)); fma->mmgr = mmgr; - if (blksize <= QSE_SIZEOF(qse_fma_blk_t)) + if (blksize < QSE_SIZEOF(qse_fma_blk_t)) blksize = QSE_SIZEOF(qse_fma_blk_t); if (maxblks <= 0) maxblks = 1; - if (maxcnks <= 0) maxcnks = 1; fma->blksize = blksize; fma->maxblks = maxblks; @@ -78,6 +79,7 @@ qse_fma_t* qse_fma_init ( void qse_fma_fini (qse_fma_t* fma) { + /* destroys the chunks allocated */ while (fma->cnkhead) { qse_fma_cnk_t* next = fma->cnkhead->next; @@ -93,7 +95,7 @@ static QSE_INLINE qse_fma_cnk_t* add_chunk (qse_fma_t* fma) qse_size_t i; /* check if there are too many chunks */ - if (fma->numcnks >= fma->maxcnks) return QSE_NULL; + if (fma->maxcnks && fma->numcnks >= fma->maxcnks) return QSE_NULL; /* allocate a chunk */ cnk = (qse_fma_cnk_t*) QSE_MMGR_ALLOC (fma->mmgr, @@ -118,10 +120,16 @@ static QSE_INLINE qse_fma_cnk_t* add_chunk (qse_fma_t* fma) return cnk; } -void* qse_fma_alloc (qse_fma_t* fma) +void* qse_fma_alloc (qse_fma_t* fma, qse_size_t size) { void* blk; + QSE_ASSERTX (size <= fma->blksize, + "You must not request a block larger than the fixed size set in the allocator. Use a generic allocator instead" + ); + + if (size > fma->blksize) return QSE_NULL; + if ((blk = fma->freeblk) == QSE_NULL) { if (add_chunk (fma) == QSE_NULL) return QSE_NULL; @@ -131,9 +139,23 @@ void* qse_fma_alloc (qse_fma_t* fma) return blk; } +void* qse_fma_realloc (qse_fma_t* fma, void* blk, qse_size_t size) +{ + if (blk) + { + QSE_ASSERTX (size <= fma->blksize, + "A block can be enlarged with a fixed-size block allocator. Use a generic allocator instead" + ); + + if (size > fma->blksize) return QSE_NULL; + return blk; + } + + return qse_fma_alloc (fma, size); +} + void qse_fma_free (qse_fma_t* fma, void* blk) { ((qse_fma_blk_t*)blk)->next = fma->freeblk; fma->freeblk = blk; } - diff --git a/qse/lib/cmn/htb.c b/qse/lib/cmn/htb.c index ff1fea38..9ba64617 100644 --- a/qse/lib/cmn/htb.c +++ b/qse/lib/cmn/htb.c @@ -1,5 +1,5 @@ /* - * $Id: htb.c 332 2010-07-13 11:25:24Z hyunghwan.chung $ + * $Id: htb.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -248,11 +248,14 @@ void qse_htb_close (htb_t* htb) htb_t* qse_htb_init (htb_t* htb, mmgr_t* mmgr, size_t capa, int factor) { + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + QSE_ASSERTX (capa > 0, "The initial capacity should be greater than 0. Otherwise, it is adjusted to 1 in the release mode"); QSE_ASSERTX (factor >= 0 && factor <= 100, "The load factor should be between 0 and 100 inclusive. In the release mode, a value out of the range is adjusted to 100"); + /* some initial adjustment */ if (capa <= 0) capa = 1; if (factor > 100) factor = 100; diff --git a/qse/lib/cmn/lda.c b/qse/lib/cmn/lda.c index c8192224..6df8bdc1 100644 --- a/qse/lib/cmn/lda.c +++ b/qse/lib/cmn/lda.c @@ -1,5 +1,5 @@ /* - * $Id: lda.c 327 2010-05-10 13:15:55Z hyunghwan.chung $ + * $Id: lda.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -108,10 +108,10 @@ lda_t* qse_lda_open (mmgr_t* mmgr, size_t ext, size_t capa) if (mmgr == QSE_NULL) return QSE_NULL; } - lda = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(lda_t) + ext); - if (lda == QSE_NULL) return QSE_NULL; + lda = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(lda_t) + ext); + if (lda == QSE_NULL) return QSE_NULL; - if (qse_lda_init (lda, mmgr, capa) == QSE_NULL) + if (qse_lda_init (lda, mmgr, capa) == QSE_NULL) { QSE_MMGR_FREE (mmgr, lda); return QSE_NULL; @@ -128,6 +128,8 @@ void qse_lda_close (lda_t* lda) lda_t* qse_lda_init (lda_t* lda, mmgr_t* mmgr, size_t capa) { + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + QSE_MEMSET (lda, 0, QSE_SIZEOF(*lda)); lda->mmgr = mmgr; diff --git a/qse/lib/cmn/pio.c b/qse/lib/cmn/pio.c index 075152a7..58daa6fb 100644 --- a/qse/lib/cmn/pio.c +++ b/qse/lib/cmn/pio.c @@ -1,5 +1,5 @@ /* - * $Id: pio.c 316 2009-12-14 12:50:11Z hyunghwan.chung $ + * $Id: pio.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -72,7 +72,6 @@ void qse_pio_close (qse_pio_t* pio) qse_pio_t* qse_pio_init ( qse_pio_t* pio, qse_mmgr_t* mmgr, const qse_char_t* cmd, int oflags) { - qse_pio_hnd_t handle[6] = { QSE_PIO_HND_NIL, @@ -92,6 +91,8 @@ qse_pio_t* qse_pio_init ( int i, minidx = -1, maxidx = -1; + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + #ifdef _WIN32 SECURITY_ATTRIBUTES secattr; PROCESS_INFORMATION procinfo; diff --git a/qse/lib/cmn/rbt.c b/qse/lib/cmn/rbt.c index b0dffff6..db5e137e 100644 --- a/qse/lib/cmn/rbt.c +++ b/qse/lib/cmn/rbt.c @@ -192,6 +192,8 @@ void qse_rbt_close (rbt_t* rbt) rbt_t* qse_rbt_init (rbt_t* rbt, mmgr_t* mmgr) { + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + /* do not zero out the extension */ QSE_MEMSET (rbt, 0, SIZEOF(*rbt)); rbt->mmgr = mmgr; diff --git a/qse/lib/cmn/rex.c b/qse/lib/cmn/rex.c index ce8a26f5..9dcbad53 100644 --- a/qse/lib/cmn/rex.c +++ b/qse/lib/cmn/rex.c @@ -1,5 +1,5 @@ /* - * $Id: rex.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ + * $Id: rex.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -118,6 +118,8 @@ struct cand_t qse_rex_t* qse_rex_init (qse_rex_t* rex, qse_mmgr_t* mmgr, qse_rex_node_t* code) { + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + QSE_MEMSET (rex, 0, QSE_SIZEOF(*rex)); rex->mmgr = mmgr; diff --git a/qse/lib/cmn/sio.c b/qse/lib/cmn/sio.c index 46b35814..7ec06bd7 100644 --- a/qse/lib/cmn/sio.c +++ b/qse/lib/cmn/sio.c @@ -1,5 +1,5 @@ /* - * $Id: sio.c 340 2010-08-01 13:13:38Z hyunghwan.chung $ + * $Id: sio.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -178,6 +178,8 @@ qse_sio_t* qse_sio_init ( { int mode; + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + QSE_MEMSET (sio, 0, QSE_SIZEOF(*sio)); sio->mmgr = mmgr; diff --git a/qse/lib/cmn/sll.c b/qse/lib/cmn/sll.c index 0bf6685f..df480f23 100644 --- a/qse/lib/cmn/sll.c +++ b/qse/lib/cmn/sll.c @@ -1,5 +1,5 @@ /* - * $Id: sll.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ + * $Id: sll.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -124,6 +124,8 @@ void qse_sll_close (sll_t* sll) sll_t* qse_sll_init (sll_t* sll, mmgr_t* mmgr) { + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + /* do not zero out the extension */ QSE_MEMSET (sll, 0, SIZEOF(*sll)); diff --git a/qse/lib/cmn/str_dyn.c b/qse/lib/cmn/str_dyn.c index a0fdcda3..ac049fae 100644 --- a/qse/lib/cmn/str_dyn.c +++ b/qse/lib/cmn/str_dyn.c @@ -1,5 +1,5 @@ /* - * $Id: str_dyn.c 297 2009-10-08 13:09:19Z hyunghwan.chung $ + * $Id: str_dyn.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -57,6 +57,8 @@ void qse_str_close (qse_str_t* str) qse_str_t* qse_str_init (qse_str_t* str, qse_mmgr_t* mmgr, qse_size_t capa) { + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + QSE_MEMSET (str, 0, QSE_SIZEOF(qse_str_t)); str->mmgr = mmgr; diff --git a/qse/lib/cmn/tio.c b/qse/lib/cmn/tio.c index ceaa12d8..a4b4b5ce 100644 --- a/qse/lib/cmn/tio.c +++ b/qse/lib/cmn/tio.c @@ -1,5 +1,5 @@ /* - * $Id: tio.c 287 2009-09-15 10:01:02Z hyunghwan.chung $ + * $Id: tio.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -58,6 +58,8 @@ int qse_tio_close (qse_tio_t* tio) qse_tio_t* qse_tio_init (qse_tio_t* tio, qse_mmgr_t* mmgr) { + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + QSE_MEMSET (tio, 0, QSE_SIZEOF(*tio)); tio->mmgr = mmgr; diff --git a/qse/lib/cmn/xma.c b/qse/lib/cmn/xma.c index c05594b8..fe1113c0 100644 --- a/qse/lib/cmn/xma.c +++ b/qse/lib/cmn/xma.c @@ -142,6 +142,8 @@ qse_xma_t* qse_xma_init (qse_xma_t* xma, qse_mmgr_t* mmgr, qse_size_t zonesize) qse_xma_blk_t* free; qse_size_t xfi; + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + /* round 'zonesize' to be the multiples of ALIGN */ zonesize = ((zonesize + ALIGN - 1) / ALIGN) * ALIGN; diff --git a/qse/lib/cut/cut.c b/qse/lib/cut/cut.c index 8abdc32a..330c371a 100644 --- a/qse/lib/cut/cut.c +++ b/qse/lib/cut/cut.c @@ -109,6 +109,8 @@ void qse_cut_close (qse_cut_t* cut) static qse_cut_t* qse_cut_init (qse_cut_t* cut, qse_mmgr_t* mmgr) { + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + QSE_MEMSET (cut, 0, QSE_SIZEOF(*cut)); cut->mmgr = mmgr; diff --git a/qse/lib/sed/sed.c b/qse/lib/sed/sed.c index d4d1f6f5..453d8244 100644 --- a/qse/lib/sed/sed.c +++ b/qse/lib/sed/sed.c @@ -1,5 +1,5 @@ /* - * $Id: sed.c 344 2010-08-17 13:15:14Z hyunghwan.chung $ + * $Id: sed.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -75,6 +75,8 @@ void qse_sed_close (qse_sed_t* sed) static qse_sed_t* qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr) { + if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); + QSE_MEMSET (sed, 0, QSE_SIZEOF(*sed)); sed->mmgr = mmgr; sed->errstr = qse_sed_dflerrstr; diff --git a/qse/samples/cmn/fma.c b/qse/samples/cmn/fma.c index 58c44562..67a343ab 100644 --- a/qse/samples/cmn/fma.c +++ b/qse/samples/cmn/fma.c @@ -1,4 +1,6 @@ #include +#include +#include #include #define R(f) \ @@ -12,7 +14,7 @@ static int test1 () int i; int* ptr[100]; - qse_fma_t* fma = qse_fma_open (QSE_NULL, 0, sizeof(int), 10, 5); + qse_fma_t* fma = qse_fma_open (QSE_MMGR_GETDFL(), 0, sizeof(int), 10, 5); if (fma == QSE_NULL) { qse_printf (QSE_T("cannot open fma\n")); @@ -21,7 +23,7 @@ static int test1 () for (i = 0; i < 100; i++) { - ptr[i] = qse_fma_alloc (fma); + ptr[i] = qse_fma_alloc (fma, sizeof(int)); if (ptr[i]) { qse_printf (QSE_T("%d %p\n"), i, ptr[i]); @@ -50,7 +52,7 @@ static int test1 () for (i = 0; i < 100; i++) { - ptr[i] = qse_fma_alloc (fma); + ptr[i] = qse_fma_alloc (fma, sizeof(int)); if (ptr[i]) { qse_printf (QSE_T("%d %p\n"), i, ptr[i]); @@ -63,8 +65,71 @@ static int test1 () return 0; } +static qse_rbt_walk_t walk (qse_rbt_t* rbt, qse_rbt_pair_t* pair, void* ctx) +{ + qse_printf (QSE_T("key = %lld, value = %lld\n"), + *(long*)QSE_RBT_KPTR(pair), *(long*)QSE_RBT_VPTR(pair)); + return QSE_RBT_WALK_FORWARD; +} + +static int test2 () +{ + qse_mmgr_t mmgr = + { + (qse_mmgr_alloc_t) qse_fma_alloc, + (qse_mmgr_realloc_t) qse_fma_realloc, + (qse_mmgr_free_t) qse_fma_free, + QSE_NULL + }; + qse_fma_t* fma; + qse_rbt_t rbt; + qse_size_t blksize; + long x; + + /* key */ /* value */ /* internal node */ + blksize = sizeof(long) + sizeof(long) + sizeof(qse_rbt_pair_t); + + fma = qse_fma_open (QSE_MMGR_GETDFL(), 0, blksize, 10, 0); + if (fma == QSE_NULL) + { + qse_printf (QSE_T("cannot open a memory allocator\n")); + return -1; + } + + mmgr.udd = fma; + if (qse_rbt_init (&rbt, &mmgr) == QSE_NULL) + { + qse_printf (QSE_T("cannot initialize a tree\n")); + qse_fma_close (fma); + return -1; + } + + qse_rbt_setcopier (&rbt, QSE_RBT_KEY, QSE_RBT_COPIER_INLINE); + qse_rbt_setcopier (&rbt, QSE_RBT_VAL, QSE_RBT_COPIER_INLINE); + qse_rbt_setscale (&rbt, QSE_RBT_KEY, QSE_SIZEOF(long)); + qse_rbt_setscale (&rbt, QSE_RBT_VAL, QSE_SIZEOF(long)); + + for (x = 10; x < 100; x++) + { + long y = x * x; + if (qse_rbt_insert (&rbt, &x, 1, &y, 1) == QSE_NULL) + { + qse_printf (QSE_T("failed to insert. out of memory\n")); + break; + } + } + + qse_rbt_walk (&rbt, walk, QSE_NULL); + + qse_rbt_fini (&rbt); + qse_fma_close (fma); + + return 0; +} + int main () { R (test1); + R (test2); return 0; } diff --git a/qse/samples/cmn/rbt.c b/qse/samples/cmn/rbt.c index fc7aef60..dbb85c56 100644 --- a/qse/samples/cmn/rbt.c +++ b/qse/samples/cmn/rbt.c @@ -102,7 +102,6 @@ qse_printf (QSE_T("deleting %d\n"), i); static int test2 () { qse_rbt_t* s1; - int i; s1 = qse_rbt_open (QSE_MMGR_GETDFL(), 0); if (s1 == QSE_NULL)