Counter Strike : Global Offensive Source Code
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.
 
 
 
 
 
 

161 lines
3.1 KiB

//===== Copyright © 1996-2008, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
//
// Encoder suitable for encoding binary data as key values
//
// Every 3 characters = 4 encoded characters
// Syntax:
// - a ... { A ... [ 0 ... 9
// 0 1 ... 27 28 .. 54 55 .. 64
//
// SRC0 ... SRCN ...
// FL X0 . XN ...
// FL = 6 bits
//
// if Xk == 64 then SRCk is pad
// else
// SRCk = Xk + 64 * ( FL >> ( 2 * k ) % 4 )
//
#ifndef UTLENCODE_H
#define UTLENCODE_H
#pragma once
namespace KvEncoder
{
inline char DecodeChar( char ch )
{
if ( ch == '-' )
return 0;
if ( ch >= 'a' && ch <= '{' )
return 1 + ch - 'a';
if ( ch >= 'A' && ch <= '[' )
return 28 + ch - 'A';
if ( ch >= '0' && ch <= '9' )
return 55 + ch - '0';
return -1;
}
inline char EncodeChar( char ch )
{
if ( ch == 0 )
return '-';
if ( ch >= 1 && ch <= 27 )
return 'a' + ch - 1;
if ( ch >= 28 && ch <= 54 )
return 'A' + ch - 28;
if ( ch >= 55 && ch <= 64 )
return '0' + ch - 55;
return -1;
}
inline unsigned long EncodeByte( unsigned char x )
{
unsigned int iSegment = x / 64;
unsigned int iOffset = x % 64;
return (
( unsigned long ) ( ( iOffset ) & 0xFFFF ) |
( unsigned long ) ( ( ( iSegment ) & 0xFFFF ) << 16 )
);
}
inline unsigned char DecodeByte( int iSegment, int iOffset )
{
return iSegment * 64 + iOffset;
}
inline int GuessEncodedLength( int nLength )
{
return 4 * ( ( nLength + 2 ) / 3 );
}
inline int GuessDecodedLength( int nLength )
{
return 3 * ( ( nLength + 3 ) / 4 );
}
inline BOOL Encode( CUtlBuffer &src, CUtlBuffer &dst )
{
int numBytes = dst.Size();
int nReqLen = GuessEncodedLength( src.TellPut() );
if ( numBytes < nReqLen )
return FALSE;
char *pBase = (char *) dst.Base();
char *pSrc = (char *) src.Base();
int srcBytes = src.TellPut();
while ( srcBytes > 0 )
{
char *pSegs = pBase;
char *pOffs = pBase + 1;
int flags = 0;
for ( int k = 0; k < 3; ++ k )
{
if ( srcBytes -- > 0 )
{
unsigned long enc = EncodeByte( *pSrc ++ );
*( pOffs ++ ) = EncodeChar( enc & 0xFFFF );
flags |= ( enc >> 16 ) << ( 2 * k );
}
else
{
*( pOffs ++ ) = EncodeChar( 64 );
}
}
*pSegs = EncodeChar( flags );
pBase = pOffs;
}
dst.SeekPut( CUtlBuffer::SEEK_HEAD, nReqLen );
return TRUE;
}
inline BOOL Decode( CUtlBuffer &src, CUtlBuffer &dst )
{
int numBytesLimit = dst.Size();
char *pBase = (char *) src.Base();
char *pData = (char *) dst.Base();
char *pBaseEnd = pBase + src.TellPut();
while ( pBase < pBaseEnd )
{
int flags = DecodeChar( *( pBase ++ ) );
if ( -1 == flags )
return FALSE;
for ( int k = 0; k < 3 && pBase < pBaseEnd; ++ k )
{
int off = DecodeChar( *( pBase ++ ) );
if ( off == -1 )
return FALSE;
if ( off == 64 )
continue;
int seg = flags >> ( 2 * k );
seg %= 4;
if ( numBytesLimit --> 0 )
*( pData ++ ) = DecodeByte( seg, off );
else
return FALSE;
}
}
int numBytes = dst.Size() - numBytesLimit;
dst.SeekPut( CUtlBuffer::SEEK_HEAD, numBytes );
return TRUE;
}
}; // namespace KvEncoder
#endif // UTLENCODE_H