void hxercise(HXFILE *hp, char const *str, FILE *fp) { int maxrec = hxmaxrec(hp), reclim = maxrec * 2, buflim = reclim; char *recspc = malloc(reclim), *rec = recspc + 5; char *bufspc = malloc(buflim), *buf = bufspc + 7; int i, test[2] = {}; # define OK(...) ++test[_ok(fp, __VA_ARGS__)] memset(recspc, fill, reclim); int len1 = hx_load(hp, rec, 0, str); OK(len1 > 0 && len1 <= maxrec, "hx_load(,,0,) returns: %d in 1..%d for '%s'", len1, maxrec, str); OK(memspan(recspc, fill, reclim), "hx_load(,rec,0,) leaves rec unchanged"); int len2 = hx_load(hp, rec, len1, str); OK(len2 == len1 && memspan(recspc, fill, 5) && memspan(rec+len1, fill, reclim-5-len1), "hx_load(,,%d,): %d", len1, len2); char rec2[len1]; memcpy(rec2, rec, len1); OK(!hx_diff(hp, rec2, rec), "diff of copy"); OK(hx_hash(hp, rec2) == hx_hash(hp, rec), "hash of copy"); memset(recspc, fill, reclim); for (i = 1; i < len1; ++i) { len2 = hx_load(hp, rec, i, str); OK(len2 == len1 && memspan(recspc, fill, 5) && !memcmp(rec, buf, i) && memspan(rec+i, fill, reclim-5-i), "hx_load(,,%d,): %d", i ,len2); } memcpy(buf, rec, len1); for (i = len1; i > 0; --i) { if (hx_test(hp, buf, i)) { buf[i] ^= 0x5A; OK(hx_test(hp, buf, i), "retest %d", i); } } memset(bufspc, fill, buflim); len2 = hx_save(hp, rec2, len1, buf, 0); OK(memspan(bufspc, fill, buflim), "hx_save(,,,,0) leaves target unchanged"); if (len2 > buflim - 5) { buflim *= 2; bufspc = realloc(bufspc, buflim); memset(bufspc, fill, buflim); buf = bufspc + 7; } int len3 = hx_save(hp, rec2, len1, buf, len2 + 1); OK(len3 == len2 && memspan(buf, fill, 7) && memspan(buf, fill, buflim-7-len2) && buf[len3-1] && (int)strlen(buf) == len3-1 && strchr(buf, '\t') && !strchr(buf, '\n'), "hx_save(,,%d,,%d): %d", len1, len2+1, len3); DEBUG2("+%d -%d: '%s'", test[0], test[1], str); free(recspc); free(bufspc); }
static void do_save(HXFILE * hp, FILE * fp) { int leng, maxrec = hxmaxrec(hp); int strsize = 2 * maxrec; char rec[maxrec], str[strsize]; while (0 < (leng = hxnext(hp, rec, maxrec))) { hx_save(hp, rec, leng, str, strsize); fprintf(fp, "%s\n", str); } }
// (size < 0) means hxhold: head is left locked on exit. // Usual usage is: hxhold(), modify record, hxput(). int hxget(HXFILE * hp, char *rp, int size) { HXLOCAL loc, *locp = &loc; int leng, rpos, loops, junk; HXBUF *bufp; char *recp; if (!hp || !rp) return HXERR_BAD_REQUEST; if (hxdebug > 1) { char buf[25] = {}; hx_save(hp, rp, size<0 ? -size-1 : size, buf, sizeof buf); DEBUG2("%s('%s...')", size < 0 ? "hold" : "get", buf, size); } ENTER(locp, hp, rp, 1); if (size >= 0) { locp->mode = F_RDLCK; _hxlockset(locp, HEAD_LOCK); // just lock head } else { _hxlockset(locp, HIGH_LOCK); // lock head, +split if > head HOLD_HEAD(locp); } if (IS_MMAP(hp)) _hxremap(locp); leng = 0; loops = HX_MAX_CHAIN; bufp = &locp->buf[0]; bufp->next = locp->head; do { if (!--loops) LEAVE(locp, HXERR_BAD_FILE); _hxload(locp, bufp, bufp->next); rpos = _hxfind(locp, bufp, locp->hash, rp, &junk); } while (rpos < 0 && bufp->next); if (rpos < 0) LEAVE(locp, 0); recp = bufp->data + rpos; leng = RECLENG(recp); memcpy(rp, RECDATA(recp), IMIN(leng, size<0? -size-1 : size)); LEAVE(locp, leng); }