1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "core/stream/bitStream.h"
- #include "core/strings/stringFunctions.h"
- #include "math/mathIO.h"
- #include "console/consoleObject.h"
- #include "platform/platformNet.h"
- #include "core/bitVector.h"
- static BitStream gPacketStream(NULL, 0);
- static U8 gPacketBuffer[Net::MaxPacketDataSize];
- // bitstream utility functions
- void BitStream::clearStringBuffer()
- {
- static char stringBuf[256];
- stringBuf[0] = 0;
- // setStringBuffer( stringBuf );
- }
- void BitStream::setStringBuffer(char buffer[256])
- {
- // stringBuffer = buffer;
- }
- BitStream *BitStream::getPacketStream(U32 writeSize)
- {
- if(!writeSize)
- writeSize = Net::MaxPacketDataSize;
- gPacketStream.setBuffer(gPacketBuffer, writeSize, Net::MaxPacketDataSize);
- gPacketStream.setPosition(0);
- return &gPacketStream;
- }
- void BitStream::sendPacketStream(const NetAddress *addr)
- {
- Net::sendto(addr, gPacketStream.getBuffer(), gPacketStream.getPosition());
- }
- // CodeReview WTF is this additional IsEqual? - BJG, 3/29/07
- inline bool IsEqual(F32 a, F32 b) { return a == b; }
- ResizeBitStream::ResizeBitStream(U32 minSpace, U32 initialSize) : BitStream(NULL, 0, 0)
- {
- mMinSpace = minSpace;
- if(!initialSize)
- initialSize = minSpace * 2;
- U8 *buf = (U8 *) dMalloc(initialSize);
- setBuffer(buf, initialSize, initialSize);
- }
- ResizeBitStream::~ResizeBitStream()
- {
- dFree(mDataPtr);
- }
- void ResizeBitStream::validate()
- {
- if(getPosition() + mMinSpace > bufSize)
- {
- bufSize = getPosition() + mMinSpace * 2;
- mDataPtr = (U8 *) dRealloc(mDataPtr, bufSize);
- maxReadBitNum = bufSize << 3;
- maxWriteBitNum = bufSize << 3;
- }
- }
- class HuffmanProcessor
- {
- static const U32 csm_charFreqs[256];
- bool m_tablesBuilt;
- void buildTables();
- struct HuffNode {
- U32 pop;
- S16 index0;
- S16 index1;
- };
- struct HuffLeaf {
- U32 pop;
- U8 numBits;
- U8 symbol;
- U32 code; // no code should be longer than 32 bits.
- };
- // We have to be a bit careful with these, mSince they are pointers...
- struct HuffWrap {
- HuffNode* pNode;
- HuffLeaf* pLeaf;
- public:
- HuffWrap() : pNode(NULL), pLeaf(NULL) { }
- void set(HuffLeaf* in_leaf) { pNode = NULL; pLeaf = in_leaf; }
- void set(HuffNode* in_node) { pLeaf = NULL; pNode = in_node; }
- U32 getPop() { if (pNode) return pNode->pop; else return pLeaf->pop; }
- };
- Vector<HuffNode> m_huffNodes;
- Vector<HuffLeaf> m_huffLeaves;
- S16 determineIndex(HuffWrap&);
- void generateCodes(BitStream&, S32, S32);
- public:
- HuffmanProcessor() : m_tablesBuilt(false) { }
- static HuffmanProcessor g_huffProcessor;
- bool readHuffBuffer(BitStream* pStream, char* out_pBuffer, S32 maxLen);
- bool writeHuffBuffer(BitStream* pStream, const char* out_pBuffer, S32 maxLen);
- };
- HuffmanProcessor HuffmanProcessor::g_huffProcessor;
- void BitStream::setBuffer(void *bufPtr, S32 size, S32 maxSize)
- {
- mDataPtr = (U8 *) bufPtr;
- bitNum = 0;
- bufSize = size;
- maxReadBitNum = size << 3;
- if(maxSize < 0)
- maxSize = size;
- maxWriteBitNum = maxSize << 3;
- error = false;
- clearCompressionPoint();
- }
- U32 BitStream::getPosition() const
- {
- return (bitNum + 7) >> 3;
- }
- bool BitStream::setPosition(const U32 pos)
- {
- bitNum = pos << 3;
- return (true);
- }
- U32 BitStream::getStreamSize()
- {
- return bufSize;
- }
- U8 *BitStream::getBytePtr()
- {
- return mDataPtr + getPosition();
- }
- U32 BitStream::getReadByteSize()
- {
- return (maxReadBitNum >> 3) - getPosition();
- }
- U32 BitStream::getWriteByteSize()
- {
- return (maxWriteBitNum >> 3) - getPosition();
- }
- void BitStream::clear()
- {
- dMemset(mDataPtr, 0, bufSize);
- }
- void BitStream::writeClassId(U32 classId, U32 classType, U32 classGroup)
- {
- AssertFatal(classType < NetClassTypesCount, "Out of range class type.");
- AssertFatal(classGroup < NetClassGroupsCount, "Out of range class group.");
- AssertFatal(classId < AbstractClassRep::NetClassCount[classGroup][classType], "Out of range class id.");
- AssertFatal(AbstractClassRep::NetClassCount[classGroup][classType] < (1 << AbstractClassRep::NetClassBitSize[classGroup][classType]),
- "NetClassBitSize too small!");
- writeInt(classId, AbstractClassRep::NetClassBitSize[classGroup][classType]);
- }
- S32 BitStream::readClassId(U32 classType, U32 classGroup)
- {
- AssertFatal(classType < NetClassTypesCount, "Out of range class type.");
- AssertFatal(classGroup < NetClassGroupsCount, "Out of range class group.");
- AssertFatal(AbstractClassRep::NetClassCount[classGroup][classType] < (1 << AbstractClassRep::NetClassBitSize[classGroup][classType]),
- "NetClassBitSize too small!");
- S32 ret = readInt(AbstractClassRep::NetClassBitSize[classGroup][classType]);
- AssertFatal(ret < AbstractClassRep::NetClassCount[classGroup][classType], "BitStream::readClassId - unexpected class ID!");
- if(ret >= AbstractClassRep::NetClassCount[classGroup][classType])
- return -1;
- return ret;
- }
- void BitStream::writeBits(S32 bitCount, const void *bitPtr)
- {
- if(!bitCount)
- return;
- if((bitCount + bitNum) > maxWriteBitNum)
- {
- error = true;
- AssertFatal(false, avar("BitStream::writeBits - Out of range write [(%i+%i)/%i]", bitCount, bitNum, maxWriteBitNum));
- return;
- }
- // [tom, 8/17/2006] This is probably a lot lamer then it needs to be. However,
- // at least it doesnt clobber data or overrun the buffer like the old code did.
- const U8 *ptr = (U8 *)bitPtr;
- for(S32 srcBitNum = 0;srcBitNum < bitCount;srcBitNum++)
- {
- if((*(ptr + (srcBitNum >> 3)) & (1 << (srcBitNum & 0x7))) != 0)
- *(mDataPtr + (bitNum >> 3)) |= (1 << (bitNum & 0x7));
- else
- *(mDataPtr + (bitNum >> 3)) &= ~(1 << (bitNum & 0x7));
- bitNum++;
- }
- }
- void BitStream::setBit(S32 bitCount, bool set)
- {
- if(set)
- *(mDataPtr + (bitCount >> 3)) |= (1 << (bitCount & 0x7));
- else
- *(mDataPtr + (bitCount >> 3)) &= ~(1 << (bitCount & 0x7));
- }
- bool BitStream::testBit(S32 bitCount)
- {
- return (*(mDataPtr + (bitCount >> 3)) & (1 << (bitCount & 0x7))) != 0;
- }
- bool BitStream::writeFlag(bool val)
- {
- if((bitNum + 1) > maxWriteBitNum)
- {
- error = true;
- AssertFatal(false, avar("BitStream::writeFlag - Out of range write [%i/%i]", bitNum+1, maxWriteBitNum));
- return false;
- }
- if(val)
- *(mDataPtr + (bitNum >> 3)) |= (1 << (bitNum & 0x7));
- else
- *(mDataPtr + (bitNum >> 3)) &= ~(1 << (bitNum & 0x7));
- bitNum++;
- return (val);
- }
- void BitStream::readBits(S32 bitCount, void *bitPtr)
- {
- if(!bitCount)
- return;
- if(bitCount + bitNum > maxReadBitNum)
- {
- error = true;
- //AssertFatal(false, "Out of range read");
- AssertWarn(false, "Out of range read");
- return;
- }
- U8 *stPtr = mDataPtr + (bitNum >> 3);
- S32 byteCount = (bitCount + 7) >> 3;
- U8 *ptr = (U8 *) bitPtr;
- S32 downShift = bitNum & 0x7;
- S32 upShift = 8 - downShift;
- U8 curB = *stPtr;
- const U8 *stEnd = mDataPtr + bufSize;
- while(byteCount--)
- {
- stPtr++;
- U8 nextB = stPtr < stEnd ? *stPtr : 0;
- *ptr++ = (curB >> downShift) | (nextB << upShift);
- curB = nextB;
- }
- bitNum += bitCount;
- }
- bool BitStream::_read(U32 size, void *dataPtr)
- {
- readBits(size << 3, dataPtr);
- return true;
- }
- bool BitStream::_write(U32 size, const void *dataPtr)
- {
- writeBits(size << 3, dataPtr);
- return true;
- }
- S32 BitStream::readInt(S32 bitCount)
- {
- S32 ret = 0;
- readBits(bitCount, &ret);
- ret = convertLEndianToHost(ret);
- if(bitCount == 32)
- return ret;
- else
- ret &= (1 << bitCount) - 1;
- return ret;
- }
- void BitStream::writeInt(S32 val, S32 bitCount)
- {
- AssertFatal((bitCount == 32) || ((val >> bitCount) == 0), avar("BitStream::writeInt: value out of range: %i/%i (%i bits)", val, 1 << bitCount, bitCount));
- val = convertHostToLEndian(val);
- writeBits(bitCount, &val);
- }
- void BitStream::writeFloat(F32 f, S32 bitCount)
- {
- auto maxInt = (1U << bitCount) - 1;
- U32 i;
- if (f < POINT_EPSILON)
- {
- // Special case: <= 0 serializes to 0
- i = 0.0f;
- }
- else if (f == 0.5)
- {
- // Special case: 0.5 serializes to maxInt / 2 + 1
- i = maxInt / 2 + 1;
- }
- else if (f > (1.0f- POINT_EPSILON))
- {
- // Special case: >= 1 serializes to maxInt
- i = maxInt;
- }
- else
- {
- // Serialize normally but round the number
- i = static_cast<U32>(roundf(f * maxInt));
- }
- writeInt(i, bitCount);
- }
- F32 BitStream::readFloat(S32 bitCount)
- {
- auto maxInt = (1U << bitCount) - 1;
- auto i = static_cast<U32>(readInt(bitCount));
- if (i == 0)
- return 0;
- if (i == maxInt / 2 + 1)
- return 0.5;
- if (i == maxInt)
- return 1;
- return i / static_cast<F32>(maxInt);
- }
- void BitStream::writeSignedFloat(F32 f, S32 bitCount)
- {
- writeFloat((f + 1) / 2, bitCount);
- }
- F32 BitStream::readSignedFloat(S32 bitCount)
- {
- return readFloat(bitCount) * 2 - 1;
- }
- void BitStream::writeSignedInt(S32 value, S32 bitCount)
- {
- if(writeFlag(value < 0))
- writeInt(-value, bitCount - 1);
- else
- writeInt(value, bitCount - 1);
- }
- S32 BitStream::readSignedInt(S32 bitCount)
- {
- if(readFlag())
- return -readInt(bitCount - 1);
- else
- return readInt(bitCount - 1);
- }
- void BitStream::writeNormalVector(const Point3F& vec, S32 bitCount)
- {
- F32 phi = mAtan2(vec.x, vec.y) / M_PI;
- F32 theta = mAtan2(vec.z, mSqrt(vec.x*vec.x + vec.y*vec.y)) / (M_PI/2.0);
- writeSignedFloat(phi, bitCount+1);
- writeSignedFloat(theta, bitCount);
- }
- void BitStream::readNormalVector(Point3F *vec, S32 bitCount)
- {
- F32 phi = readSignedFloat(bitCount+1) * M_PI;
- F32 theta = readSignedFloat(bitCount) * (M_PI/2.0);
- vec->x = mSin(phi)*mCos(theta);
- vec->y = mCos(phi)*mCos(theta);
- vec->z = mSin(theta);
- }
- Point3F BitStream::dumbDownNormal(const Point3F& vec, S32 bitCount)
- {
- U8 buffer[128];
- BitStream temp(buffer, 128);
- temp.writeNormalVector(vec, bitCount);
- temp.setCurPos(0);
- Point3F ret;
- temp.readNormalVector(&ret, bitCount);
- return ret;
- }
- void BitStream::writeVector( Point3F vec, F32 maxMag, S32 magBits, S32 normalBits )
- {
- F32 mag = vec.len();
- // If its zero length then we're done.
- if ( !writeFlag( mag > 0.0f ) )
- return;
- // Write the magnitude compressed unless its greater than the maximum.
- if ( writeFlag( mag < maxMag ) )
- writeFloat( mag / maxMag, magBits );
- else
- write( mag );
- // Finally write the normal part.
- vec *= 1.0f / mag;
- writeNormalVector( vec, normalBits );
- }
- void BitStream::readVector( Point3F *outVec, F32 maxMag, S32 magBits, S32 normalBits )
- {
- // Nothing more to do if we got a zero length vector.
- if ( !readFlag() )
- {
- outVec->set(0,0,0);
- return;
- }
- // Read the compressed or uncompressed magnitude.
- F32 mag;
- if ( readFlag() )
- mag = readFloat( magBits ) * maxMag;
- else
- read( &mag );
- // Finally read the normal and reconstruct the vector.
- readNormalVector( outVec, normalBits );
- *outVec *= mag;
- }
- void BitStream::writeAffineTransform(const MatrixF& matrix)
- {
- // AssertFatal(matrix.isAffine() == true,
- // "BitStream::writeAffineTransform: Error, must write only affine transforms!");
- Point3F pos;
- matrix.getColumn(3, &pos);
- mathWrite(*this, pos);
- QuatF q(matrix);
- q.normalize();
- write(q.x);
- write(q.y);
- write(q.z);
- writeFlag(q.w < 0.0);
- }
- void BitStream::readAffineTransform(MatrixF* matrix)
- {
- Point3F pos;
- QuatF q;
- mathRead(*this, &pos);
- read(&q.x);
- read(&q.y);
- read(&q.z);
- q.w = mSqrt(1.0 - getMin(F32(((q.x * q.x) + (q.y * q.y) + (q.z * q.z))), 1.f));
- if (readFlag())
- q.w = -q.w;
- q.setMatrix(matrix);
- matrix->setColumn(3, pos);
- // AssertFatal(matrix->isAffine() == true,
- // "BitStream::readAffineTransform: Error, transform should be affine after this function!");
- }
- void BitStream::writeQuat( const QuatF& quat, U32 bitCount )
- {
- F32 quatVals[4] = { quat.x, quat.y, quat.z, quat.w };
- bool flipQuat = (quatVals[0] < 0);
- F32 maxVal = mFabs(quatVals[0]);
- S32 idxMax = 0;
- for (S32 i = 1; i < 4; ++i)
- {
- if (mFabs(quatVals[i]) > maxVal)
- {
- idxMax = i;
- maxVal = mFabs(quatVals[i]);
- flipQuat = (quatVals[i] < 0);
- }
- }
- writeInt(idxMax, 2);
- for (S32 i = 0; i < 4; ++i)
- {
- if (i == idxMax)
- continue;
- F32 curValue = (flipQuat ? -quatVals[i] : quatVals[i]) * (F32) M_SQRT2;
- writeSignedFloat( curValue, bitCount );
- }
- }
- void BitStream::readQuat( QuatF *outQuat, U32 bitCount )
- {
- F32 quatVals[4];
- F32 sum = 0.0f;
- S32 idxMax = readInt( 2 );
- for (S32 i = 0; i < 4; ++i)
- {
- if (i == idxMax)
- continue;
- quatVals[i] = readSignedFloat( bitCount ) * M_SQRTHALF_F;
- sum += quatVals[i] * quatVals[i];
- }
- if (sum > 1.0f)
- quatVals[idxMax] = 1.0f;
- else
- quatVals[idxMax] = mSqrt(1.0f - sum);
- outQuat->set(quatVals[0], quatVals[1], quatVals[2], quatVals[3]);
- }
- void BitStream::writeBits( const BitVector &bitvec )
- {
- U32 size = bitvec.getSize();
- if ( writeFlag( size <= 127 ) )
- writeInt( size, 7 );
- else
- write( size );
- writeBits( bitvec.getSize(), bitvec.getBits() );
- }
- void BitStream::readBits( BitVector *bitvec )
- {
- U32 size;
- if ( readFlag() ) // size <= 127
- size = readInt( 7 );
- else
- read( &size );
- bitvec->setSize( size );
- readBits( size, bitvec->getBits() );
- }
- //----------------------------------------------------------------------------
- void BitStream::clearCompressionPoint()
- {
- mCompressPoint.set(0,0,0);
- }
- void BitStream::setCompressionPoint(const Point3F& p)
- {
- mCompressPoint = p;
- }
- static U32 gBitCounts[4] = {
- 16, 18, 20, 32
- };
- void BitStream::writeCompressedPoint(const Point3F& p,F32 scale)
- {
- // Same # of bits for all axis
- Point3F vec;
- F32 invScale = 1 / scale;
- U32 type;
- vec = p - mCompressPoint;
- F32 dist = vec.len() * invScale;
- if(dist < (1 << 15))
- type = 0;
- else if(dist < (1 << 17))
- type = 1;
- else if(dist < (1 << 19))
- type = 2;
- else
- type = 3;
- writeInt(type, 2);
- if (type != 3)
- {
- type = gBitCounts[type];
- writeSignedInt(S32(vec.x * invScale + 0.5f),type);
- writeSignedInt(S32(vec.y * invScale + 0.5f),type);
- writeSignedInt(S32(vec.z * invScale + 0.5f),type);
- }
- else
- {
- write(p.x);
- write(p.y);
- write(p.z);
- }
- }
- void BitStream::readCompressedPoint(Point3F* p,F32 scale)
- {
- // Same # of bits for all axis
- U32 type = readInt(2);
- if(type == 3)
- {
- read(&p->x);
- read(&p->y);
- read(&p->z);
- }
- else
- {
- type = gBitCounts[type];
- p->x = (F32)readSignedInt(type);
- p->y = (F32)readSignedInt(type);
- p->z = (F32)readSignedInt(type);
- p->x = mCompressPoint.x + p->x * scale;
- p->y = mCompressPoint.y + p->y * scale;
- p->z = mCompressPoint.z + p->z * scale;
- }
- }
- //------------------------------------------------------------------------------
- InfiniteBitStream::InfiniteBitStream()
- {
- //
- }
- InfiniteBitStream::~InfiniteBitStream()
- {
- //
- }
- void InfiniteBitStream::reset()
- {
- // Rewing back to beginning
- setPosition(0);
- }
- void InfiniteBitStream::validate(U32 upcomingBytes)
- {
- if(getPosition() + upcomingBytes + mMinSpace > bufSize)
- {
- bufSize = getPosition() + upcomingBytes + mMinSpace;
- mDataPtr = (U8 *) dRealloc(mDataPtr, bufSize);
- maxReadBitNum = bufSize << 3;
- maxWriteBitNum = bufSize << 3;
- }
- }
- void InfiniteBitStream::compact()
- {
- // Prepare to copy...
- U32 oldSize = bufSize;
- U8 *tmp = (U8*)dMalloc(bufSize);
- // Copy things...
- bufSize = getPosition() + mMinSpace * 2;
- dMemcpy(tmp, mDataPtr, oldSize);
- // And clean up.
- dFree(mDataPtr);
- mDataPtr = tmp;
- maxReadBitNum = bufSize << 3;
- maxWriteBitNum = bufSize << 3;
- }
- void InfiniteBitStream::writeToStream(Stream &s)
- {
- s.write(getPosition(), mDataPtr);
- }
- //------------------------------------------------------------------------------
- void BitStream::readString(char buf[256])
- {
- if(stringBuffer)
- {
- if(readFlag())
- {
- S32 offset = readInt(8);
- HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, stringBuffer + offset, 256 - offset);
- dStrcpy(buf, stringBuffer, 256);
- return;
- }
- }
- HuffmanProcessor::g_huffProcessor.readHuffBuffer(this, buf, 256);
- if(stringBuffer)
- dStrcpy(stringBuffer, buf, 256);
- }
- void BitStream::writeString(const char *string, S32 maxLen)
- {
- if(!string)
- string = "";
- if(stringBuffer)
- {
- S32 j;
- for(j = 0; j < maxLen && stringBuffer[j] == string[j] && string[j];j++)
- ;
- dStrncpy(stringBuffer, string, maxLen);
- stringBuffer[maxLen] = 0;
- if(writeFlag(j > 2))
- {
- writeInt(j, 8);
- HuffmanProcessor::g_huffProcessor.writeHuffBuffer(this, string + j, maxLen - j);
- return;
- }
- }
- HuffmanProcessor::g_huffProcessor.writeHuffBuffer(this, string, maxLen);
- }
- void HuffmanProcessor::buildTables()
- {
- AssertFatal(m_tablesBuilt == false, "Cannot build tables twice!");
- m_tablesBuilt = true;
- S32 i;
- // First, construct the array of wraps...
- //
- m_huffLeaves.setSize(256);
- m_huffNodes.reserve(256);
- m_huffNodes.increment();
- for (i = 0; i < 256; i++) {
- HuffLeaf& rLeaf = m_huffLeaves[i];
- rLeaf.pop = csm_charFreqs[i] + 1;
- rLeaf.symbol = U8(i);
- dMemset(&rLeaf.code, 0, sizeof(rLeaf.code));
- rLeaf.numBits = 0;
- }
- S32 currWraps = 256;
- HuffWrap* pWrap = new HuffWrap[256];
- for (i = 0; i < 256; i++) {
- pWrap[i].set(&m_huffLeaves[i]);
- }
- while (currWraps != 1) {
- U32 min1 = 0xfffffffe, min2 = 0xffffffff;
- S32 index1 = -1, index2 = -1;
- for (i = 0; i < currWraps; i++) {
- if (pWrap[i].getPop() < min1) {
- min2 = min1;
- index2 = index1;
- min1 = pWrap[i].getPop();
- index1 = i;
- } else if (pWrap[i].getPop() < min2) {
- min2 = pWrap[i].getPop();
- index2 = i;
- }
- }
- AssertFatal(index1 != -1 && index2 != -1 && index1 != index2, "hrph");
- // Create a node for this...
- m_huffNodes.increment();
- HuffNode& rNode = m_huffNodes.last();
- rNode.pop = pWrap[index1].getPop() + pWrap[index2].getPop();
- rNode.index0 = determineIndex(pWrap[index1]);
- rNode.index1 = determineIndex(pWrap[index2]);
- S32 mergeIndex = index1 > index2 ? index2 : index1;
- S32 nukeIndex = index1 > index2 ? index1 : index2;
- pWrap[mergeIndex].set(&rNode);
- if (index2 != (currWraps - 1)) {
- pWrap[nukeIndex] = pWrap[currWraps - 1];
- }
- currWraps--;
- }
- AssertFatal(currWraps == 1, "wrong wraps?");
- AssertFatal(pWrap[0].pNode != NULL && pWrap[0].pLeaf == NULL, "Wrong wrap type!");
- // Ok, now we have one wrap, which is a node. we need to make sure that this
- // is the first node in the node list.
- m_huffNodes[0] = *(pWrap[0].pNode);
- delete [] pWrap;
- U32 code = 0;
- BitStream bs(&code, 4);
- generateCodes(bs, 0, 0);
- }
- void HuffmanProcessor::generateCodes(BitStream& rBS, S32 index, S32 depth)
- {
- if (index < 0) {
- // leaf node, copy the code in, and back out...
- HuffLeaf& rLeaf = m_huffLeaves[-(index + 1)];
- dMemcpy(&rLeaf.code, rBS.mDataPtr, sizeof(rLeaf.code));
- rLeaf.numBits = depth;
- } else {
- HuffNode& rNode = m_huffNodes[index];
- S32 pos = rBS.getCurPos();
- rBS.writeFlag(false);
- generateCodes(rBS, rNode.index0, depth + 1);
- rBS.setCurPos(pos);
- rBS.writeFlag(true);
- generateCodes(rBS, rNode.index1, depth + 1);
- rBS.setCurPos(pos);
- }
- }
- S16 HuffmanProcessor::determineIndex(HuffWrap& rWrap)
- {
- if (rWrap.pLeaf != NULL) {
- AssertFatal(rWrap.pNode == NULL, "Got a non-NULL pNode in a HuffWrap with a non-NULL leaf.");
- return -((rWrap.pLeaf - m_huffLeaves.address()) + 1);
- } else {
- AssertFatal(rWrap.pNode != NULL, "Got a NULL pNode in a HuffWrap with a NULL leaf.");
- return rWrap.pNode - m_huffNodes.address();
- }
- }
- bool HuffmanProcessor::readHuffBuffer(BitStream* pStream, char* out_pBuffer, S32 maxLen=256)
- {
- if (m_tablesBuilt == false)
- buildTables();
- if (pStream->readFlag()) {
- S32 len = pStream->readInt(8);
- if (len >= maxLen) {
- len = maxLen;
- }
- for (S32 i = 0; i < len; i++) {
- S32 index = 0;
- while (true) {
- if (index >= 0) {
- if (pStream->readFlag() == true) {
- index = m_huffNodes[index].index1;
- } else {
- index = m_huffNodes[index].index0;
- }
- } else {
- out_pBuffer[i] = m_huffLeaves[-(index+1)].symbol;
- break;
- }
- }
- }
- out_pBuffer[len] = '\0';
- return true;
- } else {
- // Uncompressed string...
- U32 len = pStream->readInt(8);
- if (len >= maxLen) {
- len = maxLen;
- }
- pStream->read(len, out_pBuffer);
- out_pBuffer[len] = '\0';
- return true;
- }
- }
- bool HuffmanProcessor::writeHuffBuffer(BitStream* pStream, const char* out_pBuffer, S32 maxLen)
- {
- if (out_pBuffer == NULL) {
- pStream->writeFlag(false);
- pStream->writeInt(0, 8);
- return true;
- }
- if (m_tablesBuilt == false)
- buildTables();
- S32 len = out_pBuffer ? dStrlen(out_pBuffer) : 0;
- AssertWarn(len <= 255, "String TOO long for writeString");
- AssertWarn(len <= 255, out_pBuffer);
- if (len > maxLen)
- len = maxLen;
- S32 numBits = 0;
- S32 i;
- for (i = 0; i < len; i++)
- numBits += m_huffLeaves[(unsigned char)out_pBuffer[i]].numBits;
- if (numBits >= (len * 8)) {
- pStream->writeFlag(false);
- pStream->writeInt(len, 8);
- pStream->write(len, out_pBuffer);
- } else {
- pStream->writeFlag(true);
- pStream->writeInt(len, 8);
- for (i = 0; i < len; i++) {
- HuffLeaf& rLeaf = m_huffLeaves[((unsigned char)out_pBuffer[i])];
- pStream->writeBits(rLeaf.numBits, &rLeaf.code);
- }
- }
- return true;
- }
- const U32 HuffmanProcessor::csm_charFreqs[256] = {
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 329 ,
- 21 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 2809 ,
- 68 ,
- 0 ,
- 27 ,
- 0 ,
- 58 ,
- 3 ,
- 62 ,
- 4 ,
- 7 ,
- 0 ,
- 0 ,
- 15 ,
- 65 ,
- 554 ,
- 3 ,
- 394 ,
- 404 ,
- 189 ,
- 117 ,
- 30 ,
- 51 ,
- 27 ,
- 15 ,
- 34 ,
- 32 ,
- 80 ,
- 1 ,
- 142 ,
- 3 ,
- 142 ,
- 39 ,
- 0 ,
- 144 ,
- 125 ,
- 44 ,
- 122 ,
- 275 ,
- 70 ,
- 135 ,
- 61 ,
- 127 ,
- 8 ,
- 12 ,
- 113 ,
- 246 ,
- 122 ,
- 36 ,
- 185 ,
- 1 ,
- 149 ,
- 309 ,
- 335 ,
- 12 ,
- 11 ,
- 14 ,
- 54 ,
- 151 ,
- 0 ,
- 0 ,
- 2 ,
- 0 ,
- 0 ,
- 211 ,
- 0 ,
- 2090 ,
- 344 ,
- 736 ,
- 993 ,
- 2872 ,
- 701 ,
- 605 ,
- 646 ,
- 1552 ,
- 328 ,
- 305 ,
- 1240 ,
- 735 ,
- 1533 ,
- 1713 ,
- 562 ,
- 3 ,
- 1775 ,
- 1149 ,
- 1469 ,
- 979 ,
- 407 ,
- 553 ,
- 59 ,
- 279 ,
- 31 ,
- 0 ,
- 0 ,
- 0 ,
- 68 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0 ,
- 0
- };
|