bintools/rcomp/src/RCOSTRM.CPP
changeset 0 044383f39525
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 /*
       
     2 * Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <assert.h>
       
    20 #include <stdlib.h>
       
    21 #include <memory.h>
       
    22 
       
    23 #include "RESOURCE.H"          
       
    24 #include "DATATYPE.H"          
       
    25 #include "Parser.h"            
       
    26 #include "rcomp.hpp"           
       
    27 #include "NUMVAL.H"            
       
    28 #include "MEM.H"               
       
    29 #include "ERRORHAN.H"          
       
    30 #include "UNICODE_COMPRESSOR.H"
       
    31 #include "main.h"              
       
    32 
       
    33 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
    34 using std::endl;
       
    35 using std::cout;
       
    36 #endif //__MSVCDOTNET__
       
    37 
       
    38 extern int verbose;
       
    39 extern String::CharacterSet SourceCharacterSet;
       
    40 
       
    41 void Panic(int aCode) // used by UNICODE_COMPRESSOR.CPP
       
    42 	{
       
    43 	exit(aCode);
       
    44 	}
       
    45 
       
    46 RCTypeArray gTypes;
       
    47 
       
    48 // StructItem based ostream functions
       
    49 
       
    50 ostream& SimpleStructItem::StreamOut ( ostream & os)
       
    51 	{
       
    52 	return operator<< ( os, * this);
       
    53 	}
       
    54 
       
    55 ostream& ArrayStructItem::StreamOut ( ostream & os)
       
    56 	{
       
    57 	return operator<< ( os, * this);
       
    58 	}
       
    59 
       
    60 ostream& StructTypeStructItem::StreamOut ( ostream & os)
       
    61 	{
       
    62 	return operator<< ( os, * this);
       
    63 	}
       
    64 
       
    65 ostream& StructArrayStructItem::StreamOut ( ostream & os)
       
    66 	{
       
    67 	return operator<< ( os, * this);
       
    68 	}
       
    69 
       
    70 ostream& operator<< ( ostream & os, SimpleStructItem & o)
       
    71 	{
       
    72 	os << "SimpleStructItem        ";
       
    73 	os << o.iLabel;
       
    74 	os << "\t" << gTypes.GetName( o.iItemType);
       
    75 	os << "\tDefault: " << o.iDefault;
       
    76 	os << "\tLength limit: " << o.iLengthLimit;
       
    77 	os << endl;
       
    78 	return os ;
       
    79 	}
       
    80 
       
    81 ostream& operator<< ( ostream & os, ArrayStructItem & o)
       
    82 	{
       
    83 	os << "ArrayStructItem         ";
       
    84 	os << o.iLabel;
       
    85 	os << "\t" << gTypes.GetName( o.iItemType);
       
    86 	os << "\tDefaults: " << o.iDefaults;
       
    87 	os << "\tLen Type: " << ((o.iLenType == 0) ? "<none>" : gTypes.GetName(o.iLenType));
       
    88 	os << "\tSize: " << o.iSize;
       
    89 	os << endl;
       
    90 	return os ;
       
    91 	}
       
    92 
       
    93 ostream& operator<< ( ostream & os, StructTypeStructItem & o)
       
    94 	{
       
    95 	os << "StructTypeStructItem    ";
       
    96 	os << o.iLabel;
       
    97 	os << endl;
       
    98 	return os;
       
    99 	}
       
   100 
       
   101 ostream& operator<< ( ostream & os, StructArrayStructItem & o)
       
   102 	{
       
   103 	os << "StructArrayStructItem   ";
       
   104 	os << o.iLabel;
       
   105 	os << "\tLen Type: " << ( ( o.iLenType == 0) ? "<none>" : gTypes.GetName( o.iLenType) );
       
   106 	os << "\tSize: " << o.iSize;
       
   107 	os << endl;
       
   108 	return os;
       
   109 	}
       
   110 
       
   111 ostream& operator<< ( ostream & os, StructItemArray & o)
       
   112 	{
       
   113 	if (o.Size() == 0)
       
   114 		return ( os << "<none>");
       
   115 	StructItemArrayIterator next(o);
       
   116 	StructItem* p;
       
   117 	while ((p = next() ) != NULL)
       
   118 		p->StreamOut(os);
       
   119 	return os;
       
   120 	}
       
   121 
       
   122 ostream& operator<< ( ostream & os, StructHeader & o)
       
   123 	{
       
   124 	os << "StructHeader            ";
       
   125 	os << o.iLabel << endl;
       
   126 	os << "\tLen Type: " << ( ( o.iLenType == 0) ? "<none>" : gTypes.GetName( o.iLenType) ) << endl;
       
   127 	os << o.iSIA;
       
   128 	return os;
       
   129 	}
       
   130 
       
   131 ostream& operator<< ( ostream & os, StructHeaderArray & o)
       
   132 	{
       
   133 	if (o.Size() == 0)
       
   134 		return ( os << "<none>");
       
   135 	StructHeaderArrayIterator next( o);
       
   136 	StructHeader* p;
       
   137 	while ( ( p = next() ) != NULL)
       
   138 		os << *p;
       
   139 	return os;
       
   140 	}
       
   141 
       
   142 // ResourceItem based ostream functions
       
   143 
       
   144 ostream& SimpleResourceItem::StreamOut(ostream& os)
       
   145 	{
       
   146 	return operator<<(os,*this);
       
   147 	}
       
   148 
       
   149 ostream& ArrayResourceItem::StreamOut(ostream& os)
       
   150 	{
       
   151 	return operator<<(os,*this);
       
   152 	}
       
   153 
       
   154 ostream& StructTypeResourceItem::StreamOut(ostream& os)
       
   155 	{
       
   156 	return operator<<(os,*this);
       
   157 	}
       
   158 
       
   159 ostream& StructArrayResourceItem::StreamOut(ostream& os)
       
   160 	{
       
   161 	return operator<<(os,*this);
       
   162 	}
       
   163 
       
   164 ostream & operator<<(ostream& os,SimpleResourceItem& o)
       
   165 	{
       
   166 	os << "SimpleResourceItem [" << gTypes.GetName(o.iStructItem->iItemType) << " " << o.iStructItem->iLabel << "]  ";
       
   167 	switch( o.iStructItem->iItemType)
       
   168 		{
       
   169 		case L_TEXT:
       
   170 		case L_LTEXT:
       
   171 		case L_BUF:
       
   172 		case L_BYTE:
       
   173 		case L_WORD:
       
   174 		case L_LONG:
       
   175 			os << o.iValue;
       
   176 			break;
       
   177 		case L_SRLINK:
       
   178 			break;	// Don't know value yet.
       
   179 		}
       
   180 	os << endl;
       
   181 	return os;
       
   182 	}
       
   183 
       
   184 ostream & operator<< ( ostream & os, ArrayResourceItem & o)
       
   185 	{
       
   186 	os << "ArrayResourceItem [" << o.iStructItem->iLabel << "]  ";
       
   187 	os << o.iValues;
       
   188 	os << endl;
       
   189 	return os;
       
   190 	}
       
   191 
       
   192 ostream & operator<< ( ostream & os, StructTypeResourceItem & o)
       
   193 	{
       
   194 	static unsigned long level = 0;	// Recursion level.
       
   195 	os << "StructTypeResourceItem (Level " << level++ << ") ["  << o.iStructItem->iLabel << "]  " << endl;
       
   196 	os << "----------------------" << endl;
       
   197 	os << o.iResourceItems;
       
   198 	os << "----------------------" << endl;
       
   199 	level--;
       
   200 	return os;
       
   201 	}
       
   202 
       
   203 ostream & operator<< ( ostream & os, StructArrayResourceItem & o)
       
   204 	{
       
   205 	static unsigned long level = 0;	// Recursion level.
       
   206 	os << "StructArrayResourceItem (Level " << level++ << ") ["  << o.iStructItem->iLabel << "]  " << endl;
       
   207 	DataType counttype = o.iStructItem->iLenType;
       
   208 	if (counttype==0)
       
   209 		counttype = L_WORD;
       
   210 	unsigned long nitems = o.iArrayOfResourceItemArrays.Size();
       
   211 	os << "ArrayLength [" << gTypes.GetName(counttype) << "] " << nitems << endl;
       
   212 	if (nitems > 0)
       
   213 		{
       
   214 		os << "----------------------" << endl;
       
   215 		os << o.iArrayOfResourceItemArrays;
       
   216 		os << "----------------------" << endl;
       
   217 		}
       
   218 	level--;
       
   219 	return os;
       
   220 	}
       
   221 
       
   222 ostream & operator<< ( ostream & os, ResourceHeader & o)
       
   223 	{
       
   224 	os << "ResourceHeader          ";
       
   225 	os << o.iLabel << endl;
       
   226 	os << o.iRIA;
       
   227 	return os;
       
   228 	}
       
   229 
       
   230 ostream & operator<< ( ostream & os, ResourceItemArray & o)
       
   231 	{
       
   232 	os << "++ResourceItemArray" << endl;
       
   233 	if ( o.iLenType != 0)
       
   234 		{
       
   235 		os << "LenType: " << gTypes.GetName( o.iLenType) << "\t";
       
   236 		}
       
   237 	if ( o.Size() == 0)
       
   238 		return ( os << "<none>");
       
   239 	ResourceItemArrayIterator	next( o);
       
   240 	ResourceItem * p;
       
   241 	while ( ( p = next() ) != NULL)
       
   242 		p->StreamOut( os);
       
   243 	return os;
       
   244 	}
       
   245 
       
   246 ostream & operator<< ( ostream & os, ResourceItemArrayArray & o)
       
   247 	{
       
   248 	os << "--ResourceItemArrayArray" << endl;
       
   249 	if ( o.Size() == 0)
       
   250 		return ( os << "<none>");
       
   251 	ResourceItemArrayArrayIterator	next( o);
       
   252 	ResourceItemArray * p;
       
   253 	while ( ( p = next() ) != NULL)
       
   254 		os << * p;
       
   255 	return os;
       
   256 	}
       
   257 
       
   258 void StreamOutCompressingIfReducesSize(ResourceDataStream& aStream, const UTF16* aUncompressedUnicodeBuffer, int aUncompressedUnicodeLength)
       
   259 	{
       
   260 	const int uncompressedUnicodeSizeInBytes = aUncompressedUnicodeLength*2;
       
   261 
       
   262 	//
       
   263 	// Output buffer allocated to be one byte bigger than uncompressed input buffer.
       
   264 	// This is to allow for what appears to be the worst case where the string cannot be
       
   265 	// compressed at all.  In this case enough memory has to be allocated to contain
       
   266 	// the uncompressable string, plus the one-byte compression mode tag.
       
   267 	//
       
   268 	const int maximumOutputLengthInBytes = uncompressedUnicodeSizeInBytes;
       
   269 	unsigned char* const compressedUnicodeBuffer = new unsigned char[maximumOutputLengthInBytes];
       
   270 	assert(compressedUnicodeBuffer != NULL);
       
   271 
       
   272 	int compressedUnicodeSizeInBytes;
       
   273 	CompressUnicode(compressedUnicodeBuffer, compressedUnicodeSizeInBytes, maximumOutputLengthInBytes, aUncompressedUnicodeBuffer, aUncompressedUnicodeLength);
       
   274 
       
   275 	if (compressedUnicodeSizeInBytes < uncompressedUnicodeSizeInBytes)
       
   276 		{
       
   277 		aStream.StartOfCompressedUnicodeRun(uncompressedUnicodeSizeInBytes, (const unsigned char*)aUncompressedUnicodeBuffer);
       
   278 		aStream.StreamIn(compressedUnicodeBuffer, compressedUnicodeSizeInBytes);
       
   279 		aStream.EndOfCompressedUnicodeRun();
       
   280 		}
       
   281 	else if (uncompressedUnicodeSizeInBytes>0)
       
   282 		{
       
   283 		aStream.TwoByteAlignmentPoint();
       
   284 		aStream.StreamIn((const unsigned char*)aUncompressedUnicodeBuffer, uncompressedUnicodeSizeInBytes);
       
   285 		}
       
   286 
       
   287 	delete [] compressedUnicodeBuffer;
       
   288 	}
       
   289 
       
   290 // ResourceItem based RCBinaryStream functions
       
   291 // These are used to write the raw data as required in the final output file
       
   292 
       
   293 static void StreamOutSingleValue(
       
   294 	ResourceDataStream&	aStream,
       
   295 	const String &		aValue,
       
   296 	unsigned long		aLinkValue,
       
   297 	DataType 			aItemType,
       
   298 	const String *		aFileName,
       
   299 	int					aLineNumber
       
   300 	)
       
   301 	{
       
   302 	ErrorHandler::Register( aFileName, aLineNumber);	// Register in case conversion to number fails.
       
   303 
       
   304 
       
   305 
       
   306 	switch ( aItemType)
       
   307 		{
       
   308 
       
   309         // 8-bit text
       
   310 
       
   311 		case L_TEXT8:
       
   312             {	// Null terminator, no leading byte count.
       
   313            		unsigned char * p = new unsigned char[ aValue.Length() + 1];
       
   314 				if ( aValue.Length() > 0)
       
   315            			memcpy( p, aValue.GetAssertedNonEmptyBuffer(), aValue.Length() );
       
   316            		* ( p + aValue.Length() ) = '\0';
       
   317            		aStream.StreamIn(p, aValue.Length() + 1);
       
   318            		delete [] p;
       
   319             	break;
       
   320             }
       
   321 		case L_LTEXT8:
       
   322             {	// Leading byte count, no null terminator. (For zero length string a byte containing
       
   323             	// zero is written out.
       
   324 				assert ( aValue.Length() <= 255 );
       
   325            		unsigned char * p = new unsigned char[ aValue.Length() + 1];
       
   326 				if ( aValue.Length() > 0)
       
   327            			memcpy( p + 1, aValue.GetAssertedNonEmptyBuffer(), aValue.Length() );
       
   328            		*p = (unsigned char)(aValue.Length());
       
   329            		aStream.StreamIn(p, aValue.Length() + 1);
       
   330            		delete [] p;
       
   331             	break;
       
   332             }
       
   333 		case L_BUF8:	// Write just the characters from the string.
       
   334 			aStream.StreamIn((const unsigned char*)aValue.GetAssertedNonEmptyBuffer(), aValue.Length());
       
   335 			break;
       
   336 
       
   337 
       
   338         // 16-bit text
       
   339 
       
   340 
       
   341 
       
   342         case L_BUF16:   // write out unadorned 16-bit characters
       
   343             {
       
   344             int output_count;   // used as character count for binary output.
       
   345 
       
   346             // reserve enough for worst case
       
   347             output_count = aValue.Length();
       
   348             UTF16 *output_buffer = new UTF16[output_count];
       
   349 
       
   350             aValue.Export(output_buffer, output_count, SourceCharacterSet);
       
   351 
       
   352 			// write out the buffer as a stream of octets.
       
   353 			#if defined(__TOOLS2_WINDOWS__)
       
   354 			StreamOutCompressingIfReducesSize(aStream, (const unsigned short*)output_buffer, output_count);
       
   355 			#else
       
   356 			StreamOutCompressingIfReducesSize(aStream, output_buffer, output_count);
       
   357 			#endif
       
   358 
       
   359             delete [] output_buffer;
       
   360 
       
   361             break;
       
   362             }
       
   363 
       
   364 
       
   365 
       
   366         case L_TEXT16:  // write out a null-terminated string
       
   367 			// this has no support in BAFL
       
   368             {
       
   369             int output_count;   // used as character count for binary output.
       
   370 
       
   371             // reserve enough for worst case + null terminator.
       
   372             output_count = aValue.Length();
       
   373             UTF16 *output_buffer = new UTF16[output_count +1];
       
   374 
       
   375             aValue.Export(output_buffer, output_count, SourceCharacterSet);
       
   376             output_buffer[output_count] = 0;
       
   377             output_count +=1;
       
   378 
       
   379             // write out the buffer as a stream of octets.
       
   380 			#if defined(__TOOLS2_WINDOWS__)
       
   381 			StreamOutCompressingIfReducesSize(aStream, (const unsigned short*)output_buffer, output_count);
       
   382 			#else
       
   383 			StreamOutCompressingIfReducesSize(aStream, output_buffer, output_count);
       
   384 			#endif			
       
   385 
       
   386             delete [] output_buffer;
       
   387 
       
   388             break;
       
   389             }            
       
   390 
       
   391 
       
   392         case L_LTEXT16:  // write out counted string.  The count is in
       
   393                          // an octet, not a word.
       
   394 
       
   395             {
       
   396             int output_count;      // used as character count for binary output.
       
   397             unsigned char lbcount; // To hold the leading byte count.
       
   398 
       
   399             // reserve enough for worst case
       
   400             output_count = aValue.Length();
       
   401 	// XXX I have commented the assert statement below out, because an LTEXT can't have length
       
   402 	// XXX bigger than 255, but sometimes this happens. A solution would be to throw an error
       
   403 	// XXX in structst.cpp, in the SimpleStructItem::SimpleStructItem() constructor.
       
   404             UTF16 *output_buffer = new UTF16[output_count];
       
   405 
       
   406             aValue.Export(output_buffer, output_count, SourceCharacterSet);
       
   407 
       
   408             // write out the count.
       
   409 
       
   410             lbcount = (unsigned char) output_count;
       
   411             aStream.StreamIn(&lbcount,1);
       
   412 
       
   413             // write out the buffer as a stream of octets.
       
   414 	    StreamOutCompressingIfReducesSize(aStream, output_buffer, output_count);	
       
   415 
       
   416             delete [] output_buffer;
       
   417 
       
   418             break;
       
   419             }            
       
   420 
       
   421 
       
   422 
       
   423 
       
   424 		case L_BYTE:
       
   425 		case L_WORD:
       
   426 		case L_LONG:
       
   427 		case L_DOUBLE:
       
   428 			assert ( aValue.Length() > 0);
       
   429 			if(verbose) { MOFF; cout << "Converting " << aValue << " to number." << endl; MON;}
       
   430 			NumericValue( aValue, aItemType).StreamOut(aStream);
       
   431 			break;
       
   432 		case L_SRLINK:
       
   433 			NumericValue( aLinkValue, L_LONG).StreamOut(aStream);
       
   434 			break;
       
   435 		case L_LINK:
       
   436 		case L_LLINK:
       
   437 			{
       
   438 				if ( aValue.Length() > 0)
       
   439 				{
       
   440 					DataType dtype = ( aItemType == L_LINK) ? L_WORD : L_LONG;
       
   441 					if ( aValue.IsDecNatural() )	// If a resource id was specified explicitly e.g. -75 then output the value.
       
   442 						NumericValue(aValue, dtype).StreamOut(aStream);
       
   443 					else
       
   444 					{
       
   445 						// If FindId fails to find the link it will output an
       
   446 						// appropriate error and kill the program.
       
   447 						ErrorHandler::Register(aFileName, aLineNumber);
       
   448 						unsigned long id = pG->ResourceNameIds.FindId(aValue);
       
   449 						NumericValue(id, dtype).StreamOut(aStream);
       
   450 					}
       
   451 				}
       
   452 				break;
       
   453 			}
       
   454 		default:
       
   455 			{ 	MOFF; cout << "RCBinaryStream:Unknown type " << gTypes.GetName( aItemType) << endl; MON;}
       
   456 		}
       
   457 	}
       
   458 
       
   459 void SimpleResourceItem::StreamOut(ResourceDataStream& aStream) const
       
   460 	{
       
   461 	StreamOutSingleValue(aStream, iValue, iLinkValue, iStructItem->iItemType, iFileName, iLineNumber);
       
   462 	}
       
   463 
       
   464 void ArrayResourceItem::StreamOut(ResourceDataStream& aStream) const
       
   465 	{
       
   466 	NumericValue * itemcount = NULL;
       
   467 	if(iStructItem->iSize.Length() == 0)	// STRUCT item says [] i.e. no size specified.
       
   468 		{
       
   469 		if (iStructItem->iLenType == 0)	// No LEN declaration so default to WORD.
       
   470 			itemcount = new NumericValue( L_WORD);
       
   471 		else
       
   472 			itemcount = new NumericValue( iStructItem->iLenType); // Use specified type.
       
   473 
       
   474 		* itemcount = iValues.Size();
       
   475 		itemcount->StreamOut(aStream);
       
   476 		
       
   477 		delete itemcount;
       
   478 		}
       
   479 	if ( iValues.Size() == 0)
       
   480 		return;
       
   481 	StringArrayIterator next( iValues);
       
   482 	String * p;
       
   483 	while ( ( p = next() ) != NULL)
       
   484 		{
       
   485 		assert( iStructItem->iItemType != L_SRLINK);	// Can't handle arrays of SRlinks.
       
   486 		StreamOutSingleValue(aStream, *p, 0, iStructItem->iItemType, iFileName, iLineNumber);
       
   487 		}
       
   488 	}
       
   489 
       
   490 void StructTypeResourceItem::StreamOut(ResourceDataStream& aStream) const
       
   491 	{
       
   492 	iResourceItems.StreamOut(aStream);
       
   493 	}
       
   494 
       
   495 void StructArrayResourceItem::StreamOut(ResourceDataStream& aStream) const
       
   496 	{
       
   497 	NumericValue * itemcount = NULL;
       
   498 	if(iStructItem->iLenType == 0)	// No LEN declaration so default to WORD.
       
   499 		itemcount = new NumericValue( L_WORD);
       
   500 	else
       
   501 		itemcount = new NumericValue( iStructItem->iLenType); // Use specified type.
       
   502 	* itemcount = iArrayOfResourceItemArrays.Size();
       
   503 	itemcount->StreamOut(aStream);
       
   504 	delete itemcount;
       
   505 	if(iArrayOfResourceItemArrays.Size() == 0)
       
   506 		return;
       
   507 	iArrayOfResourceItemArrays.StreamOut(aStream);
       
   508 	}
       
   509 
       
   510 void ResourceItemArray::StreamOut(ResourceDataStream& aStream) const
       
   511 	{
       
   512 	if (Size() == 0)
       
   513 		return;
       
   514 	static unsigned int RecursionLevel = 0; // Top level should not have resource size output.
       
   515 	const bool outputSize=((iLenType != 0) && (RecursionLevel > 0));
       
   516 	if (outputSize)
       
   517 		{
       
   518 		aStream.StartOfBlockWithSizePrefix(iLenType);
       
   519 		}
       
   520 	RecursionLevel++;
       
   521 	ResourceItemArrayIterator next(*this);
       
   522 	ResourceItem * p;
       
   523 	while ( ( p = next() ) != NULL)
       
   524 		{
       
   525 		p->StreamOut(aStream);
       
   526 		}
       
   527 	RecursionLevel--;
       
   528 	if (outputSize)
       
   529 		{
       
   530 		aStream.EndOfBlockWithSizePrefix();
       
   531 		}
       
   532 	}
       
   533 
       
   534 void ResourceItemArrayArray::StreamOut(ResourceDataStream& aStream) const
       
   535 	{
       
   536 	if (Size() == 0)
       
   537 		return;
       
   538 	ResourceItemArrayArrayIterator next(*this);
       
   539 	ResourceItemArray * p;
       
   540 	while ( ( p = next() ) != NULL)
       
   541 		p->StreamOut(aStream);
       
   542 	}