--- /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);
+ }