vcio.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 2003-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#include "vchdr.h"
#include "vchuff.h"
** Some of these are stolen from the Sfio library and modified
** to deal only with memory buffers.
**
** Written by Kiem-Phong Vo (kpv@research.att.com)
*/
/* base-128 unsigned coding */
#if __STD_C
#else
Vcint_t v;
#endif
{
ssize_t n;
*code = v&127;
while((v >>= 7) > 0)
switch(n)
}
return n;
}
#if __STD_C
#else
#endif
{
int n;
Vcint_t v;
v = (n = *ptr++)&127;
while(n & 128)
return v;
}
/* base 256 coding */
#if __STD_C
#else
Vcint_t v;
#endif
{
ssize_t n;
*code = v&255;
while((max >>= 8) > 0)
if(io)
switch(n)
}
}
return n;
}
#if __STD_C
#else
#endif
{
Vcint_t v;
v = *ptr++;
while((max >>= 8) > 0)
v = (v <<= 8) | *ptr++;
return v;
}
/* A value v can be coded using two letters A and Z by treating v-1
** as the rank of a string of A's and Z's listed in lexicographic order.
** This coding is useful for coding runs of a letter, say A, using just
** another companion letter. Below are the codes of the first fourteen
** (2+4+8) integers using A and Z:
**
** 0 A 2 AA 6 AAA
** 1 Z 3 ZA 7 ZAA
** 4 AZ 8 AZA
** 5 ZZ 9 ZZA
** 10 AAZ
** 11 ZAZ
** 12 AZZ
** 13 ZZZ
*/
#if __STD_C
#else
Vcint_t v; /* value to encode */
Vcchar_t a; /* 1st coding letter */
Vcchar_t z; /* 2nd coding letter */
#endif
{
ssize_t n;
for(;;)
{ *ptr++ = (v&1) == 0 ? a : z;
if((v -= 2) < 0)
break;
else v >>= 1;
}
return n;
}
#if __STD_C
#else
Vcchar_t a; /* 1st coding letter */
Vcchar_t z; /* 2nd coding letter */
#endif
{
int d;
Vcint_t v;
v = -1; d = 1;
{ if(*ptr == a)
{ v += d;
d <<= 1;
}
else if(*ptr == z)
{ d <<= 1;
v += d;
}
else break;
}
return v;
}
/* Elias Gamma code for POSITIVE integers
** Gamma code Value Base-2 bits
** 1 1 1
** 00 1 2 10
** 01 1 3 11
** 00 00 1 4 100
** 01 00 1 5 101
** ...
*/
{ /* 0000 -> 00 00 00 00 */ 0x00000000,
/* 0001 -> 01 00 00 00 */ 0x40000000,
/* 0010 -> 00 01 00 00 */ 0x10000000,
/* 0011 -> 01 01 00 00 */ 0x50000000,
/* 0100 -> 00 00 01 00 */ 0x04000000,
/* 0101 -> 01 00 01 00 */ 0x44000000,
/* 0110 -> 00 01 01 00 */ 0x14000000,
/* 0111 -> 01 01 01 00 */ 0x54000000,
/* 1000 -> 00 00 00 01 */ 0x01000000,
/* 1001 -> 01 00 00 01 */ 0x41000000,
/* 1010 -> 00 01 00 01 */ 0x11000000,
/* 1011 -> 01 01 00 01 */ 0x51000000,
/* 1100 -> 00 00 01 01 */ 0x05000000,
/* 1101 -> 01 00 01 01 */ 0x45000000,
/* 1110 -> 00 01 01 01 */ 0x15000000,
/* 1111 -> 01 01 01 01 */ 0x55000000
};
{ /* 0 -> 0 */ 0x00000000,
/* 1 -> 1 */ 0x80000000,
/* 10 -> 00 1 */ 0x20000000,
/* 11 -> 01 1 */ 0x60000000,
/* 100 -> 00 00 1 */ 0x08000000,
/* 101 -> 01 00 1 */ 0x48000000,
/* 110 -> 00 01 1 */ 0x18000000,
/* 111 -> 01 01 1 */ 0x58000000,
/* 1000 -> 00 00 00 1 */ 0x02000000,
/* 1001 -> 01 00 00 1 */ 0x42000000,
/* 1010 -> 00 01 00 1 */ 0x12000000,
/* 1011 -> 01 01 00 1 */ 0x52000000,
/* 1100 -> 00 00 01 1 */ 0x06000000,
/* 1101 -> 01 00 01 1 */ 0x46000000,
/* 1110 -> 00 01 01 1 */ 0x16000000,
/* 1111 -> 01 01 01 1 */ 0x56000000
};
#if __STD_C
#else
Vcint_t v;
#endif
{
ssize_t n;
for(n = 0; v > 0xf; v >>= 4, n += 8)
if(v <= 0x3)
{ if(v <= 0x1)
return n+1;
}
else
return n+3;
}
}
else
{ if(v <= 0x7)
return n+5;
}
else
return n+7;
}
}
}
#if __STD_C
#else
#endif
{
Vcint_t v;
int k, b, g, s;
/* Bit strings of the below forms are terminal and map to # of sig bits.
** 1xxx xxxx |-1| bits.
** xx1x xxxx |-3| bits.
** xxxx 1xxx |-5| bits.
** xxxx xx1x |-7| bits.
** Otherwise, they would be of the below form and inversely map Gfour[].
** 0x0x 0x0x
*/
{ for(k = 0; k < 256; ++k)
{ for(b = 7; b >= 1; b -= 2) /* find the high odd bit */
if(k & (1<<b) )
break;
if(b >= 1)
if((k & ~((1<<b)-1)) == k ) /* set value in Ilast[] */
{ for(g = 0; g < 16; ++g)
break;
for(s = (1<<b)-1; s >= 0; --s)
Ilast[k|s] = g;
}
}
}
for(k = 0; k < 16; ++k) /* inverse of Gfour[] */
}
for(v = 0, s = 0;; s += 4)
return -1;
if((g = Ifour[b]) >= 0)
return -1;
k = 8;
}
else
{ k = -g;
g = Ilast[b];
}
v |= ((Vcint_t)g) << s;
if(k < 8)
break;
}
return v;
}
/* use binary search to get # of significant bits in a given integer */
{ 1, /* 0: 0000 */
1, /* 1: 0001 */
2, /* 2: 0010 */
2, /* 3: 0011 */
3, /* 4: 0100 */
3, /* 5: 0101 */
3, /* 6: 0110 */
3, /* 7: 0111 */
4, /* 8: 1000 */
4, /* 9: 1001 */
4, /* 10: 1010 */
4, /* 11: 1011 */
4, /* 12: 1100 */
4, /* 13: 1101 */
4, /* 14: 1110 */
4 /* 15: 1111 */
};
/* Coding a list of non-negative integers using a variable-length bit coding.
** Each integer is coded by a prefix telling the # of significant bits followed
** by the significant bits themselves. The #'s of significant bits are coded
** using a Huffman code.
*/
#if __STD_C
#else
#endif
{
int run;
/* compute the frequencies of the sizes of significant bits */
for(i = 0; i < VC_INTSIZE; ++i)
freq[i] = 0;
for(i = 0; i < nlist; ++i)
{ v = list[i];
}
/* compute the Huffman code for these #'s of significant bits */
return -1;
if(s == 0) /* all integers have the same size */
{ s = run+1;
for(i = 0; i < nlist; ++i)
}
}
else
return -1;
for(i = 0; i < nlist; ++i)
{ if(s > 8)
v >>= 8; s -= 8;
}
else
{ e = v << (VC_INTSIZE - s);
break;
}
}
}
}
}
#if __STD_C
#else
#endif
{
Vcint_t v;
return -1;
if(!(s & (1<<7)) ) /* all integers have the same size */
}
}
else
{ s &= ~(1<<7);
return -1;
return -1;
return -1;
p += (b >> (VC_BITSIZE-s)); /* slot to look into */
if(size[p] > 0) /* length is found */
for(v = 0, d = 0;; )
{ if(s > 8)
v |= (b >> (VC_BITSIZE-8)) << d;
d += 8; s -= 8;
}
else
v |= (b >> (VC_BITSIZE-s)) << d;
break;
}
}
break;
s = ntop; p = 0; /* restart at trie top for next integer */
}
else if(size[p] == 0) /* corrupted data */
return -1;
else
}
}
}
return nl;
}
/* Transform a list of integers into non-negative integers.
** 1. Keep a sign indicator and if the current element is of this sign,
** code its absolute value; otherwise, code it as the negative value
** with the same magnitude. This turns a run into all positives except
** for the head of the run.
** 2. Then code all integers using only non-negative integers via
** a proportional method. Suppose that we want n negatives for each p
** positives, the codings for a negative x and a positive y would be:
** x -> ((-x-1)/n)*(n+p) + (-x-1)%n + 1 + p
** y -> ( (y-1)/p)*(n+p) + ( y-1)%p + 1
*/
{
ssize_t k, p, n, s, g;
Vcint_t v;
{
/* transform runs to positives */
{ if((v = list[k]) < 0)
{ if(type > 0)
type = -1;
else list[k] = -v;
}
else if(v > 0)
{ if(type < 0)
{ type = 1;
list[k] = -v;
}
}
}
for(n = p = 0, k = 0; k < nlist; ++k)
{ if((v = list[k]) > 0)
p += 1;
else if(v < 0)
n += 1;
}
if(n == 0) /* a sequence of non-negatives */
p = 1;
else if(p == 0) /* all negatives */
{ for(k = 0; k < nlist; ++k)
n = 1;
}
else
{ /* reduce proportions */
while(p >= 128 && n >= 128)
{ p /= 2; n /= 2; }
for(k = 127; k > 1; --k)
if((p%k) == 0 && (n%k) == 0)
{ p /= k; n /= k; }
/* now do the coding */
for(s = n+p, k = 0; k < nlist; ++k)
{ if((v = list[k]) == 0 )
continue;
else if(v > 0)
}
}
}
else
if(p == 0 && n > 0) /* all negatives */
{ for(k = 0; k < nlist; ++k)
}
else if(p > 0 && n > 0) /* nontrivial coding */
{ for(s = n+p, k = 0; k < nlist; ++k)
{ if((v = list[k]) == 0)
continue;
if((g = (v-1)%s) < p)
}
}
/* undo the sign switching */
{ v = list[k];
if(type < 0)
list[k] = -v;
if(v < 0)
}
}
return nlist;
}
/* Addresses of successive matches in the Lempel-Ziv parser tend to be close
** to one another. So it is good to code an integer given another in such a
** way that the coded value is small.
*/
#if __STD_C
#else
#endif
{
Vcint_t a, n;
return -1; /* an error in specification */
return -1; /* out of range */
a = (v -= near) < 0 ? -v : v;
if(a <= n)
return (a<<1) - (v <= 0 ? 0 : 1);
else return a + n;
}
if(v < 0 || v >= max)
return -1; /* bad coded value */
if(v <= (n<<1))
return a + min;
}
else return -1;
}
#if __STD_C
#else
Vcint_t i;
char* a;
ssize_t z;
#endif
{
int k;
for(k = sizeof(buf)-1; k >= 0; --k)
if((i /= 10) == 0 )
break;
}
if((i = sizeof(buf) - k) >= z)
return -1;
else
a[i] = 0;
return i;
}
}
#if __STD_C
#else
char* a;
#endif
{
Vcint_t i;
for(i = 0; *a && isdigit(*a); ++a)
i = i*10 + (*a - '0');
return i;
}
/* transform from a native string to its ASCII version for portability */
#if __STD_C
#else
char* vcstrcode(s, a, z)
char* s; /* string to be made portable */
char* a; /* space to store asciized data */
ssize_t z; /* size of 'a' */
#endif
{
ssize_t c;
static int type = 0; /* unknown: 0, native != ASCII: -1, else: 1 */
if(type == 0) /* construct the map from native to ascii */
{ for(c = 0; c < 256; ++c)
_ascii[c] = (char)c;
for(c = 0; c < 256; ++c)
if(_ascii[c] != c)
break;
}
for(c = 0; c < z; ++c)
if((a[c] = (char)_ascii[s[c]]) == 0 )
break;
return c < z ? a : NIL(char*);
}
/* decode a list of integers from a null-terminated string */
#if __STD_C
#else
char* str; /* string to be parsed */
int comma; /* value separator */
#endif
{
for(n = 0, k = 0;; )
k += 1;
break;
k += 1;
n += 1; /* a well-defined value */
}
if(n == 0)
return n;
return -1;
for(n = 0, k = 0;; )
k += 1;
break;
list[n] = 0;
k += 1;
}
n += 1; /* a well-defined value */
}
return n;
}
{
int b, h, l, r;
if(!Didinit) /* initialize conversion tables */
for(b = 0; b < 256; ++b)
for(b = 0; b < 16; ++b)
}
Didinit = 1;
}
return -1;
if(type >= 0) /* byte to hex */
return -1;
/* 0 for lower-case, anything else upper-case */
{ if(h >= hexz-1)
return -1;
}
if(h < hexz)
hex[h] = 0;
return h;
}
else /* hex to byte, allow mixed case */
return -1;
{ if(b >= bytez ||
return -1;
}
if(b < bytez)
byte[b] = 0;
return b;
}
}