enhanced qse_fma_h to have more consistency with qse_xma_h

This commit is contained in:
hyung-hwan 2010-08-27 00:26:28 +00:00
parent 530ab74909
commit 810134f0ea
23 changed files with 422 additions and 207 deletions

View File

@ -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.
*
* <pre>
* 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 <qse/cmn/fma.h>
* 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 <qse/cmn/fma.h>
* #include <qse/cmn/rbt.h>
* #include <qse/cmn/mem.h>
* #include <qse/cmn/stdio.h>
*
* 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 <qse/types.h>
@ -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 */

View File

@ -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 <qse/types.h>
#include <qse/macros.h>
/* 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

View File

@ -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 <qse/macros.h>
/** @file
* <qse/cmn/opt.h> defines functions and data structures to process
* This file defines functions and data structures to process
* command-line arguments.
*/

View File

@ -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 <qse/types.h>
@ -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);

View File

@ -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 <qse/cmn/xma.h>
* #include <qse/cmn/stdio.h>
* 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 <qse/types.h>
#include <qse/macros.h>
@ -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;

View File

@ -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 <qse/types.h>
/** @file
* <qse/macros.h> contains various useful macro definitions.
* This file contains various useful macro definitions.
*/
#if defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L)

View File

@ -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
* <qse/types.h> 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.
*/

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -1,4 +1,6 @@
#include <qse/cmn/fma.h>
#include <qse/cmn/rbt.h>
#include <qse/cmn/mem.h>
#include <qse/cmn/stdio.h>
#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;
}

View File

@ -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)