ArithmeticCoding  0.0.0a
Arithmetic coding in C
C:/Users/clackn/Desktop/src/arithcode/src/stream.c
Go to the documentation of this file.
00001 #include "stream.h"
00002 
00003 #include <stdint.h> // for fixed width integer types
00004 #include <stdlib.h> // for size_t
00005 #include <stdio.h>  // for exception logging
00006 #include <string.h> // for memset
00007 
00008 typedef uint8_t   u8;
00009 typedef uint16_t  u16;
00010 typedef uint32_t  u32;
00011 typedef uint64_t  u64;
00012 typedef  int8_t   i8;
00013 typedef  int16_t  i16;
00014 typedef  int32_t  i32;
00015 typedef  int64_t  i64;
00016 
00017 #define ENDL "\n"
00018 #define TRY(e) \
00019   do{ if(!(e)) {\
00020     printf("%s(%d):"ENDL "\t%s"ENDL "\tExpression evaluated as false."ENDL, \
00021         __FILE__,__LINE__,#e); \
00022     goto Error; \
00023   }} while(0)
00024 
00025 #define SAFE_FREE(e) if(e) { free(e); (e)=NULL; }
00026 
00027 static void maybe_init(stream_t *self)
00028 { if(!self->d)
00029   { memset(self,0,sizeof(*self));
00030     TRY(self->d=malloc(self->nbytes=4096));
00031     self->own=1;
00032   }
00033   return;
00034 Error:
00035   abort();
00036 }
00037 
00038 void attach(stream_t *self, void* d, size_t n)
00039 { if(self->own) SAFE_FREE(self->d);
00040   self->d = (u8*)d;
00041   self->own = 0;
00042   self->nbytes = n;
00043   maybe_init(self);
00044 }
00045 
00046 void detach(stream_t *self, void **d, size_t *n)
00047 { if(d) *d = self->d;
00048   if(n) *n = self->ibyte;
00049   memset(self,0,sizeof(*self));
00050 }
00051 
00052 static void maybe_resize(stream_t *s)
00053 { if(s->ibyte>=s->nbytes)
00054     TRY(s->d = realloc(s->d,s->nbytes=(1.2*s->ibyte+50)));
00055   return;
00056 Error:
00057   abort();
00058 }
00059 
00060 //printf("PUSH: [%llu] %llu %llu"ENDL,(u64)self->ibyte,(u64)v,(u64)(*(T*)(self->d+self->ibyte))); 
00061 
00062 #define DEFN_PUSH(T) \
00063   void push_##T(stream_t *self, T v) \
00064   { *(T*)(self->d+self->ibyte) = v;  \
00065     self->ibyte+=sizeof(T);          \
00066     maybe_resize(self);              \
00067   }
00068 DEFN_PUSH(u8);
00069 DEFN_PUSH(u16);
00070 DEFN_PUSH(u32);
00071 DEFN_PUSH(u64);
00072 DEFN_PUSH(i8);
00073 DEFN_PUSH(i16);
00074 DEFN_PUSH(i32);
00075 DEFN_PUSH(i64);
00076 
00077 void push_u1(stream_t *self, u8 v)
00078 { 
00079   self->mask = 1<<(7-self->ibit); // index from the high bit so we can use integer addition to do carries
00080   //set
00081   { u8 *w = self->d+self->ibyte,
00082         m = self->mask;
00083     *w = (*w & ~m) | (-(v) & m);
00084   }
00085   //inc
00086   if(self->ibit==7)
00087   { self->ibit=0;
00088     self->ibyte++;
00089     maybe_resize(self);
00090     self->d[self->ibyte]=0;         // clear out the byte    
00091   } else 
00092   { self->ibit++;
00093   }
00094 }
00095 void push_u4(stream_t *self, u8 v)
00096 { 
00097   self->mask = (self->ibit==0)?0xf0:0x0f ; // index from the high bit so we can use integer addition to do carries
00098   //set
00099   { u8 *w = self->d+self->ibyte,
00100         m = self->mask;
00101     *w ^= (*w^ (v<<(4-self->ibit)) )&m;
00102   }
00103   //inc
00104   if(self->ibit==4)
00105   { self->ibit=0;
00106     self->ibyte++;
00107     maybe_resize(self);
00108     self->d[self->ibyte]=0;         // clear out the byte    
00109   } else 
00110   { self->ibit=4;
00111   }
00112 }
00113 
00114 #define DEFN_POP(T) \
00115   T pop_##T(stream_t *self) \
00116   { T v; \
00117     if(self->ibyte>=self->nbytes) return 0; \
00118     v = *(T*)(self->d+self->ibyte); \
00119     self->ibyte+=sizeof(T); \
00120     return v; \
00121   }
00122 DEFN_POP(u8);
00123 DEFN_POP(u16);
00124 DEFN_POP(u32);
00125 DEFN_POP(u64);
00126 DEFN_POP(i8);
00127 DEFN_POP(i16);
00128 DEFN_POP(i32);
00129 DEFN_POP(i64);
00130 
00131 u8 pop_u1(stream_t *self)
00132 { u8 v,m;
00133   m = 1<<(7-self->ibit); 
00134   v = 0;
00135   if(self->ibyte<self->nbytes)
00136     v = (self->d[self->ibyte] & m)==m;
00137   //inc
00138   self->ibit++;
00139   if(self->ibit>7)
00140   { self->ibit=0;
00141     self->ibyte++;
00142   }
00143   return v;
00144 }
00145 u8 pop_u4(stream_t *self)
00146 { u8 v,m;
00147   m = (self->ibit==0)?0xf0:0x0f; 
00148   v = 0;
00149   if(self->ibyte<self->nbytes)
00150     v = (self->d[self->ibyte] & m)>>(4-self->ibit);
00151   //inc
00152   if(self->ibit==4)
00153   { self->ibit=0;
00154     self->ibyte++;
00155   } else
00156     self->ibit=4;
00157   return v;
00158 }
00159 
00160 #define MAX_TYPE(T) static const T max_##T = (T)(-1)
00161 MAX_TYPE(u8);
00162 MAX_TYPE(u16);
00163 MAX_TYPE(u32);
00164 MAX_TYPE(u64);
00165 
00166 #define DEFN_CARRY(T) \
00167 void carry_##T(stream_t *self)          \
00168 { size_t n = (self->ibyte-1)/sizeof(T); \
00169   while( ((T*)(self->d))[n]==max_##T )  \
00170     ((T*)(self->d))[n--]=0;             \
00171   ((T*)(self->d))[n]++;                 \
00172 }
00173 DEFN_CARRY(u8);
00174 DEFN_CARRY(u16);
00175 DEFN_CARRY(u32);
00176 DEFN_CARRY(u64);
00177 
00178 void carry_u1(stream_t *self)
00179 { size_t ibyte=self->ibyte;       // ibit = 0 is the high bit
00180   u8 *d = self->d;
00181   u8 s,c;
00182   ibyte -= (ibyte>0)&&(self->mask&1); // if ibyte has wrapped over, subtract one
00183   c=d[ibyte] + self->mask;       // carry the ibits
00184   s=c<d[ibyte];                  // overflow test
00185   d[ibyte]=c;
00186   if(s)                          // need to keep carrying
00187   { while(d[--ibyte]==255)
00188       d[ibyte]=0;                // compliment all bits
00189     d[ibyte] += 1;               // finish carrying
00190   }
00191 }
00192 void carry_u4(stream_t *self)
00193 { size_t ibyte=self->ibyte;      // ibit = 0 is the high bit
00194   u8 *d = self->d;
00195   u8 s,c;
00196   u8 m = (self->ibit==0)?0x01:0x10; //if 0, last write was 0x0f, otherwise at 0xf0
00197   ibyte -= (ibyte>0)&&(self->mask==0x0f); // if ibyte has wrapped over, subtract one
00198   c=d[ibyte] + m;                // carry
00199   s=c<d[ibyte];                  // overflow test
00200   d[ibyte]=c;
00201   if(s)                          // need to keep carrying
00202   { while(d[--ibyte]==255)
00203       d[ibyte]=0;                // compliment all bits
00204     d[ibyte] += 1;               // finish carrying
00205   }
00206 }
 All Classes Files Functions Variables Typedefs Defines