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

  1. //===== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. //
  7. // Encoder suitable for encoding binary data as key values
  8. //
  9. // Every 3 characters = 4 encoded characters
  10. // Syntax:
  11. // - a ... { A ... [ 0 ... 9
  12. // 0 1 ... 27 28 .. 54 55 .. 64
  13. //
  14. // SRC0 ... SRCN ...
  15. // FL X0 . XN ...
  16. // FL = 6 bits
  17. //
  18. // if Xk == 64 then SRCk is pad
  19. // else
  20. // SRCk = Xk + 64 * ( FL >> ( 2 * k ) % 4 )
  21. //
  22. #ifndef UTLENCODE_H
  23. #define UTLENCODE_H
  24. #pragma once
  25. namespace KvEncoder
  26. {
  27. inline char DecodeChar( char ch )
  28. {
  29. if ( ch == '-' )
  30. return 0;
  31. if ( ch >= 'a' && ch <= '{' )
  32. return 1 + ch - 'a';
  33. if ( ch >= 'A' && ch <= '[' )
  34. return 28 + ch - 'A';
  35. if ( ch >= '0' && ch <= '9' )
  36. return 55 + ch - '0';
  37. return -1;
  38. }
  39. inline char EncodeChar( char ch )
  40. {
  41. if ( ch == 0 )
  42. return '-';
  43. if ( ch >= 1 && ch <= 27 )
  44. return 'a' + ch - 1;
  45. if ( ch >= 28 && ch <= 54 )
  46. return 'A' + ch - 28;
  47. if ( ch >= 55 && ch <= 64 )
  48. return '0' + ch - 55;
  49. return -1;
  50. }
  51. inline unsigned long EncodeByte( unsigned char x )
  52. {
  53. unsigned int iSegment = x / 64;
  54. unsigned int iOffset = x % 64;
  55. return (
  56. ( unsigned long ) ( ( iOffset ) & 0xFFFF ) |
  57. ( unsigned long ) ( ( ( iSegment ) & 0xFFFF ) << 16 )
  58. );
  59. }
  60. inline unsigned char DecodeByte( int iSegment, int iOffset )
  61. {
  62. return iSegment * 64 + iOffset;
  63. }
  64. inline int GuessEncodedLength( int nLength )
  65. {
  66. return 4 * ( ( nLength + 2 ) / 3 );
  67. }
  68. inline int GuessDecodedLength( int nLength )
  69. {
  70. return 3 * ( ( nLength + 3 ) / 4 );
  71. }
  72. inline BOOL Encode( CUtlBuffer &src, CUtlBuffer &dst )
  73. {
  74. int numBytes = dst.Size();
  75. int nReqLen = GuessEncodedLength( src.TellPut() );
  76. if ( numBytes < nReqLen )
  77. return FALSE;
  78. char *pBase = (char *) dst.Base();
  79. char *pSrc = (char *) src.Base();
  80. int srcBytes = src.TellPut();
  81. while ( srcBytes > 0 )
  82. {
  83. char *pSegs = pBase;
  84. char *pOffs = pBase + 1;
  85. int flags = 0;
  86. for ( int k = 0; k < 3; ++ k )
  87. {
  88. if ( srcBytes -- > 0 )
  89. {
  90. unsigned long enc = EncodeByte( *pSrc ++ );
  91. *( pOffs ++ ) = EncodeChar( enc & 0xFFFF );
  92. flags |= ( enc >> 16 ) << ( 2 * k );
  93. }
  94. else
  95. {
  96. *( pOffs ++ ) = EncodeChar( 64 );
  97. }
  98. }
  99. *pSegs = EncodeChar( flags );
  100. pBase = pOffs;
  101. }
  102. dst.SeekPut( CUtlBuffer::SEEK_HEAD, nReqLen );
  103. return TRUE;
  104. }
  105. inline BOOL Decode( CUtlBuffer &src, CUtlBuffer &dst )
  106. {
  107. int numBytesLimit = dst.Size();
  108. char *pBase = (char *) src.Base();
  109. char *pData = (char *) dst.Base();
  110. char *pBaseEnd = pBase + src.TellPut();
  111. while ( pBase < pBaseEnd )
  112. {
  113. int flags = DecodeChar( *( pBase ++ ) );
  114. if ( -1 == flags )
  115. return FALSE;
  116. for ( int k = 0; k < 3 && pBase < pBaseEnd; ++ k )
  117. {
  118. int off = DecodeChar( *( pBase ++ ) );
  119. if ( off == -1 )
  120. return FALSE;
  121. if ( off == 64 )
  122. continue;
  123. int seg = flags >> ( 2 * k );
  124. seg %= 4;
  125. if ( numBytesLimit --> 0 )
  126. *( pData ++ ) = DecodeByte( seg, off );
  127. else
  128. return FALSE;
  129. }
  130. }
  131. int numBytes = dst.Size() - numBytesLimit;
  132. dst.SeekPut( CUtlBuffer::SEEK_HEAD, numBytes );
  133. return TRUE;
  134. }
  135. }; // namespace KvEncoder
  136. #endif // UTLENCODE_H