You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

485 lines
17 KiB

/******************************************************************************
* Copyright © 2014-2015 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
// ramcoder based on arcode.c from Michael Dipperstein
#ifdef DEFINES_ONLY
#ifndef crypto777_ramcoder_h
#define crypto777_ramcoder_h
#include <stdio.h>
#include "../includes/curve25519.h"
struct huffstream { uint8_t *ptr,*buf; uint32_t bitoffset,maski,endpos; uint32_t allocsize:31,allocated:1; };
typedef struct huffstream HUFF;
#define hrewind(hp) hseek(hp,0,SEEK_SET)
#define RAMMASK_BIT(x) ((uint16_t)(1 << ((8 * sizeof(uint16_t)) - (1 + (x)))))
#define RAMCODER_FINALIZE 1
#define RAMCODER_PUTBITS 2
#define RAMCODER_MAXSYMBOLS 0x100
#define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7)))
#define GETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] & (1 << ((bitoffset) & 7)))
struct ramcoder
{
uint32_t cumulativeProb;
uint16_t lower,upper,code,underflowBits,lastsymbol,upper_lastsymbol,counter;
uint64_t *histo;
uint16_t ranges[];
};
int32_t ramcoder_decode(struct ramcoder *coder,int32_t updateprobs,HUFF *hp);
int32_t ramcoder_decoder(struct ramcoder *coder,int32_t updateprobs,uint8_t *buf,int32_t maxlen,HUFF *hp,bits256 *seed);
#define ramcoder_encode(val,coder,hp) ramcoder_update(val,coder,1,RAMCODER_PUTBITS,hp)
int32_t ramcoder_encoder(struct ramcoder *coder,int32_t updateprobs,uint8_t *buf,int32_t len,HUFF *hp,uint64_t *histo,bits256 *seed);
int32_t ramcoder_update(int symbol,struct ramcoder *coder,int32_t updateprobs,int32_t putflags,HUFF *hp);
int32_t init_ramcoder(struct ramcoder *coder,HUFF *hp,bits256 *seed);
int32_t ramcoder_emit(HUFF *hp,struct ramcoder *coder,int32_t updateprobs,uint8_t *buf,int32_t len);
int32_t ramcoder_decompress(uint8_t *data,int32_t maxlen,uint8_t *bits,uint32_t numbits,bits256 seed);
int32_t ramcoder_compress(uint8_t *bits,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 seed);
uint64_t hconv_bitlen(uint64_t bitlen);
void _init_HUFF(HUFF *hp,int32_t allocsize,void *buf);
#endif
#else
#ifndef crypto777_ramcoder_c
#define crypto777_ramcoder_c
#ifndef crypto777_ramcoder_h
#define DEFINES_ONLY
#include "ramcoder.c"
#undef DEFINES_ONLY
#endif
static const uint8_t huffmasks[8] = { (1<<0), (1<<1), (1<<2), (1<<3), (1<<4), (1<<5), (1<<6), (1<<7) };
static const uint8_t huffoppomasks[8] = { ~(1<<0), ~(1<<1), ~(1<<2), ~(1<<3), ~(1<<4), ~(1<<5), ~(1<<6), (uint8_t)~(1<<7) };
void _init_HUFF(HUFF *hp,int32_t allocsize,void *buf) { hp->buf = hp->ptr = buf, hp->allocsize = allocsize, hp->bitoffset = 0; }
uint64_t hconv_bitlen(uint64_t bitlen)
{
uint64_t len;
len = (bitlen >> 3);
if ( (bitlen & 7) != 0 )
len++;
return(len);
}
int32_t hupdate_internals(HUFF *hp)
{
int32_t retval = 0;
if ( (hp->bitoffset >> 3) > hp->allocsize )
{
printf("hupdate_internals: ERROR: bitoffset.%d -> %d >= allocsize.%d\n",hp->bitoffset,hp->bitoffset>>3,hp->allocsize);
//getchar();
hp->bitoffset = (hp->allocsize << 3) - 1;
retval = -1;
}
if ( hp->bitoffset > hp->endpos )
hp->endpos = hp->bitoffset;
hp->ptr = &hp->buf[hp->bitoffset >> 3];
hp->maski = (hp->bitoffset & 7);
return(retval);
}
int32_t hseek(HUFF *hp,int32_t offset,int32_t mode)
{
if ( mode == SEEK_END )
hp->bitoffset = (offset + hp->endpos);
else if ( mode == SEEK_SET )
hp->bitoffset = offset;
else hp->bitoffset += offset;
if ( hupdate_internals(hp) < 0 )
{
printf("hseek.%d: illegal offset.%d %d >= allocsize.%d\n",mode,offset,offset>>3,hp->allocsize);
return(-1);
}
return(0);
}
void hclear(HUFF *hp,int32_t clearbuf)
{
hp->bitoffset = 0;
hupdate_internals(hp);
hp->endpos = 0;
if ( clearbuf != 0 )
memset(hp->buf,0,hp->allocsize);
}
int32_t hgetbit(HUFF *hp)
{
int32_t bit = 0;
//printf("hp.%p ptr.%ld buf.%ld maski.%d\n",hp,(long)hp->ptr-(long)hp->buf,(long)hp->buf-(long)hp,hp->maski);
if ( hp->bitoffset < hp->endpos )
{
if ( (*hp->ptr & huffmasks[hp->maski++]) != 0 )
bit = 1;
hp->bitoffset++;
if ( hp->maski == 8 )
hp->maski = 0, hp->ptr++;
//fprintf(stderr,"<-%d ",bit);
return(bit);
}
printf("hgetbit past EOF: %d >= %d\n",hp->bitoffset,hp->endpos);//, getchar();
return(-1);
}
int32_t hputbit(HUFF *hp,int32_t bit)
{
//fprintf(stderr,"->%d ",bit);
if ( bit != 0 )
*hp->ptr |= huffmasks[hp->maski];
else *hp->ptr &= huffoppomasks[hp->maski];
if ( ++hp->maski >= 8 )
hp->maski = 0, hp->ptr++;
if ( ++hp->bitoffset > hp->endpos )
hp->endpos = hp->bitoffset;
if ( (hp->bitoffset>>3) >= hp->allocsize )
{
printf("hwrite: bitoffset.%d >= allocsize.%d\n",hp->bitoffset,hp->allocsize);
hp->bitoffset--;
hupdate_internals(hp);
return(-1);
}
return(0);
}
int32_t hwrite(uint64_t codebits,int32_t numbits,HUFF *hp)
{
int32_t i;
for (i=0; i<numbits; i++,codebits>>=1)
if ( hputbit(hp,codebits & 1) < 0 )
return(-1);
return(numbits);
}
uint64_t hread(int32_t *numbitsp,int32_t numbits,HUFF *hp)
{
int32_t i,bit; uint64_t codebits = 0;
for (i=0; i<numbits; i++)
{
codebits <<= 1;
if ( (bit= hgetbit(hp)) < 0 )
break;
codebits |= bit;
}
*numbitsp = i;
return(codebits);
}
int32_t hmemcpy(void *dest,void *src,HUFF *hp,int32_t datalen)
{
if ( (hp->bitoffset & 7) != 0 || ((hp->bitoffset>>3) + datalen) > hp->allocsize )
{
printf("misaligned hmemcpy bitoffset.%d or overflow allocsize %d vs %d\n",hp->bitoffset,hp->allocsize,((hp->bitoffset>>3) + datalen));
getchar();
return(-1);
}
if ( dest != 0 && src == 0 )
memcpy(dest,hp->ptr,datalen);
else if ( dest == 0 && src != 0 )
memcpy(hp->ptr,src,datalen);
else
{
printf("invalid hmemcpy with both dest.%p and src.%p\n",dest,src);
return(-1);
}
hp->ptr += datalen;
hp->bitoffset += (datalen << 3);
if ( hp->bitoffset > hp->endpos )
hp->endpos = hp->bitoffset;
return(datalen);
}
int32_t hcalc_bitsize(uint64_t x)
{
uint64_t mask = ((uint64_t)1 << 63);
int32_t i;
if ( x == 0 )
return(1);
for (i=63; i>=0; i--,mask>>=1)
{
if ( (mask & x) != 0 )
return(i+1);
}
return(-1);
}
int32_t init_ramcoder(struct ramcoder *coder,HUFF *hp,bits256 *seed)
{
int32_t i,precision,numbits = 0;
if ( coder->lastsymbol == 0 )
coder->lastsymbol = RAMCODER_MAXSYMBOLS, coder->upper_lastsymbol = (coder->lastsymbol + 1);
coder->cumulativeProb = coder->lower = coder->code = coder->underflowBits = coder->ranges[0] = 0;
for (i=1; i<=coder->upper_lastsymbol; i++)
{
coder->ranges[i] = coder->ranges[i - 1] + 1 + 256*((i <= sizeof(seed)*8) ? (GETBIT(seed->bytes,i-1) != 0) : 0);
//printf("%d ",coder->ranges[i]);
}
for (i=1; i<=coder->upper_lastsymbol; i++)
coder->cumulativeProb += (coder->ranges[i] - coder->ranges[i - 1]);
precision = (8 * sizeof(uint16_t));
coder->upper = (1LL << precision) - 1;
if ( hp != 0 )
{
for (i=0; i<precision; i++,numbits++)
coder->code = (coder->code << 1) | hgetbit(hp);
//coder->code = hread(&numbits,precision,hp), coder->code <<= (precision - numbits);
//printf("set code %x\n",coder->code);
}
//printf("cumulative.%d code.%x numbits.%d\n",coder->cumulativeProb,coder->code,numbits);
return(numbits);
}
int32_t ramcoder_state(struct ramcoder *coder)
{
if ( (coder->upper & RAMMASK_BIT(0)) == (coder->lower & RAMMASK_BIT(0)) )
return(0);
else if ( (coder->lower & RAMMASK_BIT(1)) && (coder->upper & RAMMASK_BIT(1)) == 0 )
return(1);
else return(-1);
}
void ramcoder_normalize(struct ramcoder *coder) { coder->lower &= ~(RAMMASK_BIT(0) | RAMMASK_BIT(1)), coder->upper |= RAMMASK_BIT(1); }
void ramcoder_shiftbits(struct ramcoder *coder) { coder->lower <<= 1, coder->upper <<= 1, coder->upper |= 1; }
int32_t ramcoder_putbits(HUFF *hp,struct ramcoder *coder,int32_t flushflag)
{
int32_t numbits = 0;
while ( 1 )
{
switch ( ramcoder_state(coder) )
{
case 1: coder->underflowBits++, ramcoder_normalize(coder); break;
case 0:
if ( hputbit(hp,(coder->upper & RAMMASK_BIT(0)) != 0) < 0 )
return(-1);
numbits++;
//printf("%d> ",(coder->upper & RAMMASK_BIT(0)) != 0);
while ( coder->underflowBits > 0 )
{
if ( hputbit(hp,(coder->upper & RAMMASK_BIT(0)) == 0) < 0 )
return(-1);
numbits++;
//printf("%d> ",(coder->upper & RAMMASK_BIT(0)) == 0);
coder->underflowBits--;
}
break;
default:
if ( flushflag != 0 )
{
if ( hputbit(hp,(coder->lower & RAMMASK_BIT(1)) != 0) < 0 )
return(-1);
numbits++;
for (coder->underflowBits++; coder->underflowBits>0; coder->underflowBits--)
{
if ( hputbit(hp,(coder->lower & RAMMASK_BIT(1)) == 0) < 0 )
return(-1);
numbits++;
}
}
return(numbits);
break;
}
ramcoder_shiftbits(coder);
}
}
int32_t ramcoder_getbits(HUFF *hp,struct ramcoder *coder)
{
int32_t nextBit,numbits = 0;
while ( 1 )
{
switch ( ramcoder_state(coder) )
{
case 0: break; // MSBs match, allow them to be shifted out
case 1: ramcoder_normalize(coder), coder->code ^= RAMMASK_BIT(1); break;
default: return(numbits); break;
}
ramcoder_shiftbits(coder);
coder->code <<= 1;
if ( (nextBit= hgetbit(hp)) >= 0 )
coder->code |= nextBit;//, printf("<%c",'0'+nextBit);
else return(-1);
numbits++;
}
}
int32_t ramdecoder_bsearch(uint16_t probability,struct ramcoder *coder)
{
int32_t last,middle,first = 0;
last = coder->upper_lastsymbol;
while ( last >= first )
{
middle = first + ((last - first) / 2);
//printf("[%d %d] ",coder->ranges[middle],coder->ranges[middle+1]);
if ( probability < coder->ranges[middle] )
last = middle - 1;
else if ( probability >= coder->ranges[middle + 1] )
first = middle + 1;
else return(middle);
}
printf("Unknown Symbol: %llu (max: %llu)\n",(long long)probability,(long long)coder->ranges[coder->upper_lastsymbol]);
return(-1);
}
int32_t ramcoder_update(int symbol,struct ramcoder *coder,int32_t updateprobs,int32_t putflags,HUFF *hp)
{
uint32_t range; uint16_t i,original,delta;
//printf("putflags.%d %p: upper %llu lower %llu code.%x cumulative.%d | symbol.%d\n",putflags,coder,(long long)coder->upper,(long long)coder->lower,coder->code,coder->cumulativeProb,symbol);
range = (uint32_t)(coder->upper - coder->lower) + 1;
coder->upper = coder->lower + (uint16_t)(((uint32_t)coder->ranges[symbol + 1] * range)/ coder->cumulativeProb) - 1;
coder->lower = coder->lower + (uint16_t)(((uint32_t)coder->ranges[symbol] * range) / coder->cumulativeProb);
if ( updateprobs != 0 )
{
coder->cumulativeProb++;
for (i=(symbol+1); i<=coder->upper_lastsymbol; i++)
coder->ranges[i]++;
if ( coder->cumulativeProb >= (1 << ((8 * sizeof(uint16_t)) - 2)) )
{
original = coder->cumulativeProb = 0;
for (i=1; i<=coder->upper_lastsymbol; i++)
{
delta = coder->ranges[i] - original, original = coder->ranges[i];
if ( delta <= 2 )
coder->ranges[i] = coder->ranges[i - 1] + 1;
else coder->ranges[i] = coder->ranges[i - 1] + (delta / 2);
coder->cumulativeProb += (coder->ranges[i] - coder->ranges[i - 1]);
}
}
coder->counter++;
} else printf("unexpected non-update ramcoder\n");
if ( coder->lower > coder->upper )
printf("ramcoderupdate: coder->lower %llu > %llu coder->upper\n",(long long)coder->lower,(long long)coder->upper);
return((putflags != 0) ? ramcoder_putbits(hp,coder,putflags & RAMCODER_FINALIZE) : ramcoder_getbits(hp,coder));
}
int32_t ramcoder_emit(HUFF *hp,struct ramcoder *coder,int32_t updateprobs,uint8_t *buf,int32_t len)
{
int32_t i,n,numbits = 0;
for (i=0; i<len; i++)
{
if ( coder->histo != 0 )
coder->histo[buf[i]]++;
if ( (n= ramcoder_update(buf[i],coder,updateprobs,RAMCODER_PUTBITS,hp)) < 0 )
return(-1);
numbits += n;
}
return(numbits);
}
int32_t ramcoder_encoder(struct ramcoder *coder,int32_t updateprobs,uint8_t *buf,int32_t len,HUFF *hp,uint64_t *histo,bits256 *seed)
{
int32_t i,threshold; uint8_t _coder[sizeof(*coder) + (RAMCODER_MAXSYMBOLS+2)*sizeof(coder->ranges[0])];
if ( coder == 0 )
{
memset(_coder,0,sizeof(_coder));
hrewind(hp);
coder = (struct ramcoder *)_coder;
coder->histo = histo;
init_ramcoder(coder,0,seed);
if ( ramcoder_emit(hp,coder,updateprobs,buf,len) < 0 )
return(-1);
if ( ramcoder_update(coder->lastsymbol,coder,updateprobs,RAMCODER_PUTBITS,hp) < 0 )
return(-1);
if ( ramcoder_update(coder->lastsymbol,coder,updateprobs,RAMCODER_PUTBITS|RAMCODER_FINALIZE,hp) < 0 )
return(-1);
}
else if ( ramcoder_emit(hp,coder,updateprobs,buf,len) < 0 )
return(-1);
memset(seed,0,sizeof(*seed));
threshold = coder->cumulativeProb / coder->upper_lastsymbol;
for (i=1; i<=coder->upper_lastsymbol; i++)
if ( (coder->ranges[i] - coder->ranges[i - 1]) > threshold )
SETBIT(seed->bytes,i-1);
return(hp->bitoffset);
}
int32_t ramcoder_decode(struct ramcoder *coder,int32_t updateprobs,HUFF *hp)
{
int32_t ind;
#define RAMDECODER_UNSCALED(coder) ((((uint32_t)coder->code - coder->lower) + 1) * (uint32_t)coder->cumulativeProb - 1) / (((uint32_t)coder->upper - coder->lower) + 1)
if ( (ind= ramdecoder_bsearch(RAMDECODER_UNSCALED(coder),coder)) < 0 || ind == coder->lastsymbol )
return(-1);
if ( ramcoder_update(ind,coder,updateprobs,0,hp) < 0 )
return(-1);
return(ind);
}
int32_t ramcoder_decoder(struct ramcoder *coder,int32_t updateprobs,uint8_t *buf,int32_t maxlen,HUFF *hp,bits256 *seed)
{
uint8_t _coder[sizeof(*coder) + (RAMCODER_MAXSYMBOLS+2)*sizeof(coder->ranges[0])];
int32_t val,n = 0,numbits = 0;
if ( coder == 0 )
{
memset(_coder,0,sizeof(_coder));
coder = (struct ramcoder *)_coder;
hrewind(hp);
numbits = init_ramcoder(coder,hp,seed);
}
while ( n < maxlen )
{
if ( (val= ramcoder_decode(coder,updateprobs,hp)) < 0 )
return(n);
buf[n++] = val;
}
return(n);
}
int32_t ramcoder_compress(uint8_t *bits,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 seed)
{
int32_t numbits; HUFF H,*hp = &H;
_init_HUFF(hp,maxlen,bits);
if ( ramcoder_encoder(0,1,data,datalen,hp,0,&seed) < 0 )
return(-1);
numbits = hp->bitoffset;
if ( 0 )
{
void *malloc(size_t); void free(void *);
int32_t i,checklen; uint8_t *checkbuf;
checkbuf = malloc(datalen*2);
memset(seed.bytes,0,sizeof(seed));
hrewind(hp);
checklen = ramcoder_decoder(0,1,checkbuf,datalen*2,hp,&seed);
if ( checklen != datalen || memcmp(checkbuf,data,datalen) != 0 )
{
for (i=0; i<datalen; i++)
printf("%02x ",data[i]);
printf("datalen.%d\n",datalen);
for (i=0; i<=numbits/8; i++)
printf("%02x ",bits[i]);
printf("bitoffset.%d\n",numbits);
for (i=0; i<checklen; i++)
printf("%02x ",checkbuf[i]);
printf("checklen.%d\n",checklen);
getchar();
} // else printf("CODEC passed datalen.%d -> numbits %d %d\n",datalen,numbits,numbits/8);
free(checkbuf);
}
return(numbits);
}
int32_t ramcoder_decompress(uint8_t *data,int32_t maxlen,uint8_t *bits,uint32_t numbits,bits256 seed)
{
HUFF H,*hp = &H;
_init_HUFF(hp,(uint32_t)hconv_bitlen(numbits),bits);
hp->endpos = numbits;
hrewind(hp);
return(ramcoder_decoder(0,1,data,maxlen,hp,&seed));
}
#endif
#endif