DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Base64.cpp (5739B)


      1 
      2 #include "precompiled.h"
      3 #pragma hdrstop
      4 
      5 /*
      6 Copyright (c) 1996 Lars Wirzenius.  All rights reserved.
      7 
      8 June 14 2003: TTimo <ttimo@idsoftware.com>
      9 	modified + endian bug fixes
     10 	http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=197039
     11 
     12 Redistribution and use in source and binary forms, with or without
     13 modification, are permitted provided that the following conditions
     14 are met:
     15 
     16 1. Redistributions of source code must retain the above copyright
     17    notice, this list of conditions and the following disclaimer.
     18 
     19 2. Redistributions in binary form must reproduce the above copyright
     20    notice, this list of conditions and the following disclaimer in the
     21    documentation and/or other materials provided with the distribution.
     22 
     23 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     24 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     26 DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     27 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     29 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     31 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     33 POSSIBILITY OF SUCH DAMAGE.
     34 */
     35 
     36 /*
     37 ============
     38 idBase64::Encode
     39 ============
     40 */
     41 static const char sixtet_to_base64[] = 
     42 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     43 
     44 void idBase64::Encode( const byte *from, int size ) {
     45 	int i, j;
     46 	unsigned long w;
     47 	byte *to;
     48 	
     49 	EnsureAlloced( 4*(size+3)/3 + 2 ); // ratio and padding + trailing \0
     50 	to = data;
     51 	
     52 	w = 0;
     53 	i = 0;
     54 	while (size > 0) {
     55 		w |= *from << i*8;
     56 		++from;
     57 		--size;
     58 		++i;
     59 		if (size == 0 || i == 3) {
     60 			byte out[4];
     61 			SixtetsForInt( out, w );
     62 			for (j = 0; j*6 < i*8; ++j) {
     63 				*to++ = sixtet_to_base64[ out[j] ];
     64 			}
     65 			if (size == 0) {
     66 				for (j = i; j < 3; ++j) {
     67 					*to++ = '=';
     68 				}
     69 			}
     70 			w = 0;
     71 			i = 0;
     72 		}
     73 	}
     74 	
     75 	*to++ = '\0';
     76 	len = to - data;
     77 }
     78 
     79 /*
     80 ============
     81 idBase64::DecodeLength
     82 returns the minimum size in bytes of the target buffer for decoding
     83 4 base64 digits <-> 3 bytes
     84 ============
     85 */
     86 int idBase64::DecodeLength( void ) const {
     87 	return 3*len/4;
     88 }
     89 
     90 /*
     91 ============
     92 idBase64::Decode
     93 ============
     94 */
     95 int idBase64::Decode( byte *to ) const {
     96 	unsigned long w;
     97 	int i, j;
     98 	size_t n;
     99 	static char base64_to_sixtet[256];
    100 	static int tab_init = 0;
    101 	byte *from = data;
    102 	
    103 	if (!tab_init) {
    104 		memset( base64_to_sixtet, 0, 256 );
    105 		for (i = 0; (j = sixtet_to_base64[i]) != '\0'; ++i) {
    106 			base64_to_sixtet[j] = i;
    107 		}
    108 		tab_init = 1;
    109 	}
    110 
    111 	w = 0;
    112 	i = 0;
    113 	n = 0;
    114 	byte in[4] = {0,0,0,0};
    115 	while (*from != '\0' && *from != '=' ) {
    116 		if (*from == ' ' || *from == '\n') {
    117 			++from;
    118 			continue;
    119 		}
    120 		in[i] = base64_to_sixtet[* (unsigned char *) from];
    121 		++i;
    122 		++from;
    123 		if (*from == '\0' || *from == '=' || i == 4) {
    124 			w = IntForSixtets( in );
    125 			for (j = 0; j*8 < i*6; ++j) {
    126 				*to++ = w & 0xff;
    127 				++n;
    128 				w >>= 8;
    129 			}
    130 			i = 0;
    131 			w = 0;
    132 		}
    133 	}
    134 	return n;
    135 }
    136 
    137 /*
    138 ============
    139 idBase64::Encode
    140 ============
    141 */
    142 void idBase64::Encode( const idStr &src ) {
    143 	Encode( (const byte *)src.c_str(), src.Length() );
    144 }
    145 
    146 /*
    147 ============
    148 idBase64::Decode
    149 ============
    150 */
    151 void idBase64::Decode( idStr &dest ) const {
    152 	byte *buf = new (TAG_IDLIB) byte[ DecodeLength()+1 ]; // +1 for trailing \0
    153 	int out = Decode( buf );
    154 	buf[out] = '\0';
    155 	dest = (const char *)buf;
    156 	delete[] buf;
    157 }
    158 
    159 /*
    160 ============
    161 idBase64::Decode
    162 ============
    163 */
    164 void idBase64::Decode( idFile *dest ) const {	
    165 	byte *buf = new (TAG_IDLIB) byte[ DecodeLength()+1 ]; // +1 for trailing \0
    166 	int out = Decode( buf );
    167 	dest->Write( buf, out );
    168 	delete[] buf;
    169 }
    170 
    171 #if 0
    172 
    173 void idBase64_TestBase64() {
    174 		
    175 	idStr src;
    176 	idBase64 dest;
    177 	src = "Encode me in base64";
    178 	dest.Encode( src );
    179 	idLib::common->Printf( "%s -> %s\n", src.c_str(), dest.c_str() );
    180 	dest.Decode( src );
    181 	idLib::common->Printf( "%s -> %s\n", dest.c_str(), src.c_str() );
    182 
    183 	idDict src_dict;
    184 	src_dict.SetFloat("float", 0.5f);
    185 	src_dict.SetBool("bool", true);
    186 	src_dict.Set("value", "foo");
    187 	idFile_Memory src_fmem("serialize_dict");	
    188 	src_dict.WriteToFileHandle( &src_fmem );
    189 	dest.Encode( (const byte *)src_fmem.GetDataPtr(), src_fmem.Length() );
    190 	idLib::common->Printf( "idDict encoded to %s\n", dest.c_str());
    191 	
    192 	// now decode to another stream and build back
    193 	idFile_Memory dest_fmem( "build_back" );
    194 	dest.Decode( &dest_fmem );
    195 	dest_fmem.MakeReadOnly();
    196 	idDict dest_dict;
    197 	dest_dict.ReadFromFileHandle( &dest_fmem );
    198 	idLib::common->Printf( "idDict reconstructed after base64 decode\n");
    199 	dest_dict.Print();
    200 	
    201 	// test idDict read from file - from python generated files, see idDict.py
    202 	idFile *file = idLib::fileSystem->OpenFileRead("idDict.test");
    203 	if (file) {
    204 		idDict test_dict;
    205 		test_dict.ReadFromFileHandle( file );
    206 		//
    207 		idLib::common->Printf( "read idDict.test:\n");
    208 		test_dict.Print();
    209 		idLib::fileSystem->CloseFile(file);
    210 		file = NULL;
    211 	} else {
    212 		idLib::common->Printf( "idDict.test not found\n" );
    213 	}
    214 
    215 	idBase64 base64_src;
    216 	void *buffer;
    217 	if ( idLib::fileSystem->ReadFile( "idDict.base64.test", &buffer ) != -1 ) {
    218 		idFile_Memory mem_src( "dict" );
    219 		idLib::common->Printf( "read: %d %s\n", idStr::Length( (char*)buffer ), buffer );
    220 		base64_src = (char *)buffer;
    221 		base64_src.Decode( &mem_src );
    222 		mem_src.MakeReadOnly();
    223 		idDict test_dict;
    224 		test_dict.ReadFromFileHandle( &mem_src );
    225 		idLib::common->Printf( "read idDict.base64.test:\n");
    226 		test_dict.Print();
    227 		idLib::fileSystem->FreeFile( buffer );
    228 	} else {
    229 		idLib::common->Printf( "idDict.base64.test not found\n" );
    230 	}
    231 }
    232 
    233 #endif