/*
* 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:
*
*/
#ifndef __RCOFSTRM_H__
#define __RCOFSTRM_H__
#if defined(__VC32__) && !defined(__MSVCDOTNET__)
#pragma warning( disable : 4710 ) // function not inlined
#endif
#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
#include <fstream>
using std::ofstream;
#else //!__MSVCDOTNET__
#include <fstream.h>
#endif //__MSVCDOTNET__
#include "ASTRING.H"
#include "NUMVAL.H"
#include "ARRAY.H"
class RCBinaryStream
{
public:
RCBinaryStream();
~RCBinaryStream();
void OpenForAppend(const String& aFileName);
int IsOpen();
RCBinaryStream& operator<<(char aChar);
RCBinaryStream& operator<<(char* aCharPtr);
static int SizeOfCompressedInteger(unsigned int aInteger);
void WriteCompressedInteger(unsigned int aInteger);
void Write(const unsigned char* aCharPtr, unsigned long aCount);
unsigned long GetPosition();
void SetPosition(unsigned long NewPosition);
private:
ofstream iOs;
};
class ResourceDataStream // this class knows about resources that contain compressed Unicode - i.e. that each run of alternating compressed-Unicode and other-stuff needs to be preceded by a 1-2 byte run-length
{
public:
ResourceDataStream();
~ResourceDataStream();
void StartOfBlockWithSizePrefix(DataType aDataTypeOfSizePrefix); // StartOfBlockWithSizePrefix/EndOfBlockWithSizePrefix blocks can be nested
void EndOfBlockWithSizePrefix();
void StartOfCompressedUnicodeRun(int aUncompressedUnicodeSizeInBytes, const unsigned char* aUncompressedUnicodeBuffer); // StartOfCompressedUnicodeRun/EndOfCompressedUnicodeRun runs *cannot* be nested
void EndOfCompressedUnicodeRun();
void TwoByteAlignmentPoint();
void EnquireStreamPositionWhenKnown(unsigned long& aStreamPosition);
void StreamIn(const unsigned char* aBuffer, int aNumberOfBytes);
void MakePlaceHolder(int aNumberOfBytes);
bool StreamOutReturningWhetherContainsCompressedUnicode(RCBinaryStream& aStream, int& aSizeWhenUncompressed);
void Dump(const char* aDumpFile) const;
private:
enum MarkType
{
EMarkType_StartOfBlockWithSizePrefix, // uses iOtherData to store the address of the NumericValue of the size-prefix
EMarkType_EndOfBlockWithSizePrefix,
EMarkType_StartOfCompressedUnicodeRun, // uses iOtherData to store a BinaryBuffer which contains the uncompressed Unicode - a EMarkType_StartOfCompressedUnicodeRun mark is always followed in ResourceDataStream's iArrayOfMarks by a EMarkType_EndOfCompressedUnicodeRun
EMarkType_EndOfCompressedUnicodeRun, // uses iOtherData to store the combined size of the run taking into account any extra bytes caused by other marks, e.g. a padding byte caused by a EMarkType_TwoByteAlignmentPoint
EMarkType_TwoByteAlignmentPoint, // uses iOtherData to store whether a padding byte is required or not (iOtherData is set to non-zero if it is and zero if it isn't)
EMarkType_EnquireStreamPositionWhenKnown // uses iOtherData to store the address of the unsigned long to write the stream-position to
};
class BinaryBuffer
{
public:
static BinaryBuffer* New(int aNumberOfBytes, const unsigned char* aBuffer);
void Destroy();
inline int NumberOfBytes() const {return iNumberOfBytes;}
inline const unsigned char* Buffer() const {return iBuffer;}
private:
BinaryBuffer(); // defined (as private) but not declared to prevent anyone instantiating this class apart from the static New function
private:
int iNumberOfBytes;
unsigned char iBuffer[1];
};
class Mark : public ArrayItem
{
public:
inline Mark(int aBufferPosition, MarkType aMarkType, unsigned int aOtherData) :iBufferPosition(aBufferPosition), iMarkType(aMarkType), iOtherData(aOtherData) {}
public:
int iBufferPosition;
MarkType iMarkType;
unsigned int iOtherData;
};
class ArrayOfMarks : public Array
{
public:
inline ArrayOfMarks() {}
inline void AppendMark(int aBufferPosition, MarkType aMarkType, unsigned int aOtherData=0xbebebebe) {Add(new Mark(aBufferPosition, aMarkType, aOtherData));}
inline void InsertMark(int aIndex, int aBufferPosition, MarkType aMarkType, unsigned int aOtherData=0xbebebebe) {Add(aIndex, new Mark(aBufferPosition, aMarkType, aOtherData));}
inline void RemoveMark(int aIndex) {Discard(aIndex);}
inline Mark& MarkAt(int aIndex) const {return *(Mark*)(*this)[aIndex];}
};
private:
void EnsureEnoughSpareBytes(int aNumberOfBytes);
int NumberOfBytesToNextMark(int aMarkIndex) const;
void ConvertCompressedRunToUncompressed(int aIndexOfStartOfCompressedUnicodeRun); // aIndexOfStartOfCompressedUnicodeRun is an index into iArrayOfMarks
private:
unsigned char* iBuffer;
int iNumberOfBytesAllocated;
int iNumberOfBytesUsed;
ArrayOfMarks iArrayOfMarks;
bool iContainsCompressedUnicode;
};
#endif