* kclib1のページ#8 -(by [[K]], 2019.04.18) ** (12) KSizPtr -サイズとポインタが組になった構造体です。主に可変サイズのデータを扱うために使います。 -これさえあれば、もしかしたらバッファが足りなくなるかもしれないとか、そういう不安から解放されます。 ---- -void KSizPtr_init(KSizPtr *w, int s1) --KSizPtrを初期化します。指定するのはとりあえず最初はどのくらいのサイズで始めるかということです。0以上のサイズで指定しますが、0を指定しても4バイトは確保します(KMallocの最低サイズ)。 -void KSizPtr_free(KSizPtr *w) --KSizPtrが管理しているメモリを解放させます。使い終わって捨てるときに使います。 --initしていないものはfreeできません。 -void KSizPtr_reserve(KSizPtr *w, int s0) --領域サイズs1がs0以上になるように調整させます。この関数を呼んだ後は、サイズs0までは問題なくアクセスできます。 -void KSizPtr_expand2(KSizPtr *w) --領域サイズs1を2倍にします。 -void KSizPtr_addChar(KSizPtr *w, int c) --利用中サイズsを参照して、末尾に1バイトを追加します。sは1増えます。 -void KSizPtr_addInt(KSizPtr *w, int i) --利用中サイズsを参照して、末尾に32ビット整数を追加します。sは4増えます。 -void KSizPtr_addPtr(KSizPtr *w, void *p) --利用中サイズsを参照して、末尾にポインタを追加します。sは4増えます。 -void KSizPtr_addBytes(KSizPtr *w, int s, const char *p) --利用中サイズsを参照して、末尾にsバイトのデータを追加します。sも増えます。 -void KSizPtr_insPtr(KSizPtr *w, int i, void *p) --先頭からiバイト目のところに、ポインタpを追加します。後ろはmemmoveで後ろにずらされます。 -void KSizPtr_delPtr(KSizPtr *w, int i) --先頭からiバイト目のところにあるデータを削除します。後ろはmemmoveで前にずらされます。 -int KSizPtr_vprintf(KSizPtr *w, const char *f, va_list arg) --利用中サイズsを参照して、末尾にvprintfの結果を追加します。sも増えます。 -int KSizPtr_printf(KSizPtr *w, const char *f, ...) --利用中サイズsを参照して、末尾にprintfの結果を追加します。sも増えます。 ---- -[内部実装] typedef struct KSizPtr_ { int s, s1; char *p; } KSizPtr; ---- -[内部実装] #include "kclib1.h" #include <string.h> #include <stdarg.h> #include <stdio.h> void KSizPtr_init(KSizPtr *w, int s1) { int i = KMalloc_index(s1); w->s = 0; w->s1 = KMalloc_t[i]; w->p = KPtrPool_alloc(KMalloc_work->p + i); } void KSizPtr_free(KSizPtr *w) { if (w->s1 == 0) kerrorExit("KSizPtr_free: over free error"); KMalloc_free(w->s1, w->p); w->s1 = 0; // たまにやらかすのでつけておくことにした. } void KSizPtr_reserve(KSizPtr *w, int s0) { if (w->s1 < s0) { int s2 = w->s1 << 1; while (s2 < s0) s2 <<= 1; w->p = KMalloc_realloc(w->s1, s2, w->p); w->s1 = s2; } } void KSizPtr_expand2(KSizPtr *w) { w->p = KMalloc_realloc(w->s1, w->s1 << 1, w->p); w->s1 <<= 1; } void KSizPtr_addChar(KSizPtr *w, int c) { if (w->s >= w->s1) KSizPtr_expand2(w); w->p[w->s] = c; w->s++; } void KSizPtr_addInt(KSizPtr *w, int i) { if (w->s + (int) sizeof (int) >= w->s1) KSizPtr_reserve(w, w->s + sizeof (int)); *((int *) &w->p[w->s]) = i; w->s += sizeof (int); } void KSizPtr_addPtr(KSizPtr *w, void *p) { if (w->s + (int) sizeof (void *) >= w->s1) KSizPtr_reserve(w, w->s + sizeof (void *)); *((void **) &w->p[w->s]) = p; w->s += sizeof (void *); } void KSizPtr_addBytes(KSizPtr *w, int s, const char *p) { if (s > 0) { if (w->s + s >= w->s1) KSizPtr_reserve(w, w->s + s); memcpy(w->p + w->s, p, s); } } void KSizPtr_insPtr(KSizPtr *w, int i, void *p) { if (w->s + (int) sizeof (void *) >= w->s1) KSizPtr_reserve(w, w->s + sizeof (void *)); if (w->s > i) memmove(w->p + i + sizeof (void *), w->p + i, w->s - i); *((void **) &w->p[i]) = p; w->s += sizeof (void *); } void KSizPtr_delPtr(KSizPtr *w, int i) { w->s -= sizeof (void *); if (w->s > i) memmove(w->p + i, w->p + i + sizeof (void *), w->s - i); } int KSizPtr_vprintf(KSizPtr *w, const char *f, va_list arg) { const int maxSiz = 1024 * 1024; char *b = KMalloc_alloc(maxSiz); int i = vsnprintf(b, maxSiz, f, arg); if (i < 0 || maxSiz <= i) kerrorExit("KSizPtr_vprintf: tmp-buf over"); KSizPtr_addBytes(w, i, b); KMalloc_free(maxSiz, b); return i; } int KSizPtr_printf(KSizPtr *w, const char *f, ...) { va_list arg; int i; va_start(arg, f); i = KSizPtr_vprintf(w, f, arg); va_end(arg); return i; } * こめんと欄 #comment