bitStream.cpp

Engine/source/core/stream/bitStream.cpp

More...

Classes:

Public Variables

gPacketBuffer [Net::MaxPacketDataSize]

Public Functions

bool
IsEqual(F32 a, F32 b)

Detailed Description

Public Variables

U32 gBitCounts [4]
U8 gPacketBuffer [Net::MaxPacketDataSize]
BitStream gPacketStream (NULL, 0)

Public Functions

IsEqual(F32 a, F32 b)

   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 GarageGames, LLC
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy
   6// of this software and associated documentation files (the "Software"), to
   7// deal in the Software without restriction, including without limitation the
   8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   9// sell copies of the Software, and to permit persons to whom the Software is
  10// furnished to do so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in
  13// all copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21// IN THE SOFTWARE.
  22//-----------------------------------------------------------------------------
  23
  24#include "platform/platform.h"
  25#include "core/stream/bitStream.h"
  26
  27#include "core/strings/stringFunctions.h"
  28#include "math/mathIO.h"
  29#include "console/consoleObject.h"
  30#include "platform/platformNet.h"
  31#include "core/bitVector.h"
  32
  33
  34static BitStream gPacketStream(NULL, 0);
  35static U8 gPacketBuffer[Net::MaxPacketDataSize];
  36
  37// bitstream utility functions
  38
  39void BitStream::clearStringBuffer() 
  40{
  41   static char stringBuf[256];
  42   stringBuf[0] = 0; 
  43//   setStringBuffer( stringBuf ); 
  44}
  45
  46void BitStream::setStringBuffer(char buffer[256])
  47{
  48//   stringBuffer = buffer;
  49}
  50
  51BitStream *BitStream::getPacketStream(U32 writeSize)
  52{
  53   if(!writeSize)
  54      writeSize = Net::MaxPacketDataSize;
  55
  56   gPacketStream.setBuffer(gPacketBuffer, writeSize, Net::MaxPacketDataSize);
  57   gPacketStream.setPosition(0);
  58
  59   return &gPacketStream;
  60}
  61
  62void BitStream::sendPacketStream(const NetAddress *addr)
  63{
  64   Net::sendto(addr, gPacketStream.getBuffer(), gPacketStream.getPosition());
  65}
  66
  67// CodeReview WTF is this additional IsEqual? - BJG, 3/29/07
  68
  69inline bool IsEqual(F32 a, F32 b) { return a == b; }
  70
  71ResizeBitStream::ResizeBitStream(U32 minSpace, U32 initialSize) : BitStream(NULL, 0, 0)
  72{
  73   mMinSpace = minSpace;
  74   if(!initialSize)
  75      initialSize = minSpace * 2;
  76   U8 *buf = (U8 *) dMalloc(initialSize);
  77   setBuffer(buf, initialSize, initialSize);
  78}
  79
  80ResizeBitStream::~ResizeBitStream()
  81{
  82   dFree(mDataPtr);
  83}
  84
  85void ResizeBitStream::validate()
  86{
  87   if(getPosition() + mMinSpace > bufSize)
  88   {
  89      bufSize = getPosition() + mMinSpace * 2;
  90     mDataPtr = (U8 *) dRealloc(mDataPtr, bufSize);
  91
  92      maxReadBitNum = bufSize << 3;
  93      maxWriteBitNum = bufSize << 3;
  94   }
  95}
  96
  97
  98class HuffmanProcessor
  99{
 100   static const U32 csm_charFreqs[256];
 101   bool   m_tablesBuilt;
 102
 103   void buildTables();
 104
 105   struct HuffNode {
 106      U32 pop;
 107
 108      S16 index0;
 109      S16 index1;
 110   };
 111   struct HuffLeaf {
 112      U32 pop;
 113
 114      U8  numBits;
 115      U8  symbol;
 116      U32 code;   // no code should be longer than 32 bits.
 117   };
 118   // We have to be a bit careful with these, mSince they are pointers...
 119   struct HuffWrap {
 120      HuffNode* pNode;
 121      HuffLeaf* pLeaf;
 122
 123     public:
 124      HuffWrap() : pNode(NULL), pLeaf(NULL) { }
 125
 126      void set(HuffLeaf* in_leaf) { pNode = NULL; pLeaf = in_leaf; }
 127      void set(HuffNode* in_node) { pLeaf = NULL; pNode = in_node; }
 128
 129      U32 getPop() { if (pNode) return pNode->pop; else return pLeaf->pop; }
 130   };
 131
 132   Vector<HuffNode> m_huffNodes;
 133   Vector<HuffLeaf> m_huffLeaves;
 134
 135   S16 determineIndex(HuffWrap&);
 136
 137   void generateCodes(BitStream&, S32, S32);
 138
 139  public:
 140   HuffmanProcessor() : m_tablesBuilt(false) { }
 141
 142   static HuffmanProcessor g_huffProcessor;
 143
 144   bool readHuffBuffer(BitStream* pStream, char* out_pBuffer, S32 maxLen);
 145   bool writeHuffBuffer(BitStream* pStream, const char* out_pBuffer, S32 maxLen);
 146};
 147
 148HuffmanProcessor HuffmanProcessor::g_huffProcessor;
 149
 150void BitStream::setBuffer(void *bufPtr, S32 size, S32 maxSize)
 151{
 152   mDataPtr = (U8 *) bufPtr;
 153   bitNum = 0;
 154   bufSize = size;
 155   maxReadBitNum = size << 3;
 156   if(maxSize < 0)
 157      maxSize = size;
 158   maxWriteBitNum = maxSize << 3;
 159   error = false;
 160   clearCompressionPoint();
 161}
 162
 163U32 BitStream::getPosition() const
 164{
 165   return (bitNum + 7) >> 3;
 166}
 167
 168
 169bool BitStream::setPosition(const U32 pos)
 170{
 171   bitNum = pos << 3;
 172   return (true);
 173}
 174
 175U32 BitStream::getStreamSize()
 176{
 177   return bufSize;
 178}
 179
 180U8 *BitStream::getBytePtr()
 181{
 182   return mDataPtr + getPosition();
 183}
 184
 185
 186U32 BitStream::getReadByteSize()
 187{
 188   return (maxReadBitNum >> 3) - getPosition();
 189}
 190
 191U32 BitStream::getWriteByteSize()
 192{
 193   return (maxWriteBitNum >> 3) - getPosition();
 194}
 195
 196void BitStream::clear()
 197{
 198   dMemset(mDataPtr, 0, bufSize);
 199}
 200
 201void BitStream::writeClassId(U32 classId, U32 classType, U32 classGroup)
 202{
 203   AssertFatal(classType < NetClassTypesCount, "Out of range class type.");
 204   AssertFatal(classGroup < NetClassGroupsCount, "Out of range class group.");
 205   AssertFatal(classId < AbstractClassRep::NetClassCount[classGroup][classType], "Out of range class id.");
 206   AssertFatal(AbstractClassRep::NetClassCount[classGroup][classType] < (1 << AbstractClassRep::NetClassBitSize[classGroup][classType]), 
 207      "NetClassBitSize too small!");
 208
 209   writeInt(classId, AbstractClassRep::NetClassBitSize[classGroup][classType]);
 210}
 211
 212S32 BitStream::readClassId(U32 classType, U32 classGroup)
 213{
 214   AssertFatal(classType < NetClassTypesCount, "Out of range class type.");
 215   AssertFatal(classGroup < NetClassGroupsCount, "Out of range class group.");
 216   AssertFatal(AbstractClassRep::NetClassCount[classGroup][classType] < (1 << AbstractClassRep::NetClassBitSize[classGroup][classType]), 
 217      "NetClassBitSize too small!");
 218
 219   S32 ret = readInt(AbstractClassRep::NetClassBitSize[classGroup][classType]);
 220
 221   AssertFatal(ret < AbstractClassRep::NetClassCount[classGroup][classType], "BitStream::readClassId - unexpected class ID!");
 222   if(ret >= AbstractClassRep::NetClassCount[classGroup][classType])
 223      return -1;
 224   return ret;
 225}
 226
 227void BitStream::writeBits(S32 bitCount, const void *bitPtr)
 228{
 229   if(!bitCount)
 230      return;
 231
 232   if(bitCount + bitNum > maxWriteBitNum)
 233   {
 234      error = true;
 235      AssertFatal(false, "Out of range write");
 236      return;
 237   }
 238
 239   // [tom, 8/17/2006] This is probably a lot lamer then it needs to be. However,
 240   // at least it doesnt clobber data or overrun the buffer like the old code did.
 241   const U8 *ptr = (U8 *)bitPtr;
 242
 243   for(S32 srcBitNum = 0;srcBitNum < bitCount;srcBitNum++)
 244   {
 245      if((*(ptr + (srcBitNum >> 3)) & (1 << (srcBitNum & 0x7))) != 0)
 246         *(mDataPtr + (bitNum >> 3)) |= (1 << (bitNum & 0x7));
 247      else
 248         *(mDataPtr + (bitNum >> 3)) &= ~(1 << (bitNum & 0x7));
 249      bitNum++;
 250   }
 251}
 252
 253void BitStream::setBit(S32 bitCount, bool set)
 254{
 255   if(set)
 256      *(mDataPtr + (bitCount >> 3)) |= (1 << (bitCount & 0x7));
 257   else
 258      *(mDataPtr + (bitCount >> 3)) &= ~(1 << (bitCount & 0x7));
 259}
 260
 261bool BitStream::testBit(S32 bitCount)
 262{
 263   return (*(mDataPtr + (bitCount >> 3)) & (1 << (bitCount & 0x7))) != 0;
 264}
 265
 266bool BitStream::writeFlag(bool val)
 267{
 268   if(bitNum + 1 > maxWriteBitNum)
 269   {
 270      error = true;
 271      AssertFatal(false, "Out of range write");
 272      return false;
 273   }
 274   if(val)
 275      *(mDataPtr + (bitNum >> 3)) |= (1 << (bitNum & 0x7));
 276   else
 277      *(mDataPtr + (bitNum >> 3)) &= ~(1 << (bitNum & 0x7));
 278   bitNum++;
 279   return (val);
 280}
 281
 282void BitStream::readBits(S32 bitCount, void *bitPtr)
 283{
 284   if(!bitCount)
 285      return;
 286   if(bitCount + bitNum > maxReadBitNum)
 287   {
 288      error = true;
 289      //AssertFatal(false, "Out of range read");
 290      AssertWarn(false, "Out of range read");
 291      return;
 292   }
 293   U8 *stPtr = mDataPtr + (bitNum >> 3);
 294   S32 byteCount = (bitCount + 7) >> 3;
 295
 296   U8 *ptr = (U8 *) bitPtr;
 297
 298   S32 downShift = bitNum & 0x7;
 299   S32 upShift = 8 - downShift;
 300
 301   U8 curB = *stPtr;
 302   const U8 *stEnd = mDataPtr + bufSize;
 303   while(byteCount--)
 304   {
 305      stPtr++;
 306      U8 nextB = stPtr < stEnd ? *stPtr : 0;
 307      *ptr++ = (curB >> downShift) | (nextB << upShift);
 308      curB = nextB;
 309   }
 310
 311   bitNum += bitCount;
 312}
 313
 314bool BitStream::_read(U32 size, void *dataPtr)
 315{
 316   readBits(size << 3, dataPtr);
 317   return true;
 318}
 319
 320bool BitStream::_write(U32 size, const void *dataPtr)
 321{
 322   writeBits(size << 3, dataPtr);
 323   return true;
 324}
 325
 326S32 BitStream::readInt(S32 bitCount)
 327{
 328   S32 ret = 0;
 329   readBits(bitCount, &ret);
 330   ret = convertLEndianToHost(ret);
 331   if(bitCount == 32)
 332      return ret;
 333   else
 334      ret &= (1 << bitCount) - 1;
 335   return ret;
 336}
 337
 338void BitStream::writeInt(S32 val, S32 bitCount)
 339{
 340   AssertFatal((bitCount == 32) || ((val >> bitCount) == 0), avar("BitStream::writeInt: value out of range: %i/%i (%i bits)", val, 1 << bitCount, bitCount));
 341
 342   val = convertHostToLEndian(val);
 343   writeBits(bitCount, &val);
 344}
 345
 346void BitStream::writeFloat(F32 f, S32 bitCount)
 347{
 348   writeInt((S32)(f * ((1 << bitCount) - 1)), bitCount);
 349}
 350
 351F32 BitStream::readFloat(S32 bitCount)
 352{
 353   return readInt(bitCount) / F32((1 << bitCount) - 1);
 354}
 355
 356void BitStream::writeSignedFloat(F32 f, S32 bitCount)
 357{
 358   writeInt((S32)(((f + 1) * .5) * ((1 << bitCount) - 1)), bitCount);
 359}
 360
 361F32 BitStream::readSignedFloat(S32 bitCount)
 362{
 363   return readInt(bitCount) * 2 / F32((1 << bitCount) - 1) - 1.0f;
 364}
 365
 366void BitStream::writeSignedInt(S32 value, S32 bitCount)
 367{
 368   if(writeFlag(value < 0))
 369      writeInt(-value, bitCount - 1);
 370   else
 371      writeInt(value, bitCount - 1);
 372}
 373
 374S32 BitStream::readSignedInt(S32 bitCount)
 375{
 376   if(readFlag())
 377      return -readInt(bitCount - 1);
 378   else
 379      return readInt(bitCount - 1);
 380}
 381
 382void BitStream::writeNormalVector(const Point3F& vec, S32 bitCount)
 383{
 384   F32 phi   = mAtan2(vec.x, vec.y) / M_PI;
 385   F32 theta = mAtan2(vec.z, mSqrt(vec.x*vec.x + vec.y*vec.y)) / (M_PI/2.0);
 386
 387   writeSignedFloat(phi, bitCount+1);
 388   writeSignedFloat(theta, bitCount);
 389}
 390
 391void BitStream::readNormalVector(Point3F *vec, S32 bitCount)
 392{
 393   F32 phi   = readSignedFloat(bitCount+1) * M_PI;
 394   F32 theta = readSignedFloat(bitCount) * (M_PI/2.0);
 395
 396   vec->x = mSin(phi)*mCos(theta);
 397   vec->y = mCos(phi)*mCos(theta);
 398   vec->z = mSin(theta);
 399}
 400
 401Point3F BitStream::dumbDownNormal(const Point3F& vec, S32 bitCount)
 402{
 403   U8 buffer[128];
 404   BitStream temp(buffer, 128);
 405
 406   temp.writeNormalVector(vec, bitCount);
 407   temp.setCurPos(0);
 408
 409   Point3F ret;
 410   temp.readNormalVector(&ret, bitCount);
 411   return ret;
 412}
 413
 414void BitStream::writeVector( Point3F vec, F32 maxMag, S32 magBits, S32 normalBits )
 415{
 416   F32 mag = vec.len();
 417
 418   // If its zero length then we're done.
 419   if ( !writeFlag( mag > 0.0f ) )
 420      return;
 421
 422   // Write the magnitude compressed unless its greater than the maximum.
 423   if ( writeFlag( mag < maxMag ) )
 424      writeFloat( mag / maxMag, magBits );
 425   else
 426      write( mag );
 427
 428   // Finally write the normal part.
 429   vec *= 1.0f / mag;
 430   writeNormalVector( vec, normalBits );
 431}
 432
 433void BitStream::readVector( Point3F *outVec, F32 maxMag, S32 magBits, S32 normalBits )
 434{
 435   // Nothing more to do if we got a zero length vector.
 436   if ( !readFlag() )
 437   {
 438      outVec->set(0,0,0);
 439      return;
 440   }
 441
 442   // Read the compressed or uncompressed magnitude.
 443   F32 mag;
 444   if ( readFlag() )
 445      mag = readFloat( magBits ) * maxMag;
 446   else
 447      read( &mag );
 448
 449   // Finally read the normal and reconstruct the vector.
 450   readNormalVector( outVec, normalBits );
 451   *outVec *= mag;
 452}
 453
 454void BitStream::writeAffineTransform(const MatrixF& matrix)
 455{
 456//   AssertFatal(matrix.isAffine() == true,
 457//               "BitStream::writeAffineTransform: Error, must write only affine transforms!");
 458
 459   Point3F pos;
 460   matrix.getColumn(3, &pos);
 461   mathWrite(*this, pos);
 462
 463   QuatF q(matrix);
 464   q.normalize();
 465   write(q.x);
 466   write(q.y);
 467   write(q.z);
 468   writeFlag(q.w < 0.0);
 469}
 470
 471void BitStream::readAffineTransform(MatrixF* matrix)
 472{
 473   Point3F pos;
 474   QuatF   q;
 475
 476   mathRead(*this, &pos);
 477   read(&q.x);
 478   read(&q.y);
 479   read(&q.z);
 480   q.w = mSqrt(1.0 - getMin(F32(((q.x * q.x) + (q.y * q.y) + (q.z * q.z))), 1.f));
 481   if (readFlag())
 482      q.w = -q.w;
 483
 484   q.setMatrix(matrix);
 485   matrix->setColumn(3, pos);
 486//   AssertFatal(matrix->isAffine() == true,
 487//               "BitStream::readAffineTransform: Error, transform should be affine after this function!");
 488}
 489
 490void BitStream::writeQuat( const QuatF& quat, U32 bitCount )
 491{
 492   F32 quatVals[4] = { quat.x, quat.y, quat.z, quat.w };
 493   bool flipQuat = (quatVals[0] < 0);
 494   F32 maxVal = mFabs(quatVals[0]);
 495   S32 idxMax = 0;
 496
 497   for (S32 i = 1; i < 4; ++i)
 498   {
 499      if (mFabs(quatVals[i]) > maxVal)
 500      {
 501         idxMax = i;
 502         maxVal = mFabs(quatVals[i]);
 503         flipQuat = (quatVals[i] < 0);
 504      }
 505   }
 506   writeInt(idxMax, 2);
 507
 508   for (S32 i = 0; i < 4; ++i)
 509   {
 510      if (i == idxMax)
 511         continue;
 512      F32 curValue = (flipQuat ? -quatVals[i] : quatVals[i]) * (F32) M_SQRT2;
 513      writeSignedFloat( curValue, bitCount );
 514   }
 515}
 516
 517void BitStream::readQuat( QuatF *outQuat, U32 bitCount )
 518{
 519   F32 quatVals[4];
 520   F32 sum = 0.0f;
 521
 522   S32 idxMax = readInt( 2 );
 523   for (S32 i = 0; i < 4; ++i)
 524   {
 525      if (i == idxMax)
 526         continue;
 527      quatVals[i] = readSignedFloat( bitCount ) * M_SQRTHALF_F;
 528      sum += quatVals[i] * quatVals[i];
 529   }
 530
 531   if (sum > 1.0f)
 532      quatVals[idxMax] = 1.0f;
 533   else
 534      quatVals[idxMax] = mSqrt(1.0f - sum);
 535
 536   outQuat->set(quatVals[0], quatVals[1], quatVals[2], quatVals[3]);
 537}
 538
 539void BitStream::writeBits( const BitVector &bitvec )
 540{
 541   U32 size = bitvec.getSize();   
 542   if ( writeFlag( size <= 127 ) )
 543      writeInt( size, 7 );
 544   else
 545      write( size );
 546
 547   writeBits( bitvec.getSize(), bitvec.getBits() );
 548}
 549
 550void BitStream::readBits( BitVector *bitvec )
 551{
 552   U32 size;   
 553   if ( readFlag() ) // size <= 127
 554      size = readInt( 7 );
 555   else
 556      read( &size );
 557
 558   bitvec->setSize( size );
 559   readBits( size, bitvec->getBits() );
 560}
 561
 562//----------------------------------------------------------------------------
 563
 564void BitStream::clearCompressionPoint()
 565{
 566   mCompressPoint.set(0,0,0);
 567}
 568
 569void BitStream::setCompressionPoint(const Point3F& p)
 570{
 571   mCompressPoint = p;
 572}
 573
 574static U32 gBitCounts[4] = {
 575   16, 18, 20, 32
 576};
 577
 578void BitStream::writeCompressedPoint(const Point3F& p,F32 scale)
 579{
 580   // Same # of bits for all axis
 581   Point3F vec;
 582   F32 invScale = 1 / scale;
 583   U32 type;
 584   vec = p - mCompressPoint;
 585   F32 dist = vec.len() * invScale;
 586   if(dist < (1 << 15))
 587      type = 0;
 588   else if(dist < (1 << 17))
 589      type = 1;
 590   else if(dist < (1 << 19))
 591      type = 2;
 592   else
 593      type = 3;
 594
 595   writeInt(type, 2);
 596
 597   if (type != 3)
 598   {
 599      type = gBitCounts[type];
 600      writeSignedInt(S32(vec.x * invScale + 0.5f),type);
 601      writeSignedInt(S32(vec.y * invScale + 0.5f),type);
 602      writeSignedInt(S32(vec.z * invScale + 0.5f),type);
 603   }
 604   else
 605   {
 606      write(p.x);
 607      write(p.y);
 608      write(p.z);
 609   }
 610}
 611
 612void BitStream::readCompressedPoint(Point3F* p,F32 scale)
 613{
 614   // Same # of bits for all axis
 615   U32 type = readInt(2);
 616
 617   if(type == 3)
 618   {
 619      read(&p->x);
 620      read(&p->y);
 621      read(&p->z);
 622   }
 623   else
 624   {
 625      type = gBitCounts[type];
 626      p->x = (F32)readSignedInt(type);
 627      p->y = (F32)readSignedInt(type);
 628      p->z = (F32)readSignedInt(type);
 629
 630      p->x = mCompressPoint.x + p->x * scale;
 631      p->y = mCompressPoint.y + p->y * scale;
 632      p->z = mCompressPoint.z + p->z * scale;
 633   }
 634}
 635
 636//------------------------------------------------------------------------------
 637
 638InfiniteBitStream::InfiniteBitStream()
 639{
 640   //
 641}
 642
 643InfiniteBitStream::~InfiniteBitStream()
 644{
 645   //
 646}
 647
 648void InfiniteBitStream::reset()
 649{
 650   // Rewing back to beginning
 651   setPosition(0);
 652}
 653
 654void InfiniteBitStream::validate(U32 upcomingBytes)
 655{
 656   if(getPosition() + upcomingBytes + mMinSpace > bufSize)
 657   {
 658      bufSize = getPosition() + upcomingBytes + mMinSpace;
 659     mDataPtr = (U8 *) dRealloc(mDataPtr, bufSize);
 660
 661      maxReadBitNum = bufSize << 3;
 662      maxWriteBitNum = bufSize << 3;
 663   }
 664}
 665
 666void InfiniteBitStream::compact()
 667{
 668   // Prepare to copy...
 669   U32 oldSize = bufSize;
 670   U8 *tmp = (U8*)dMalloc(bufSize);
 671
 672   // Copy things...
 673   bufSize = getPosition() + mMinSpace * 2;
 674   dMemcpy(tmp, mDataPtr, oldSize);
 675
 676   // And clean up.
 677   dFree(mDataPtr);
 678   mDataPtr = tmp;
 679
 680   maxReadBitNum = bufSize << 3;
 681   maxWriteBitNum = bufSize << 3;
 682}
 683
 684void InfiniteBitStream::writeToStream(Stream &s)
 685{
 686   s.write(getPosition(), mDataPtr);
 687}
 688
 689//------------------------------------------------------------------------------
 690
 691void BitStream::readString(char buf[256])
 692{
 693   if(stringBuffer)
 694   {
 695      if(readFlag())
 696      {
 697         S32 offset = readInt(8);
 698         HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, stringBuffer + offset, 256 - offset);
 699         dStrcpy(buf, stringBuffer, 256);
 700         return;
 701      }
 702   }
 703   HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, buf, 256);
 704   if(stringBuffer)
 705      dStrcpy(stringBuffer, buf, 256);
 706}
 707
 708void BitStream::writeString(const char *string, S32 maxLen)
 709{
 710   if(!string)
 711      string = "";
 712   if(stringBuffer)
 713   {
 714      S32 j;
 715      for(j = 0; j < maxLen && stringBuffer[j] == string[j] && string[j];j++)
 716         ;
 717      dStrncpy(stringBuffer, string, maxLen);
 718      stringBuffer[maxLen] = 0;
 719
 720      if(writeFlag(j > 2))
 721      {
 722         writeInt(j, 8);
 723         HuffmanProcessor::g_huffProcessor.writeHuffBuffer(this, string + j, maxLen - j);
 724         return;
 725      }
 726   }
 727   HuffmanProcessor::g_huffProcessor.writeHuffBuffer(this, string, maxLen);
 728}
 729
 730void HuffmanProcessor::buildTables()
 731{
 732   AssertFatal(m_tablesBuilt == false, "Cannot build tables twice!");
 733   m_tablesBuilt = true;
 734
 735   S32 i;
 736
 737   // First, construct the array of wraps...
 738   //
 739   m_huffLeaves.setSize(256);
 740   m_huffNodes.reserve(256);
 741   m_huffNodes.increment();
 742   for (i = 0; i < 256; i++) {
 743      HuffLeaf& rLeaf = m_huffLeaves[i];
 744
 745      rLeaf.pop    = csm_charFreqs[i] + 1;
 746      rLeaf.symbol = U8(i);
 747
 748      dMemset(&rLeaf.code, 0, sizeof(rLeaf.code));
 749      rLeaf.numBits = 0;
 750   }
 751
 752   S32 currWraps = 256;
 753   HuffWrap* pWrap = new HuffWrap[256];
 754   for (i = 0; i < 256; i++) {
 755      pWrap[i].set(&m_huffLeaves[i]);
 756   }
 757
 758   while (currWraps != 1) {
 759      U32 min1 = 0xfffffffe, min2 = 0xffffffff;
 760      S32 index1 = -1, index2 = -1;
 761
 762      for (i = 0; i < currWraps; i++) {
 763         if (pWrap[i].getPop() < min1) {
 764            min2   = min1;
 765            index2 = index1;
 766
 767            min1   = pWrap[i].getPop();
 768            index1 = i;
 769         } else if (pWrap[i].getPop() < min2) {
 770            min2   = pWrap[i].getPop();
 771            index2 = i;
 772         }
 773      }
 774      AssertFatal(index1 != -1 && index2 != -1 && index1 != index2, "hrph");
 775
 776      // Create a node for this...
 777      m_huffNodes.increment();
 778      HuffNode& rNode = m_huffNodes.last();
 779      rNode.pop    = pWrap[index1].getPop() + pWrap[index2].getPop();
 780      rNode.index0 = determineIndex(pWrap[index1]);
 781      rNode.index1 = determineIndex(pWrap[index2]);
 782
 783      S32 mergeIndex = index1 > index2 ? index2 : index1;
 784      S32 nukeIndex  = index1 > index2 ? index1 : index2;
 785      pWrap[mergeIndex].set(&rNode);
 786
 787      if (index2 != (currWraps - 1)) {
 788         pWrap[nukeIndex] = pWrap[currWraps - 1];
 789      }
 790      currWraps--;
 791   }
 792   AssertFatal(currWraps == 1, "wrong wraps?");
 793   AssertFatal(pWrap[0].pNode != NULL && pWrap[0].pLeaf == NULL, "Wrong wrap type!");
 794
 795   // Ok, now we have one wrap, which is a node.  we need to make sure that this
 796   //  is the first node in the node list.
 797   m_huffNodes[0] = *(pWrap[0].pNode);
 798   delete [] pWrap;
 799
 800   U32 code = 0;
 801   BitStream bs(&code, 4);
 802
 803   generateCodes(bs, 0, 0);
 804}
 805
 806void HuffmanProcessor::generateCodes(BitStream& rBS, S32 index, S32 depth)
 807{
 808   if (index < 0) {
 809      // leaf node, copy the code in, and back out...
 810      HuffLeaf& rLeaf = m_huffLeaves[-(index + 1)];
 811
 812      dMemcpy(&rLeaf.code, rBS.mDataPtr, sizeof(rLeaf.code));
 813      rLeaf.numBits = depth;
 814   } else {
 815      HuffNode& rNode = m_huffNodes[index];
 816
 817      S32 pos = rBS.getCurPos();
 818
 819      rBS.writeFlag(false);
 820      generateCodes(rBS, rNode.index0, depth + 1);
 821
 822      rBS.setCurPos(pos);
 823      rBS.writeFlag(true);
 824      generateCodes(rBS, rNode.index1, depth + 1);
 825
 826      rBS.setCurPos(pos);
 827   }
 828}
 829
 830S16 HuffmanProcessor::determineIndex(HuffWrap& rWrap)
 831{
 832   if (rWrap.pLeaf != NULL) {
 833      AssertFatal(rWrap.pNode == NULL, "Got a non-NULL pNode in a HuffWrap with a non-NULL leaf.");
 834
 835      return -((rWrap.pLeaf - m_huffLeaves.address()) + 1);
 836   } else {
 837      AssertFatal(rWrap.pNode != NULL, "Got a NULL pNode in a HuffWrap with a NULL leaf.");
 838
 839      return rWrap.pNode - m_huffNodes.address();
 840   }
 841}
 842
 843bool HuffmanProcessor::readHuffBuffer(BitStream* pStream, char* out_pBuffer, S32 maxLen=256)
 844{
 845   if (m_tablesBuilt == false)
 846      buildTables();
 847
 848   if (pStream->readFlag()) {
 849      S32 len = pStream->readInt(8);
 850      if (len >= maxLen) {
 851         len = maxLen;
 852      }
 853      for (S32 i = 0; i < len; i++) {
 854         S32 index = 0;
 855         while (true) {
 856            if (index >= 0) {
 857               if (pStream->readFlag() == true) {
 858                  index = m_huffNodes[index].index1;
 859               } else {
 860                  index = m_huffNodes[index].index0;
 861               }
 862            } else {
 863               out_pBuffer[i] = m_huffLeaves[-(index+1)].symbol;
 864               break;
 865            }
 866         }
 867      }
 868      out_pBuffer[len] = '\0';
 869      return true;
 870   } else {
 871      // Uncompressed string...
 872      U32 len = pStream->readInt(8);
 873      if (len >= maxLen) {
 874         len = maxLen;
 875      }
 876      pStream->read(len, out_pBuffer);
 877      out_pBuffer[len] = '\0';
 878      return true;
 879   }
 880}
 881
 882bool HuffmanProcessor::writeHuffBuffer(BitStream* pStream, const char* out_pBuffer, S32 maxLen)
 883{
 884   if (out_pBuffer == NULL) {
 885      pStream->writeFlag(false);
 886      pStream->writeInt(0, 8);
 887      return true;
 888   }
 889
 890   if (m_tablesBuilt == false)
 891      buildTables();
 892
 893   S32 len = out_pBuffer ? dStrlen(out_pBuffer) : 0;
 894   AssertWarn(len <= 255, "String TOO long for writeString");
 895   AssertWarn(len <= 255, out_pBuffer);
 896   if (len > maxLen)
 897      len = maxLen;
 898
 899   S32 numBits = 0;
 900   S32 i;
 901   for (i = 0; i < len; i++)
 902      numBits += m_huffLeaves[(unsigned char)out_pBuffer[i]].numBits;
 903
 904   if (numBits >= (len * 8)) {
 905      pStream->writeFlag(false);
 906      pStream->writeInt(len, 8);
 907      pStream->write(len, out_pBuffer);
 908   } else {
 909      pStream->writeFlag(true);
 910      pStream->writeInt(len, 8);
 911      for (i = 0; i < len; i++) {
 912         HuffLeaf& rLeaf = m_huffLeaves[((unsigned char)out_pBuffer[i])];
 913         pStream->writeBits(rLeaf.numBits, &rLeaf.code);
 914      }
 915   }
 916
 917   return true;
 918}
 919
 920const U32 HuffmanProcessor::csm_charFreqs[256] = {
 9210     ,
 9220     ,
 9230     ,
 9240     ,
 9250     ,
 9260     ,
 9270     ,
 9280     ,
 9290     ,
 930329   ,
 93121    ,
 9320     ,
 9330     ,
 9340     ,
 9350     ,
 9360     ,
 9370     ,
 9380     ,
 9390     ,
 9400     ,
 9410     ,
 9420     ,
 9430     ,
 9440     ,
 9450     ,
 9460     ,
 9470     ,
 9480     ,
 9490     ,
 9500     ,
 9510     ,
 9520     ,
 9532809  ,
 95468    ,
 9550     ,
 95627    ,
 9570     ,
 95858    ,
 9593     ,
 96062    ,
 9614     ,
 9627     ,
 9630     ,
 9640     ,
 96515    ,
 96665    ,
 967554   ,
 9683     ,
 969394   ,
 970404   ,
 971189   ,
 972117   ,
 97330    ,
 97451    ,
 97527    ,
 97615    ,
 97734    ,
 97832    ,
 97980    ,
 9801     ,
 981142   ,
 9823     ,
 983142   ,
 98439    ,
 9850     ,
 986144   ,
 987125   ,
 98844    ,
 989122   ,
 990275   ,
 99170    ,
 992135   ,
 99361    ,
 994127   ,
 9958     ,
 99612    ,
 997113   ,
 998246   ,
 999122   ,
100036    ,
1001185   ,
10021     ,
1003149   ,
1004309   ,
1005335   ,
100612    ,
100711    ,
100814    ,
100954    ,
1010151   ,
10110     ,
10120     ,
10132     ,
10140     ,
10150     ,
1016211   ,
10170     ,
10182090  ,
1019344   ,
1020736   ,
1021993   ,
10222872  ,
1023701   ,
1024605   ,
1025646   ,
10261552  ,
1027328   ,
1028305   ,
10291240  ,
1030735   ,
10311533  ,
10321713  ,
1033562   ,
10343     ,
10351775  ,
10361149  ,
10371469  ,
1038979   ,
1039407   ,
1040553   ,
104159    ,
1042279   ,
104331    ,
10440     ,
10450     ,
10460     ,
104768    ,
10480     ,
10490     ,
10500     ,
10510     ,
10520     ,
10530     ,
10540     ,
10550     ,
10560     ,
10570     ,
10580     ,
10590     ,
10600     ,
10610     ,
10620     ,
10630     ,
10640     ,
10650     ,
10660     ,
10670     ,
10680     ,
10690     ,
10700     ,
10710     ,
10720     ,
10730     ,
10740     ,
10750     ,
10760     ,
10770     ,
10780     ,
10790     ,
10800     ,
10810     ,
10820     ,
10830     ,
10840     ,
10850     ,
10860     ,
10870     ,
10880     ,
10890     ,
10900     ,
10910     ,
10920     ,
10930     ,
10940     ,
10950     ,
10960     ,
10970     ,
10980     ,
10990     ,
11000     ,
11010     ,
11020     ,
11030     ,
11040     ,
11050     ,
11060     ,
11070     ,
11080     ,
11090     ,
11100     ,
11110     ,
11120     ,
11130     ,
11140     ,
11150     ,
11160     ,
11170     ,
11180     ,
11190     ,
11200     ,
11210     ,
11220     ,
11230     ,
11240     ,
11250     ,
11260     ,
11270     ,
11280     ,
11290     ,
11300     ,
11310     ,
11320     ,
11330     ,
11340     ,
11350     ,
11360     ,
11370     ,
11380     ,
11390     ,
11400     ,
11410     ,
11420     ,
11430     ,
11440     ,
11450     ,
11460     ,
11470     ,
11480     ,
11490     ,
11500     ,
11510     ,
11520     ,
11530     ,
11540     ,
11550     ,
11560     ,
11570     ,
11580     ,
11590     ,
11600     ,
11610     ,
11620     ,
11630     ,
11640     ,
11650     ,
11660     ,
11670     ,
11680     ,
11690     ,
11700     ,
11710     ,
11720     ,
11730     ,
11740     ,
11750     ,
11760
1177};
1178
1179