bintools/rcomp/src/RCOSTRM.CPP
changeset 0 044383f39525
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bintools/rcomp/src/RCOSTRM.CPP	Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,542 @@
+/*
+* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <memory.h>
+
+#include "RESOURCE.H"          
+#include "DATATYPE.H"          
+#include "Parser.h"            
+#include "rcomp.hpp"           
+#include "NUMVAL.H"            
+#include "MEM.H"               
+#include "ERRORHAN.H"          
+#include "UNICODE_COMPRESSOR.H"
+#include "main.h"              
+
+#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
+using std::endl;
+using std::cout;
+#endif //__MSVCDOTNET__
+
+extern int verbose;
+extern String::CharacterSet SourceCharacterSet;
+
+void Panic(int aCode) // used by UNICODE_COMPRESSOR.CPP
+	{
+	exit(aCode);
+	}
+
+RCTypeArray gTypes;
+
+// StructItem based ostream functions
+
+ostream& SimpleStructItem::StreamOut ( ostream & os)
+	{
+	return operator<< ( os, * this);
+	}
+
+ostream& ArrayStructItem::StreamOut ( ostream & os)
+	{
+	return operator<< ( os, * this);
+	}
+
+ostream& StructTypeStructItem::StreamOut ( ostream & os)
+	{
+	return operator<< ( os, * this);
+	}
+
+ostream& StructArrayStructItem::StreamOut ( ostream & os)
+	{
+	return operator<< ( os, * this);
+	}
+
+ostream& operator<< ( ostream & os, SimpleStructItem & o)
+	{
+	os << "SimpleStructItem        ";
+	os << o.iLabel;
+	os << "\t" << gTypes.GetName( o.iItemType);
+	os << "\tDefault: " << o.iDefault;
+	os << "\tLength limit: " << o.iLengthLimit;
+	os << endl;
+	return os ;
+	}
+
+ostream& operator<< ( ostream & os, ArrayStructItem & o)
+	{
+	os << "ArrayStructItem         ";
+	os << o.iLabel;
+	os << "\t" << gTypes.GetName( o.iItemType);
+	os << "\tDefaults: " << o.iDefaults;
+	os << "\tLen Type: " << ((o.iLenType == 0) ? "<none>" : gTypes.GetName(o.iLenType));
+	os << "\tSize: " << o.iSize;
+	os << endl;
+	return os ;
+	}
+
+ostream& operator<< ( ostream & os, StructTypeStructItem & o)
+	{
+	os << "StructTypeStructItem    ";
+	os << o.iLabel;
+	os << endl;
+	return os;
+	}
+
+ostream& operator<< ( ostream & os, StructArrayStructItem & o)
+	{
+	os << "StructArrayStructItem   ";
+	os << o.iLabel;
+	os << "\tLen Type: " << ( ( o.iLenType == 0) ? "<none>" : gTypes.GetName( o.iLenType) );
+	os << "\tSize: " << o.iSize;
+	os << endl;
+	return os;
+	}
+
+ostream& operator<< ( ostream & os, StructItemArray & o)
+	{
+	if (o.Size() == 0)
+		return ( os << "<none>");
+	StructItemArrayIterator next(o);
+	StructItem* p;
+	while ((p = next() ) != NULL)
+		p->StreamOut(os);
+	return os;
+	}
+
+ostream& operator<< ( ostream & os, StructHeader & o)
+	{
+	os << "StructHeader            ";
+	os << o.iLabel << endl;
+	os << "\tLen Type: " << ( ( o.iLenType == 0) ? "<none>" : gTypes.GetName( o.iLenType) ) << endl;
+	os << o.iSIA;
+	return os;
+	}
+
+ostream& operator<< ( ostream & os, StructHeaderArray & o)
+	{
+	if (o.Size() == 0)
+		return ( os << "<none>");
+	StructHeaderArrayIterator next( o);
+	StructHeader* p;
+	while ( ( p = next() ) != NULL)
+		os << *p;
+	return os;
+	}
+
+// ResourceItem based ostream functions
+
+ostream& SimpleResourceItem::StreamOut(ostream& os)
+	{
+	return operator<<(os,*this);
+	}
+
+ostream& ArrayResourceItem::StreamOut(ostream& os)
+	{
+	return operator<<(os,*this);
+	}
+
+ostream& StructTypeResourceItem::StreamOut(ostream& os)
+	{
+	return operator<<(os,*this);
+	}
+
+ostream& StructArrayResourceItem::StreamOut(ostream& os)
+	{
+	return operator<<(os,*this);
+	}
+
+ostream & operator<<(ostream& os,SimpleResourceItem& o)
+	{
+	os << "SimpleResourceItem [" << gTypes.GetName(o.iStructItem->iItemType) << " " << o.iStructItem->iLabel << "]  ";
+	switch( o.iStructItem->iItemType)
+		{
+		case L_TEXT:
+		case L_LTEXT:
+		case L_BUF:
+		case L_BYTE:
+		case L_WORD:
+		case L_LONG:
+			os << o.iValue;
+			break;
+		case L_SRLINK:
+			break;	// Don't know value yet.
+		}
+	os << endl;
+	return os;
+	}
+
+ostream & operator<< ( ostream & os, ArrayResourceItem & o)
+	{
+	os << "ArrayResourceItem [" << o.iStructItem->iLabel << "]  ";
+	os << o.iValues;
+	os << endl;
+	return os;
+	}
+
+ostream & operator<< ( ostream & os, StructTypeResourceItem & o)
+	{
+	static unsigned long level = 0;	// Recursion level.
+	os << "StructTypeResourceItem (Level " << level++ << ") ["  << o.iStructItem->iLabel << "]  " << endl;
+	os << "----------------------" << endl;
+	os << o.iResourceItems;
+	os << "----------------------" << endl;
+	level--;
+	return os;
+	}
+
+ostream & operator<< ( ostream & os, StructArrayResourceItem & o)
+	{
+	static unsigned long level = 0;	// Recursion level.
+	os << "StructArrayResourceItem (Level " << level++ << ") ["  << o.iStructItem->iLabel << "]  " << endl;
+	DataType counttype = o.iStructItem->iLenType;
+	if (counttype==0)
+		counttype = L_WORD;
+	unsigned long nitems = o.iArrayOfResourceItemArrays.Size();
+	os << "ArrayLength [" << gTypes.GetName(counttype) << "] " << nitems << endl;
+	if (nitems > 0)
+		{
+		os << "----------------------" << endl;
+		os << o.iArrayOfResourceItemArrays;
+		os << "----------------------" << endl;
+		}
+	level--;
+	return os;
+	}
+
+ostream & operator<< ( ostream & os, ResourceHeader & o)
+	{
+	os << "ResourceHeader          ";
+	os << o.iLabel << endl;
+	os << o.iRIA;
+	return os;
+	}
+
+ostream & operator<< ( ostream & os, ResourceItemArray & o)
+	{
+	os << "++ResourceItemArray" << endl;
+	if ( o.iLenType != 0)
+		{
+		os << "LenType: " << gTypes.GetName( o.iLenType) << "\t";
+		}
+	if ( o.Size() == 0)
+		return ( os << "<none>");
+	ResourceItemArrayIterator	next( o);
+	ResourceItem * p;
+	while ( ( p = next() ) != NULL)
+		p->StreamOut( os);
+	return os;
+	}
+
+ostream & operator<< ( ostream & os, ResourceItemArrayArray & o)
+	{
+	os << "--ResourceItemArrayArray" << endl;
+	if ( o.Size() == 0)
+		return ( os << "<none>");
+	ResourceItemArrayArrayIterator	next( o);
+	ResourceItemArray * p;
+	while ( ( p = next() ) != NULL)
+		os << * p;
+	return os;
+	}
+
+void StreamOutCompressingIfReducesSize(ResourceDataStream& aStream, const UTF16* aUncompressedUnicodeBuffer, int aUncompressedUnicodeLength)
+	{
+	const int uncompressedUnicodeSizeInBytes = aUncompressedUnicodeLength*2;
+
+	//
+	// Output buffer allocated to be one byte bigger than uncompressed input buffer.
+	// This is to allow for what appears to be the worst case where the string cannot be
+	// compressed at all.  In this case enough memory has to be allocated to contain
+	// the uncompressable string, plus the one-byte compression mode tag.
+	//
+	const int maximumOutputLengthInBytes = uncompressedUnicodeSizeInBytes;
+	unsigned char* const compressedUnicodeBuffer = new unsigned char[maximumOutputLengthInBytes];
+	assert(compressedUnicodeBuffer != NULL);
+
+	int compressedUnicodeSizeInBytes;
+	CompressUnicode(compressedUnicodeBuffer, compressedUnicodeSizeInBytes, maximumOutputLengthInBytes, aUncompressedUnicodeBuffer, aUncompressedUnicodeLength);
+
+	if (compressedUnicodeSizeInBytes < uncompressedUnicodeSizeInBytes)
+		{
+		aStream.StartOfCompressedUnicodeRun(uncompressedUnicodeSizeInBytes, (const unsigned char*)aUncompressedUnicodeBuffer);
+		aStream.StreamIn(compressedUnicodeBuffer, compressedUnicodeSizeInBytes);
+		aStream.EndOfCompressedUnicodeRun();
+		}
+	else if (uncompressedUnicodeSizeInBytes>0)
+		{
+		aStream.TwoByteAlignmentPoint();
+		aStream.StreamIn((const unsigned char*)aUncompressedUnicodeBuffer, uncompressedUnicodeSizeInBytes);
+		}
+
+	delete [] compressedUnicodeBuffer;
+	}
+
+// ResourceItem based RCBinaryStream functions
+// These are used to write the raw data as required in the final output file
+
+static void StreamOutSingleValue(
+	ResourceDataStream&	aStream,
+	const String &		aValue,
+	unsigned long		aLinkValue,
+	DataType 			aItemType,
+	const String *		aFileName,
+	int					aLineNumber
+	)
+	{
+	ErrorHandler::Register( aFileName, aLineNumber);	// Register in case conversion to number fails.
+
+
+
+	switch ( aItemType)
+		{
+
+        // 8-bit text
+
+		case L_TEXT8:
+            {	// Null terminator, no leading byte count.
+           		unsigned char * p = new unsigned char[ aValue.Length() + 1];
+				if ( aValue.Length() > 0)
+           			memcpy( p, aValue.GetAssertedNonEmptyBuffer(), aValue.Length() );
+           		* ( p + aValue.Length() ) = '\0';
+           		aStream.StreamIn(p, aValue.Length() + 1);
+           		delete [] p;
+            	break;
+            }
+		case L_LTEXT8:
+            {	// Leading byte count, no null terminator. (For zero length string a byte containing
+            	// zero is written out.
+				assert ( aValue.Length() <= 255 );
+           		unsigned char * p = new unsigned char[ aValue.Length() + 1];
+				if ( aValue.Length() > 0)
+           			memcpy( p + 1, aValue.GetAssertedNonEmptyBuffer(), aValue.Length() );
+           		*p = (unsigned char)(aValue.Length());
+           		aStream.StreamIn(p, aValue.Length() + 1);
+           		delete [] p;
+            	break;
+            }
+		case L_BUF8:	// Write just the characters from the string.
+			aStream.StreamIn((const unsigned char*)aValue.GetAssertedNonEmptyBuffer(), aValue.Length());
+			break;
+
+
+        // 16-bit text
+
+
+
+        case L_BUF16:   // write out unadorned 16-bit characters
+            {
+            int output_count;   // used as character count for binary output.
+
+            // reserve enough for worst case
+            output_count = aValue.Length();
+            UTF16 *output_buffer = new UTF16[output_count];
+
+            aValue.Export(output_buffer, output_count, SourceCharacterSet);
+
+			// write out the buffer as a stream of octets.
+			#if defined(__TOOLS2_WINDOWS__)
+			StreamOutCompressingIfReducesSize(aStream, (const unsigned short*)output_buffer, output_count);
+			#else
+			StreamOutCompressingIfReducesSize(aStream, output_buffer, output_count);
+			#endif
+
+            delete [] output_buffer;
+
+            break;
+            }
+
+
+
+        case L_TEXT16:  // write out a null-terminated string
+			// this has no support in BAFL
+            {
+            int output_count;   // used as character count for binary output.
+
+            // reserve enough for worst case + null terminator.
+            output_count = aValue.Length();
+            UTF16 *output_buffer = new UTF16[output_count +1];
+
+            aValue.Export(output_buffer, output_count, SourceCharacterSet);
+            output_buffer[output_count] = 0;
+            output_count +=1;
+
+            // write out the buffer as a stream of octets.
+			#if defined(__TOOLS2_WINDOWS__)
+			StreamOutCompressingIfReducesSize(aStream, (const unsigned short*)output_buffer, output_count);
+			#else
+			StreamOutCompressingIfReducesSize(aStream, output_buffer, output_count);
+			#endif			
+
+            delete [] output_buffer;
+
+            break;
+            }            
+
+
+        case L_LTEXT16:  // write out counted string.  The count is in
+                         // an octet, not a word.
+
+            {
+            int output_count;      // used as character count for binary output.
+            unsigned char lbcount; // To hold the leading byte count.
+
+            // reserve enough for worst case
+            output_count = aValue.Length();
+	// XXX I have commented the assert statement below out, because an LTEXT can't have length
+	// XXX bigger than 255, but sometimes this happens. A solution would be to throw an error
+	// XXX in structst.cpp, in the SimpleStructItem::SimpleStructItem() constructor.
+            UTF16 *output_buffer = new UTF16[output_count];
+
+            aValue.Export(output_buffer, output_count, SourceCharacterSet);
+
+            // write out the count.
+
+            lbcount = (unsigned char) output_count;
+            aStream.StreamIn(&lbcount,1);
+
+            // write out the buffer as a stream of octets.
+	    StreamOutCompressingIfReducesSize(aStream, output_buffer, output_count);	
+
+            delete [] output_buffer;
+
+            break;
+            }            
+
+
+
+
+		case L_BYTE:
+		case L_WORD:
+		case L_LONG:
+		case L_DOUBLE:
+			assert ( aValue.Length() > 0);
+			if(verbose) { MOFF; cout << "Converting " << aValue << " to number." << endl; MON;}
+			NumericValue( aValue, aItemType).StreamOut(aStream);
+			break;
+		case L_SRLINK:
+			NumericValue( aLinkValue, L_LONG).StreamOut(aStream);
+			break;
+		case L_LINK:
+		case L_LLINK:
+			{
+				if ( aValue.Length() > 0)
+				{
+					DataType dtype = ( aItemType == L_LINK) ? L_WORD : L_LONG;
+					if ( aValue.IsDecNatural() )	// If a resource id was specified explicitly e.g. -75 then output the value.
+						NumericValue(aValue, dtype).StreamOut(aStream);
+					else
+					{
+						// If FindId fails to find the link it will output an
+						// appropriate error and kill the program.
+						ErrorHandler::Register(aFileName, aLineNumber);
+						unsigned long id = pG->ResourceNameIds.FindId(aValue);
+						NumericValue(id, dtype).StreamOut(aStream);
+					}
+				}
+				break;
+			}
+		default:
+			{ 	MOFF; cout << "RCBinaryStream:Unknown type " << gTypes.GetName( aItemType) << endl; MON;}
+		}
+	}
+
+void SimpleResourceItem::StreamOut(ResourceDataStream& aStream) const
+	{
+	StreamOutSingleValue(aStream, iValue, iLinkValue, iStructItem->iItemType, iFileName, iLineNumber);
+	}
+
+void ArrayResourceItem::StreamOut(ResourceDataStream& aStream) const
+	{
+	NumericValue * itemcount = NULL;
+	if(iStructItem->iSize.Length() == 0)	// STRUCT item says [] i.e. no size specified.
+		{
+		if (iStructItem->iLenType == 0)	// No LEN declaration so default to WORD.
+			itemcount = new NumericValue( L_WORD);
+		else
+			itemcount = new NumericValue( iStructItem->iLenType); // Use specified type.
+
+		* itemcount = iValues.Size();
+		itemcount->StreamOut(aStream);
+		
+		delete itemcount;
+		}
+	if ( iValues.Size() == 0)
+		return;
+	StringArrayIterator next( iValues);
+	String * p;
+	while ( ( p = next() ) != NULL)
+		{
+		assert( iStructItem->iItemType != L_SRLINK);	// Can't handle arrays of SRlinks.
+		StreamOutSingleValue(aStream, *p, 0, iStructItem->iItemType, iFileName, iLineNumber);
+		}
+	}
+
+void StructTypeResourceItem::StreamOut(ResourceDataStream& aStream) const
+	{
+	iResourceItems.StreamOut(aStream);
+	}
+
+void StructArrayResourceItem::StreamOut(ResourceDataStream& aStream) const
+	{
+	NumericValue * itemcount = NULL;
+	if(iStructItem->iLenType == 0)	// No LEN declaration so default to WORD.
+		itemcount = new NumericValue( L_WORD);
+	else
+		itemcount = new NumericValue( iStructItem->iLenType); // Use specified type.
+	* itemcount = iArrayOfResourceItemArrays.Size();
+	itemcount->StreamOut(aStream);
+	delete itemcount;
+	if(iArrayOfResourceItemArrays.Size() == 0)
+		return;
+	iArrayOfResourceItemArrays.StreamOut(aStream);
+	}
+
+void ResourceItemArray::StreamOut(ResourceDataStream& aStream) const
+	{
+	if (Size() == 0)
+		return;
+	static unsigned int RecursionLevel = 0; // Top level should not have resource size output.
+	const bool outputSize=((iLenType != 0) && (RecursionLevel > 0));
+	if (outputSize)
+		{
+		aStream.StartOfBlockWithSizePrefix(iLenType);
+		}
+	RecursionLevel++;
+	ResourceItemArrayIterator next(*this);
+	ResourceItem * p;
+	while ( ( p = next() ) != NULL)
+		{
+		p->StreamOut(aStream);
+		}
+	RecursionLevel--;
+	if (outputSize)
+		{
+		aStream.EndOfBlockWithSizePrefix();
+		}
+	}
+
+void ResourceItemArrayArray::StreamOut(ResourceDataStream& aStream) const
+	{
+	if (Size() == 0)
+		return;
+	ResourceItemArrayArrayIterator next(*this);
+	ResourceItemArray * p;
+	while ( ( p = next() ) != NULL)
+		p->StreamOut(aStream);
+	}