/* * dyna.h -- 動的に大きくなるバッファ * Copyright (C) 1991-1993 by candy * Thu Oct 31 10:13:53 JST 1996 * DYNA_IZ() 不要に * Sat May 3 00:27:48 JST 1997 * BOGUS_REALLOC */ /* * $Id: dyna.h,v 3.6 1996/11/28 09:01:21 candy Exp $ */ #ifndef __DYNA_H /* [ */ #define __DYNA_H #ifdef BOGUS_REALLOC #undef realloc #define realloc(p,s) ((p)?((realloc)(p,s)):malloc(s)) #endif /* * NAME * STRUCT_DYNA - 構造体の宣言(の一部!!) * * SYNOPSIS * struct DYNA STRUCT_DYNA(TYPE); * * DESCRIPTION * TYPE 型を要素とする動的に大きくなる配列を扱う構造体 * struct DYNA * を宣言します。 * * EXAPMLE * struct CHAR_BUF STRUCT_DYNA(char); 文字バッファ * struct LIST_BUF STRUCT_DYNA(char *); 文字列のリスト * のように宣言します。 * TYPE の書式には制限があって、定義 * TYPE * identifier; * において、identifier が TYPE へのポインタとなるようなものしか書けません。 * 例えば * STRUCT_DYNA(char **) はいいけれど * STRUCT_DYNA(int (*)()) はだめです。 */ #define STRUCT_DYNA(TYPE) \ { \ unsigned int more, size, used; \ TYPE *buf; \ TYPE *spare; \ } /* * NAME * DYNA_IZ - 構造体の初期化 * * SYNOPSIS * void DYNA_IZ(struct DYNA *dyna, unsigned int nmore); * * DESCRIPTION * 構造体を初期化します。 * dyna には STRUCT_DYNA で宣言した構造体のアドレスを与えます。 * nmore には一度に増加する要素の数を指定します。 * * EXAMPLE * struct LIST_BUF STRUCT_DYNA(char *) list_buf; * の時、 * DYNA_IZ(&list_buf, 64); * のように初期化します。 */ #define DYNA_IZ(dyna, nmore) ((void)( \ (dyna)->more = (nmore), \ (dyna)->used = (dyna)->size = 0, \ (dyna)->buf = (void *)0 \ )) /* * NAME * DYNA_BRK - 配列の拡大 * * SYNOPSIS * TYPE *DYNA_BRK(struct DYNA *dyna, unsigned int nmore); * * DESCRIPTION * 構造体の配列を nmore 個だけ拡大します。 * DYNA_NEXT() が自動的に実行するので普通は関係ありません。 * 成功なら NULL 以外を返し、失敗なら NULL を返します。 * * EXAMPLE * struct LIST_BUF STRUCT_DYNA(char *) list_buf; * DYNA_IZ(&list_buf, 64); * の時、 * if (DYNA_BRK(&list_buf, 16) == NULL) * goto no_memory; * などとします。 */ #define DYNA_BRK(dyna, nmore) ( \ (dyna)->spare = (dyna)->buf, \ (dyna)->size += (nmore), \ (dyna)->buf = realloc((dyna)->buf, (dyna)->size * sizeof((dyna)->buf[0])), \ (((dyna)->buf != (void *)0) ? (dyna)->buf \ : ((dyna)->buf = (dyna)->spare, \ (dyna)->size -= (nmore), \ (void *)0)) \ ) /* * NAME * DYNA_NEXT - バッファの拡大 * * SYNOPSIS * TYPE *DYNA_NEXT(struct DYNA *dyna); * * DESCRIPTION * 配列の新しい要素のアドレスを返します。 * 使用領域が 1 増えます。 * 足りない場合は DYNA_BRK() を呼び出します。 * 失敗なら NULL を返します。 * * EXAMPLE * struct LIST_BUF STRUCT_DYNA(char *)list_buf; * char **next; * DYNA_IZ(&list_buf, 64); * の時、 * if ((next = DYNA_NEXT(&list_buf)) == NULL) * goto no_memory; * *next = malloc(256); * などとします。 */ #define DYNA_NEXT(dyna) ( \ ((dyna)->used >= (dyna)->size && DYNA_BRK(dyna, \ ((dyna)->more ? (dyna)->more : 256)) == (void *)0) \ ? (void *)0 \ : (dyna)->buf + (dyna)->used++ \ ) /* * NAME * DYNA_ALLOC - バッファの拡大 * * SYNOPSIS * TYPE *DYNA_ALLOC(struct DYNA *dyna, unsigned int n); * * DESCRIPTION * 配列の中の新しい n 個の連続した要素のアドレスを返します。 * 使用領域が n 増えます。 * 足りない場合は DYNA_BRK() を呼び出します。 * 失敗なら NULL を返します。 * * EXAMPLE * struct CHAR_BUF STRUCT_DYNA(char) char_buf; * char *next; * DYNA_IZ(&char_buf, 256); * の時、 * if ((next = DYNA_ALLOC(&char_buf, strlen(s) + 1)) == NULL) * goto no_memory; * strcpy(next, s); * などとします。 */ #define DYNA_ALLOC(dyna, nmore) ( \ ((dyna)->used + (nmore) > (dyna)->size && DYNA_BRK(dyna, (dyna)->more + (nmore)) == (void *)0) \ ? ((void *)0)\ : ((dyna)->used += (nmore), (dyna)->buf + (dyna)->used - (nmore))\ ) /* * NAME * DYNA_RESET - バッファを空にする * * SYNOPSIS * void DYNA_RESET(struct DYNA *dyna) * * DESCRIPTION * バッファを空にします(使用領域を 0 にします)。 * dyna には STRUCT_DYNA で宣言した構造体のアドレスを与えます。 */ #define DYNA_RESET(dyna) ((void)((dyna)->used = 0)) /* * NAME * DYNA_UNGROW - バッファの縮小 * * SYNOPSIS * void DYNA_UNGROW(struct DYNA *dyna, unsigned int n); * * DESCRIPTION * バッファの大きさ(使用領域)が 0 でなければ、n 要素分縮小します。 * */ #define DYNA_UNGROW(dyna, n) ((void)((dyna)->used > (n) ? ((dyna)->used -= (n)) : ((dyna)->used = 0))) /* * NAME * DYNA_BUF - バッファのアドレス * * SYNOPSIS * TYPE *DYNA_BUF(struct DYNA *dyna); * * DESCRIPTION * バッファの最初の要素のアドレスを返します。 * DYNA_BRK() や DYNA_NEXT() によって値が変化しますので、 * それらを呼び出した後は以前の値は無効になります。 */ #define DYNA_BUF(dyna) ((dyna)->buf) /* * NAME * DYNA_USED - バッファの大きさ * * SYNOPSIS * unsigned int DYNA_USED(struct DYNA *dyna); * * DESCRIPTION * バッファの大きさを返します。 * DYNA_IZ() 直後は 0 で、 * DYNA_NEXT() する毎に + 1 します。 */ #define DYNA_USED(dyna) ((dyna)->used) #endif /* ] !__DYNA_H */