| 131 | |
| 132 | //*************************************************************** |
| 133 | int CHuffman::Compress(const void *pInput, int InputSize, void *pOutput, int OutputSize) const |
| 134 | { |
| 135 | // this macro loads a symbol for a byte into bits and bitcount |
| 136 | #define HUFFMAN_MACRO_LOADSYMBOL(Sym) \ |
| 137 | do \ |
| 138 | { \ |
| 139 | Bits |= m_aNodes[Sym].m_Bits << Bitcount; \ |
| 140 | Bitcount += m_aNodes[Sym].m_NumBits; \ |
| 141 | } while(0) |
| 142 | |
| 143 | // this macro writes the symbol stored in bits and bitcount to the dst pointer |
| 144 | #define HUFFMAN_MACRO_WRITE() \ |
| 145 | do \ |
| 146 | { \ |
| 147 | while(Bitcount >= 8) \ |
| 148 | { \ |
| 149 | *pDst++ = (unsigned char)(Bits & 0xff); \ |
| 150 | if(pDst == pDstEnd) \ |
| 151 | return -1; \ |
| 152 | Bits >>= 8; \ |
| 153 | Bitcount -= 8; \ |
| 154 | } \ |
| 155 | } while(0) |
| 156 | |
| 157 | // setup buffer pointers |
| 158 | const unsigned char *pSrc = (const unsigned char *)pInput; |
| 159 | const unsigned char *pSrcEnd = pSrc + InputSize; |
| 160 | unsigned char *pDst = (unsigned char *)pOutput; |
| 161 | unsigned char *pDstEnd = pDst + OutputSize; |
| 162 | |
| 163 | // symbol variables |
| 164 | unsigned Bits = 0; |
| 165 | unsigned Bitcount = 0; |
| 166 | |
| 167 | // make sure that we have data that we want to compress |
| 168 | if(InputSize) |
| 169 | { |
| 170 | // {A} load the first symbol |
| 171 | int Symbol = *pSrc++; |
| 172 | |
| 173 | while(pSrc != pSrcEnd) |
| 174 | { |
| 175 | // {B} load the symbol |
| 176 | HUFFMAN_MACRO_LOADSYMBOL(Symbol); |
| 177 | |
| 178 | // {C} fetch next symbol, this is done here because it will reduce dependency in the code |
| 179 | Symbol = *pSrc++; |
| 180 | |
| 181 | // {B} write the symbol loaded at |
| 182 | HUFFMAN_MACRO_WRITE(); |
| 183 | } |
| 184 | |
| 185 | // write the last symbol loaded from {C} or {A} in the case of only 1 byte input buffer |
| 186 | HUFFMAN_MACRO_LOADSYMBOL(Symbol); |
| 187 | HUFFMAN_MACRO_WRITE(); |
| 188 | } |
| 189 | |
| 190 | // write EOF symbol |