Index: ossp-pkg/act/Makefile.in RCS File: /v/ossp/cvs/ossp-pkg/act/Makefile.in,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/act/Makefile.in,v' 2>/dev/null --- Makefile.in 2000/08/18 15:35:57 1.3 +++ Makefile.in 2000/08/20 13:57:52 1.4 @@ -13,8 +13,8 @@ PRE = act_p.h LIB = libact.a -SRC = act_mem.c act_ctx.c act_lib.c act_hash.c act_hash_fct.c act_hash_oh.c act_hash_lh.c -OBJ = act_mem.o act_ctx.o act_lib.o act_hash.o act_hash_fct.o act_hash_oh.o act_hash_lh.o +SRC = act_mem.c act_ctx.c act_str.c act_lib.c act_hash.c act_hash_fct.c act_hash_oh.c act_hash_lh.c +OBJ = act_mem.o act_ctx.o act_str.o act_lib.o act_hash.o act_hash_fct.o act_hash_oh.o act_hash_lh.o TST = act_test _VERSION_FILE = \ Index: ossp-pkg/act/act_hash.c RCS File: /v/ossp/cvs/ossp-pkg/act/act_hash.c,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/act/act_hash.c,v' 2>/dev/null --- act_hash.c 2000/08/18 15:58:08 1.3 +++ act_hash.c 2000/08/20 13:57:53 1.4 @@ -134,6 +134,17 @@ int act_hash_size(act_hash_t *h, long *pb, long *pe) { insist(h != NULL, NULL); + insist(pb != NULL, NULL); + insist(pe != NULL, NULL); return method(h, size)(h->h_ctx, h->h_data, pb, pe); } +/* return summary of current internal status */ +int act_hash_status(act_hash_t *h, char *ps, int ns) +{ + insist(h != NULL, NULL); + insist(ps != NULL, NULL); + insist(ns > 0, NULL); + return method(h, status)(h->h_ctx, h->h_data, ps, ns); +} + Index: ossp-pkg/act/act_hash.h RCS File: /v/ossp/cvs/ossp-pkg/act/act_hash.h,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/act/act_hash.h,v' 2>/dev/null --- act_hash.h 2000/08/18 15:58:08 1.3 +++ act_hash.h 2000/08/20 13:57:53 1.4 @@ -46,6 +46,7 @@ typedef int (*act_hash_lookup_t) (act_ctx_t *, void *, void *, int, void **, int *); typedef int (*act_hash_delete_t) (act_ctx_t *, void *, void *, int); typedef int (*act_hash_size_t) (act_ctx_t *, void *, long *, long *); +typedef int (*act_hash_status_t) (act_ctx_t *, void *, char *, int); typedef int (*act_hash_free_t) (act_ctx_t *, void *); /* the dispatch structure for the hash implementation method */ @@ -56,6 +57,7 @@ act_hash_lookup_t m_lookup; act_hash_delete_t m_delete; act_hash_size_t m_size; + act_hash_status_t m_status; act_hash_free_t m_free; } act_hash_method_t; @@ -69,6 +71,7 @@ int act_hash_lookup(act_hash_t *, void *, int, void **, int *); int act_hash_delete(act_hash_t *, void *, int); int act_hash_size(act_hash_t *, long *, long *); +int act_hash_status(act_hash_t *, char *, int); int act_hash_free(act_hash_t *); #define act_hash_mth(name) \ @@ -90,16 +93,22 @@ __act_hash_fct_proto(djbx33a); __act_hash_fct_proto(djbx33x); +__act_hash_fct_proto(jedi); __act_hash_fct_proto(vocong); +__act_hash_fct_proto(cdt); +__act_hash_fct_proto(jotcl); __act_hash_fct_proto(bjddj); __act_hash_fct_proto(crc32); +__act_hash_fct_proto(teadm); __act_hash_fct_proto(cpoaat); __act_hash_fct_proto(ozsdbm); __act_hash_fct_proto(fonovo); __act_hash_fct_proto(kazlib); __act_hash_fct_proto(buzhash); __act_hash_fct_proto(pearson); -__act_hash_fct_proto(jotcl); +__act_hash_fct_proto(rifkin); +__act_hash_fct_proto(asu); +__act_hash_fct_proto(holub); __act_hash_fct_proto(cbu); __act_hash_fct_proto(cvs); Index: ossp-pkg/act/act_hash_lh.c RCS File: /v/ossp/cvs/ossp-pkg/act/act_hash_lh.c,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/act/act_hash_lh.c,v' 2>/dev/null --- act_hash_lh.c 2000/08/19 14:21:08 1.6 +++ act_hash_lh.c 2000/08/20 13:57:53 1.7 @@ -33,44 +33,69 @@ ** collision chains as the backend data structure. Some ideas were ** taken over from MIKAEL PETTERSON's Linear Hashing enhancements ** (1993). +** +** Linear Hashing can be summarized as following: ** -** The internal structure of the linear hashing table is illustrated in -** the following figure: +** o drawback of classical hashing is that the hash table is of +** fixed size; if table is filled, the table has to be expanded; +** unfortunately this requires re-hashing of all existing elements. +** +** o Extendible Hashing solves this problem by allowing the table +** to grow without complete re-hashing of elements every time; +** unfortunately the table must double in size to grow - not a +** problem for small tables, but a disadvantage for large ones. +** +** o Linear Hashing allows the table to grow one bucket at a time: +** table is extended when its load factor passes a critical value; buckets +** are split "in sequence" starting at index 0 and ending at 2^n; two +** hashing functions are always "active" - one for split buckets and one +** for unsplit; when last bucket (the 2^n-th one) is split, the table has +** been doubled in size, and a new cycle of splitting begins starting at +** bucket 0. +** +** The internal structure of the linear hashing table is illustrated +** in the following figure: ** ** -----BEGIN EMBEDDED OBJECT----- ** Content-type: application/fig ** Description: linear hashing structure layout ** Version: eo/1.0 -** H4sIAKaXnjkCA5WRzwrCMAyHz+YpAp430nR/3FlQBrv5BGMWFWSI2/tjG9uuNy2l -** 9Gt/5SMk+1N/Rl0yDON8XabxZeBo5tW8oZ+nu1lgMKu9IYIiKong8phvTwMFg2Ii -** ZGBkJFR2t1iTPQrL9qfD78WuGnZY2dTtjrYzZZ//L1TaG1WTgtQl2UZZXla+Gq5S -** ELlkG+V5D75MTZRA49rooghZVq2DLDRYwMkkipBnbYMsjEZAZG2dQJa14jDnMDoB -** J5MoQv681IHCnCJJeyXdyKVWrX+rtVOLsAtNFYpv8AGUMVDTPQMAAA== +** H4sIACfenzkCA62WTYvbMBCGz+tfIeixJOhb9rnQsrC3XntxE7ExdZ0ldhf233dG +** sr6aNllRE2K90USPpNGMRx8+P34hYs+bp346zof+xTaf7LTYS/M4HU52bp7sAr8I +** aRile0qbr8P0PNpmxxvGKSW84QQ/jOwYMURRQlFx+CtK9wMb1TwQBlYB3R1NLX6x +** P7TQX0OkK5IbmguNNGdLagXDT/jyzoM5PCLYRC6HzRIJ/+BKZYIJVGhLCoyVXNhm +** 4EXFJV15SaG1Eu1Z5UPIsNSk0FDhZt6Gxaq4Aa86JDprUn8su725bIFdTOM68fgz +** 1foTLZRWNWgd0UYVqo0xklQVWvKAlkIVCoHemlQduo3oThXKAVtaKI9mKxqOLJwj +** zc8RbbJ5QMGgn2i0EshfTGjIIskV8Y4xmfDRmUXizWnMvVm06/KZHloMSPcakVvs +** gwvYh49vE9PJxCCgmzlMUHSPgdmEKJVWZTz970Q64rtSubDgm00kecBLVSo30VWs +** 7djNmfi7fIeK822oyVF6O2rmFb4htY3UNlHD60HQe+9LlzVGpdasRTC01yWJ/RsY +** 0m896SBczXS2pGR90XA56EpFplp1/WC0zgnU+c2XikyZUCoyVedfHdFGFSpeLDJV +** hXbp6oCuVGTKhFKRqTp0G9GdKpQJpSJTIYx9KKdjZLU1I5bQKGR5Ldpgji6go/BX +** m3iNkd4L+GAaotU7CMDuPqkZ5BoDjovg43Cxh+V8eftGKbseyfbK0DaM1OFWgzey +** 2T7/hHvx/PeB5ZTS1U6fOMv5ZTfaVzveGwgn28FAoXCtuPHDeRyHeThP5HDqh+k9 +** E7P19efi/od9+3jsl/4dEzNm0O04EkP9dbgsv/qRnPr5RJb++2gd4zf8ksj2KwwA +** AA== ** -----END EMBEDDED OBJECT----- ** -** As you can see, it consists of four levels of memory chunks: -** 1. the top-level structure one sees in the API -** 2. the hash table consisting of a single directory and one or -** more directory segments -** 3. the collision chain consisting of element structures -** 4. the actual elements consisting of key and value structures +** As you can see, it consists of four classes of memory chunks: +** 1. a top-level structure which acts as the primary handle +** 2. the virtual hash table consisting of a single (growing) +** directory and one or more (fixed size) directory segments +** 3. the collision chains consisting of element structures +** 4. the actual elements consisting of key+value structures */ #include "act_p.h" /* fixed size (number of pointers) of the directory and of each segment */ #define INITDIRSIZE 256 /* can be an arbitrary value */ -#define SEGMENTSIZE 512 /* = 2^9, must be a power of 2 for below fast arithmetic */ - -/* calculate index in directory and segment from virtual array index */ -#define DIRINDEX(addr) ((addr) >> 9) /* == ((addr) / SEGMENTSIZE) */ -#define SEGINDEX(addr) ((addr) & (512-1)) /* == ((addr) % SEGMENTSIZE) */ +#define SEGMENTSIZE 512 /* has to be a power of 2 for below arithmetic */ -/* load of hash table (maximum should be between 2 and 4) */ -#define MINLOADFCTR 1 -#define MAXLOADFCTR 2 +/* the borders for the hash table load */ +#define MINLOADFCTR 1 /* should be between 0 and 1 */ +#define MAXLOADFCTR 2 /* should be between 2 and 4 */ -/* the per-element structure (keep this as small as possible!) */ +/* the per-element structure (keep as small as possible!) */ typedef struct element_st element_t; struct element_st { element_t *e_next; /* pointer to next element in collision chain */ @@ -80,10 +105,6 @@ void *e_endptr; /* pointer to end of key+data memory chunk */ }; -/* on-the-fly calculate lengths of key and data to reduce memory in element_t */ -#define el_keylen(el) ((char *)((el)->e_datptr)-(char *)((el)->e_keyptr)) -#define el_datlen(el) ((char *)((el)->e_endptr)-(char *)((el)->e_datptr)) - /* the hash table segments */ typedef struct segment_st segment_t; struct segment_st { @@ -102,6 +123,14 @@ segment_t **h_dir; /* pointer to directory */ }; +/* on-the-fly calculate index into directory and segment from virtual array index */ +#define DIRINDEX(addr) (int)((addr) / SEGMENTSIZE) +#define SEGINDEX(addr) (int)((addr) % SEGMENTSIZE) + +/* on-the-fly calculate lengths of key and data to reduce memory in element_t */ +#define el_keylen(el) ((char *)((el)->e_datptr)-(char *)((el)->e_keyptr)) +#define el_datlen(el) ((char *)((el)->e_endptr)-(char *)((el)->e_datptr)) + /* create the hash table structure */ static act_hash_lh_t * act_hash_lh_new( @@ -116,7 +145,8 @@ /* allocate and clear hash table directory */ h->h_dirsize = INITDIRSIZE; - if ((h->h_dir = (segment_t **)act_mem_alloc_ctx(ctx, h->h_dirsize * sizeof(segment_t *))) == NULL) { + if ((h->h_dir = (segment_t **)act_mem_alloc_ctx( + ctx, h->h_dirsize * sizeof(segment_t *))) == NULL) { errno_safe(act_mem_free_ctx(ctx, h)); return NULL; } @@ -482,6 +512,90 @@ return TRUE; } +/* calculate total size of hash table */ +static int +act_hash_lh_status( + act_ctx_t *ctx, + act_hash_lh_t *h, + char *pstatus, + int nstatus) +{ + int bytes, elements; + int dirsize, segsize; + int segments; + int chains; + int chainlen_min, chainlen_max; + int chainlen_all, chainlen_avg; + double used; + int i, j, k; + element_t *el; + + /* argument consistency check */ + if (h == NULL) + return_errno(FALSE, EINVAL); + + /* initial values */ + bytes = 0; + elements = 0; + dirsize = h->h_dirsize; + segsize = SEGMENTSIZE; + segments = 0; + chains = 0; + chainlen_min = 0; + chainlen_max = 0; + chainlen_all = 0; + chainlen_avg = 0; + used = 0; + + /* add bytes for top-level structure and directory */ + bytes += sizeof(act_hash_lh_t); + bytes += h->h_dirsize * sizeof(segment_t *); + + /* add size for segments */ + for (i = 0; i < h->h_dirsize; i++) { + if (h->h_dir[i] == NULL) + continue; + segments++; + bytes += sizeof(segment_t); + /* add size of elements */ + for (j = 0; j < SEGMENTSIZE; j++) { + if (h->h_dir[i]->s_element[j] == NULL) + continue; + chains++; + el = h->h_dir[i]->s_element[j]; + k = 0; + for (; el != NULL; el = el->e_next) { + elements++; + k++; + /* add size of key+data */ + bytes += sizeof(element_t); + bytes += el_keylen(el); + bytes += el_datlen(el); + } + chainlen_all += k; + if (chainlen_min == 0 || chainlen_min > k) + chainlen_min = k; + if (chainlen_max == 0 || chainlen_max < k) + chainlen_max = k; + } + } + + /* calculate total table usage */ + used = ((double)chains / (double)(segments*SEGMENTSIZE)) * 100; + if (chains == 0) + chainlen_avg = 0; + else + chainlen_avg = chainlen_all / chains; + + /* provide results */ + act_snprintf(pstatus, nstatus, + "size=%d@%dB dir=1*%dB seg=%d*%dB chains=%d@%d/%d/%d usage=%0.1f", + elements, bytes, dirsize, segments, segsize, + chains, chainlen_min, chainlen_avg, chainlen_max, used); + + return TRUE; +} + /* destroy the whole hash table */ static int act_hash_lh_free( @@ -531,6 +645,7 @@ (act_hash_lookup_t) act_hash_lh_lookup, (act_hash_delete_t) act_hash_lh_delete, (act_hash_size_t) act_hash_lh_size, + (act_hash_status_t) act_hash_lh_status, (act_hash_free_t) act_hash_lh_free }; Index: ossp-pkg/act/act_hash_oh.c RCS File: /v/ossp/cvs/ossp-pkg/act/act_hash_oh.c,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/act/act_hash_oh.c,v' 2>/dev/null --- act_hash_oh.c 2000/08/18 15:58:09 1.3 +++ act_hash_oh.c 2000/08/20 13:57:53 1.4 @@ -133,6 +133,14 @@ return TRUE; } +/* find out the size of the hash table */ +static int +act_hash_oh_status( + act_ctx_t *ctx, act_hash_oh_t *h, char *pstatus, int *nstatus) +{ + return TRUE; +} + /* free the hash table structure */ static int act_hash_oh_free( @@ -168,6 +176,7 @@ (act_hash_lookup_t) act_hash_oh_lookup, (act_hash_delete_t) act_hash_oh_delete, (act_hash_size_t) act_hash_oh_size, + (act_hash_status_t) act_hash_oh_status, (act_hash_free_t) act_hash_oh_free }; Index: ossp-pkg/act/act_str.c RCS File: /v/ossp/cvs/ossp-pkg/act/act_str.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/act/act_str.c,v' | diff -u /dev/null - -L'ossp-pkg/act/act_str.c' 2>/dev/null --- ossp-pkg/act/act_str.c +++ - 2024-04-23 17:07:25.376953408 +0200 @@ -0,0 +1,712 @@ +/* +** Act - Abstract Container Type Library +** Copyright (c) 1999-2000 Ralf S. Engelschall +** +** This file is part of Act, a library for dealing with Abstract +** Container Types which can be found at http://www.ossp.org/pkg/act/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** act_str.c: string formatting (implementation) +*/ + +/* + * Copyright Patrick Powell 1995 + * This code is based on code written by Patrick Powell + * It may be used for any purpose as long as this notice remains intact + * on all source code distributions. + */ + +/* + * This code contains numerious changes and enhancements which were + * made by lots of contributors over the last years to Patrick Powell's + * original code: + * + * o Patrick Powell (1995) + * o Brandon Long (1996, for Mutt) + * o Thomas Roessler (1998, for Mutt) + * o Michael Elkins (1998, for Mutt) + * o Andrew Tridgell (1998, for Samba) + * o Luke Mewburn (1999, for LukemFTP) + * o Ralf S. Engelschall (1999, for OSSP) + */ + +#include /* for size_t */ +#include /* for malloc(3) */ +#include /* for va_list */ +#include /* for isdigit(3) */ +#include /* for integer max */ + +#include "act_p.h" + +#if HAVE_LONGLONG +#define LLONG long long +#else +#define LLONG long +#endif + +#if HAVE_LONGDOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif + +static void fmtstr (char *, size_t *, size_t, char *, int, int, int); +static void fmtint (char *, size_t *, size_t, LLONG, int, int, int, int); +static void fmtfp (char *, size_t *, size_t, LDOUBLE, int, int, int); +static void dopr_outch (char *, size_t *, size_t, int); + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* conversion flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 +#define DP_C_LLONG 4 + +/* some handy macros */ +#define char_to_int(p) (p - '0') +#define MAX(p,q) ((p >= q) ? p : q) +#define NUL '\0' + +static void +dopr( + char *buffer, + size_t maxlen, + size_t *retlen, + const char *format, + va_list args) +{ + char ch; + LLONG value; + LDOUBLE fvalue; + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + + state = DP_S_DEFAULT; + flags = currlen = cflags = min = 0; + max = -1; + ch = *format++; + + if (maxlen == -1) + /* possible maximum size in a size_t */ + maxlen = (~(1<<((sizeof(size_t)*8)-2))); + + while (state != DP_S_DONE) { + if ((ch == NUL) || (currlen >= maxlen)) + state = DP_S_DONE; + + switch (state) { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + dopr_outch(buffer, &currlen, maxlen, ch); + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) { + min = 10 * min + char_to_int(ch); + ch = *format++; + } else if (ch == '*') { + min = va_arg(args, int); + ch = *format++; + state = DP_S_DOT; + } else + state = DP_S_DOT; + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else + state = DP_S_MOD; + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) { + if (max < 0) + max = 0; + max = 10 * max + char_to_int(ch); + ch = *format++; + } else if (ch == '*') { + max = va_arg(args, int); + ch = *format++; + state = DP_S_MOD; + } else + state = DP_S_MOD; + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + if (*format == 'l') { + cflags = DP_C_LLONG; + format++; + } else + cflags = DP_C_LONG; + ch = *format++; + break; + case 'q': + cflags = DP_C_LLONG; + ch = *format++; + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) { + case 'd': + case 'i': + switch (cflags) { + case DP_C_SHORT: + value = (short int)va_arg(args, int); + break; + case DP_C_LONG: + value = va_arg(args, long int); + break; + case DP_C_LLONG: + value = va_arg(args, LLONG); + break; + default: + value = va_arg(args, int); + break; + } + fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'X': + flags |= DP_F_UP; + /* FALLTHROUGH */ + case 'x': + case 'o': + case 'u': + flags |= DP_F_UNSIGNED; + switch (cflags) { + case DP_C_SHORT: + value = (unsigned short int)va_arg(args, unsigned int); + break; + case DP_C_LONG: + value = (LLONG)va_arg(args, unsigned long int); + break; + case DP_C_LLONG: + value = va_arg(args, unsigned LLONG); + break; + default: + value = (LLONG)va_arg(args, unsigned int); + break; + } + fmtint(buffer, &currlen, maxlen, value, + ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), + min, max, flags); + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'E': + flags |= DP_F_UP; + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + break; + case 'G': + flags |= DP_F_UP; + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + break; + case 'c': + dopr_outch(buffer, &currlen, maxlen, va_arg(args, int)); + break; + case 's': + strvalue = va_arg(args, char *); + if (max < 0) + max = maxlen; + fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max); + break; + case 'p': + value = (long)va_arg(args, void *); + fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags); + break; + case 'n': /* XXX */ + if (cflags == DP_C_SHORT) { + short int *num; + num = va_arg(args, short int *); + *num = currlen; + } else if (cflags == DP_C_LONG) { /* XXX */ + long int *num; + num = va_arg(args, long int *); + *num = (long int) currlen; + } else if (cflags == DP_C_LLONG) { /* XXX */ + LLONG *num; + num = va_arg(args, LLONG *); + *num = (LLONG) currlen; + } else { + int *num; + num = va_arg(args, int *); + *num = currlen; + } + break; + case '%': + dopr_outch(buffer, &currlen, maxlen, ch); + break; + case 'w': + /* not supported yet, treat as next char */ + ch = *format++; + break; + default: + /* unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + break; + } + } + if (currlen >= maxlen - 1) + currlen = maxlen - 1; + if (buffer != NULL) + buffer[currlen] = NUL; + *retlen = currlen; + return; +} + +static void +fmtstr( + char *buffer, + size_t *currlen, + size_t maxlen, + char *value, + int flags, + int min, + int max) +{ + int padlen, strln; + int cnt = 0; + + if (value == 0) + value = ""; + for (strln = 0; value[strln] != '\0'; strln++) + ; + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; + + while ((padlen > 0) && (cnt < max)) { + dopr_outch(buffer, currlen, maxlen, ' '); + --padlen; + ++cnt; + } + while (*value && (cnt < max)) { + dopr_outch(buffer, currlen, maxlen, *value++); + ++cnt; + } + while ((padlen < 0) && (cnt < max)) { + dopr_outch(buffer, currlen, maxlen, ' '); + ++padlen; + ++cnt; + } +} + +static void +fmtint( + char *buffer, + size_t *currlen, + size_t maxlen, + LLONG value, + int base, + int min, + int max, + int flags) +{ + int signvalue = 0; + unsigned LLONG uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; + int zpadlen = 0; + int caps = 0; + + if (max < 0) + max = 0; + uvalue = value; + if (!(flags & DP_F_UNSIGNED)) { + if (value < 0) { + signvalue = '-'; + uvalue = -value; + } else if (flags & DP_F_PLUS) + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + if (flags & DP_F_UP) + caps = 1; + do { + convert[place++] = + (caps ? "0123456789ABCDEF" : "0123456789abcdef") + [uvalue % (unsigned) base]; + uvalue = (uvalue / (unsigned) base); + } while (uvalue && (place < 20)); + if (place == 20) + place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX(max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) + zpadlen = 0; + if (spadlen < 0) + spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; + + /* spaces */ + while (spadlen > 0) { + dopr_outch(buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* sign */ + if (signvalue) + dopr_outch(buffer, currlen, maxlen, signvalue); + + /* zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + dopr_outch(buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + /* digits */ + while (place > 0) + dopr_outch(buffer, currlen, maxlen, convert[--place]); + + /* left justified spaces */ + while (spadlen < 0) { + dopr_outch(buffer, currlen, maxlen, ' '); + ++spadlen; + } + return; +} + +static LDOUBLE +abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + if (value < 0) + result = -value; + return result; +} + +static LDOUBLE +pow10(int exp) +{ + LDOUBLE result = 1; + while (exp) { + result *= 10; + exp--; + } + return result; +} + +static long +round(LDOUBLE value) +{ + long intpart; + intpart = (long) value; + value = value - intpart; + if (value >= 0.5) + intpart++; + return intpart; +} + +static void +fmtfp( + char *buffer, + size_t *currlen, + size_t maxlen, + LDOUBLE fvalue, + int min, + int max, + int flags) +{ + int signvalue = 0; + LDOUBLE ufvalue; + char iconvert[20]; + char fconvert[20]; + int iplace = 0; + int fplace = 0; + int padlen = 0; + int zpadlen = 0; + int caps = 0; + long intpart; + long fracpart; + + if (max < 0) + max = 6; + ufvalue = abs_val(fvalue); + if (fvalue < 0) + signvalue = '-'; + else if (flags & DP_F_PLUS) + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + + intpart = (long)ufvalue; + + /* sorry, we only support 9 digits past the decimal because of our + conversion method */ + if (max > 9) + max = 9; + + /* we "cheat" by converting the fractional part to integer by + multiplying by a factor of 10 */ + fracpart = round((pow10(max)) * (ufvalue - intpart)); + + if (fracpart >= pow10(max)) { + intpart++; + fracpart -= pow10(max); + } + + /* convert integer part */ + do { + iconvert[iplace++] = + (caps ? "0123456789ABCDEF" + : "0123456789abcdef")[intpart % 10]; + intpart = (intpart / 10); + } while (intpart && (iplace < 20)); + if (iplace == 20) + iplace--; + iconvert[iplace] = 0; + + /* convert fractional part */ + do { + fconvert[fplace++] = + (caps ? "0123456789ABCDEF" + : "0123456789abcdef")[fracpart % 10]; + fracpart = (fracpart / 10); + } while (fracpart && (fplace < 20)); + if (fplace == 20) + fplace--; + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) + zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + dopr_outch(buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + dopr_outch(buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) { + dopr_outch(buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch(buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]); + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0) { + dopr_outch(buffer, currlen, maxlen, '.'); + + while (fplace > 0) + dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]); + } + while (zpadlen > 0) { + dopr_outch(buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (padlen < 0) { + dopr_outch(buffer, currlen, maxlen, ' '); + ++padlen; + } + return; +} + +static void +dopr_outch( + char *buffer, + size_t *currlen, + size_t maxlen, + int c) +{ + if (*currlen < maxlen) { + if (buffer != NULL) + buffer[(*currlen)] = (char)c; + (*currlen)++; + } + return; +} + +intern int +act_vsnprintf( + char *str, + size_t count, + const char *fmt, + va_list args) +{ + size_t retlen; + + if (str != NULL) + str[0] = NUL; + dopr(str, count, &retlen, fmt, args); + return retlen; +} + +intern int +act_snprintf( + char *str, + size_t count, + const char *fmt, + ...) +{ + va_list ap; + int rv; + + va_start(ap, fmt); + rv = act_vsnprintf(str, count, fmt, ap); + va_end(ap); + return rv; +} + +intern char * +act_vasprintf( + const char *fmt, + va_list ap) +{ + char *rv; + int n; + + n = act_vsnprintf(NULL, -1, fmt, ap); + if ((rv = (char *)malloc(n+1)) == NULL) + return NULL; + act_vsnprintf(rv, n+1, fmt, ap); + return rv; +} + +intern char * +act_asprintf( + const char *fmt, + ...) +{ + va_list ap; + char *rv; + + va_start(ap, fmt); + rv = act_vasprintf(fmt, ap); + va_end(ap); + return rv; +} + Index: ossp-pkg/act/act_test.c RCS File: /v/ossp/cvs/ossp-pkg/act/act_test.c,v co -q -kk -p'1.3' '/v/ossp/cvs/ossp-pkg/act/act_test.c,v' | diff -u /dev/null - -L'ossp-pkg/act/act_test.c' 2>/dev/null --- ossp-pkg/act/act_test.c +++ - 2024-04-23 17:07:25.379837956 +0200 @@ -0,0 +1,116 @@ + +#include + +#include "act_p.h" +#include "act_hash.h" + +struct kd { + char *k; + char *d; +}; + +#define act_hash_insert_str(h,k,v,o) \ + act_hash_insert((h),(k),strlen((k)),(v),strlen((v))+1,(o)) +#define act_hash_lookup_str(h,k,v) \ + act_hash_lookup((h),(k),strlen((k)),(v),NULL) +#define act_hash_delete_str(h,k) \ + act_hash_delete((h),(k),strlen((k))) + +int main(int argc, char *argv[]) +{ + act_hash_t *h; + char buf[1024]; + char buf2[1024]; + long i; + FILE *fp; + act_ctx_t *ctx; + char s[1024]; + char *cp; + + act_init(); + + ctx = act_ctx_dup(act_ctx_default, NULL); + act_ctx_set(ctx, ACT_HASH_FUNC, act_hash_fct(cdt)); + + if ((h = act_hash_new(ctx)) == NULL) { + perror("act_hash_new"); + exit(1); + } + + act_ctx_free(ctx); + + act_hash_status(h, s, sizeof s); + fprintf(stderr, "%s\n", s); + + fprintf(stderr, "\n**INSERT**\n\n"); + + fp = fopen("../data/words", "r"); + i = 1; + while (fgets(buf, sizeof(buf), fp) != NULL) { + buf[strlen(buf)-1] = '\0'; + sprintf(buf2, "%ld", i); + act_hash_insert_str(h, buf, buf2, FALSE); + if ( (i < 100 && i % 10 == 0) + || (i < 1000 && i % 100 == 0) + || (i < 10000 && i % 1000 == 0) + || (i < 100000 && i % 10000 == 0) + || (i < 1000000 && i % 100000 == 0)) { + act_hash_status(h, s, sizeof s); + fprintf(stderr, "%s\n", s); + } + i++; + } + fclose(fp); + + act_hash_status(h, s, sizeof s); + fprintf(stderr, "%s\n", s); + + fprintf(stderr, "\n**LOOKUP**\n\n"); + + fp = fopen("../data/words", "r"); + i = 1; + while (fgets(buf, sizeof(buf), fp) != NULL) { + buf[strlen(buf)-1] = '\0'; + sprintf(buf2, "%ld", i); + if (!act_hash_lookup_str(h, buf, (void **)&cp)) + fprintf(stderr, "failed to lookup `%s'\n", buf); + else { + if (strcmp(cp, buf2) != 0) + fprintf(stderr, "value failed for `%s': %s <-> %s\n", buf, buf2, cp); + } + i++; + } + fclose(fp); + + act_hash_status(h, s, sizeof s); + fprintf(stderr, "%s\n", s); + + fprintf(stderr, "\n**DELETE**\n\n"); + + fp = fopen("../data/words", "r"); + while (fgets(buf, sizeof(buf), fp) != NULL) { + buf[strlen(buf)-1] = '\0'; + if ( (i < 100 && i % 10 == 0) + || (i < 1000 && i % 100 == 0) + || (i < 10000 && i % 1000 == 0) + || (i < 100000 && i % 10000 == 0) + || (i < 1000000 && i % 100000 == 0)) { + act_hash_status(h, s, sizeof s); + fprintf(stderr, "%s\n", s); + } + if (!act_hash_delete_str(h, buf)) + fprintf(stderr, "failed to delete `%s'\n", buf); + i--; + } + fclose(fp); + + act_hash_status(h, s, sizeof s); + fprintf(stderr, "%s\n", s); + + if (!act_hash_free(h)) { + perror("act_hash_free"); + exit(1); + } + exit(0); +} + Index: ossp-pkg/act/configure.in RCS File: /v/ossp/cvs/ossp-pkg/act/Attic/configure.in,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/act/Attic/configure.in,v' 2>/dev/null --- configure.in 2000/08/18 15:35:57 1.2 +++ configure.in 2000/08/20 13:57:53 1.3 @@ -28,7 +28,8 @@ fi )dnl if test ".$enable_debug" = .yes; then - CFLAGS="$CFLAGS -ggdb3" + LDFLAGS="$LDFLAGS -g -ggdb3" + CFLAGS="$CFLAGS -g -ggdb3" CFLAGS="$CFLAGS -pedantic" CFLAGS="$CFLAGS -Wall -Wshadow -Wpointer-arith -Wcast-align" CFLAGS="$CFLAGS -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline"