/* * ugly-but-mostly-portable packed-int-saving routines * determines endianness at run-time */ #include #include #include "psave.h" /* indices to halves of a short */ static int low; static int high; /* set indices depending on endianness */ void set_end(void) { low = 1; low = *((unsigned char *)&low); high = 1 - low; } size_t writebyte(FILE *f, unsigned char byte) { return fwrite(&byte, 1, 1, f); } size_t readbyte(FILE *f, unsigned char *bytep) { return fread(bytep, 1, 1, f); } typedef union { unsigned short s; unsigned char c[2]; } buf; /* write at most 8 bits */ int writebits(FILE *f, unsigned t, int b) { static buf u = {0}; static int used = 0; assert(b <= 8); assert(sizeof(short) == 2); if (!b) /* zero means flush buffer */ b = 8 - used; u.s |= (t << used); used += b; if (used>=8) { if (writebyte(f, u.c[high]) != 1) return 1; u.s >>= 8; used -= 8; } return 0; } int psave(unsigned a[], int nelems, int bits, FILE *f) { int b, i; unsigned t; set_end(); for (i=0; i0; t >>= 8, b -= 8) { if (writebits(f, t & 0xff, b>8 ? 8 : b)) return i-1; } } writebits(f, 0, 0); return i; } /* read at most 8 bits */ unsigned readbits(FILE *f, int b) { static buf u; static int start = 8; static int end = 8; unsigned t; assert(b <= 8); assert(sizeof(short) == 2); if (end-start < b) { u.s >>= end-8; start -= end-8; readbyte(f, &u.c[low]); end=16; } t = (u.s >> start) & ~(~0 << b); start += b; return t; } int prestore(unsigned a[], int maxnelems, int bits, FILE *f) { int b, k, i; unsigned t,s; set_end(); for (i=0; i0; s += 8, b -= 8) { k = readbits(f, b>8 ? 8 : b); t |= k << s; } a[i] = t; } return i; }