sl@0
|
1 |
// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
2 |
// All rights reserved.
|
sl@0
|
3 |
// This component and the accompanying materials are made available
|
sl@0
|
4 |
// under the terms of "Eclipse Public License v1.0"
|
sl@0
|
5 |
// which accompanies this distribution, and is available
|
sl@0
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
7 |
//
|
sl@0
|
8 |
// Initial Contributors:
|
sl@0
|
9 |
// Nokia Corporation - initial contribution.
|
sl@0
|
10 |
//
|
sl@0
|
11 |
// Contributors:
|
sl@0
|
12 |
//
|
sl@0
|
13 |
// Description:
|
sl@0
|
14 |
//
|
sl@0
|
15 |
|
sl@0
|
16 |
#include <s32ucmp.h>
|
sl@0
|
17 |
#include "BADICTIONARYCOMPRESSION.H"
|
sl@0
|
18 |
#include "BaRscImpl.h"
|
sl@0
|
19 |
#include "BaAssert.h"
|
sl@0
|
20 |
#include "BaCompileAssert.h"
|
sl@0
|
21 |
|
sl@0
|
22 |
/** TCleanupItem function.
|
sl@0
|
23 |
@internalComponent
|
sl@0
|
24 |
@param aFile Pointer to the RFile instance which has to be closed. */
|
sl@0
|
25 |
LOCAL_C void CloseAndDeleteFile(TAny* aFile)
|
sl@0
|
26 |
{
|
sl@0
|
27 |
RFile* const file=STATIC_CAST(RFile*,aFile);
|
sl@0
|
28 |
if (file!=NULL)
|
sl@0
|
29 |
{
|
sl@0
|
30 |
file->Close();
|
sl@0
|
31 |
delete file;
|
sl@0
|
32 |
}
|
sl@0
|
33 |
}
|
sl@0
|
34 |
|
sl@0
|
35 |
/** TCleanupItem function.
|
sl@0
|
36 |
@internalComponent
|
sl@0
|
37 |
@param aArrayOfDictionaryCompressionBitStreams Pointer to an array (RArray) of
|
sl@0
|
38 |
RDictionaryCompressionBitStream objects which have to be closed. */
|
sl@0
|
39 |
LOCAL_C void CloseArrayOfDictionaryCompressionBitStreams(TAny* aArray)
|
sl@0
|
40 |
{
|
sl@0
|
41 |
typedef RArray<RDictionaryCompressionBitStream> RDictComprBitStream;
|
sl@0
|
42 |
RDictComprBitStream* array = static_cast <RDictComprBitStream*> (aArray);
|
sl@0
|
43 |
for (TInt i=array->Count()-1;i>=0;--i)
|
sl@0
|
44 |
{
|
sl@0
|
45 |
array[i].Close();
|
sl@0
|
46 |
}
|
sl@0
|
47 |
array->Close();
|
sl@0
|
48 |
}
|
sl@0
|
49 |
|
sl@0
|
50 |
/** @internalComponent */
|
sl@0
|
51 |
struct SDictionaryCompressionData
|
sl@0
|
52 |
{
|
sl@0
|
53 |
inline SDictionaryCompressionData() :
|
sl@0
|
54 |
iStartOfDictionaryData(0),
|
sl@0
|
55 |
iStartOfDictionaryIndex(0),
|
sl@0
|
56 |
iNumberOfDictionaryEntries(0),
|
sl@0
|
57 |
iStartOfResourceData(0),
|
sl@0
|
58 |
iStartOfResourceIndex(0),
|
sl@0
|
59 |
iNumberOfBitsUsedForDictionaryTokens(0),
|
sl@0
|
60 |
iCachedDictionaryIndex(0),
|
sl@0
|
61 |
iCachedResourceBuffer(0)// = NULL;
|
sl@0
|
62 |
{
|
sl@0
|
63 |
}
|
sl@0
|
64 |
TInt iStartOfDictionaryData;
|
sl@0
|
65 |
TInt iStartOfDictionaryIndex;
|
sl@0
|
66 |
TInt iNumberOfDictionaryEntries;
|
sl@0
|
67 |
TInt iStartOfResourceData;
|
sl@0
|
68 |
TInt iStartOfResourceIndex;
|
sl@0
|
69 |
TInt iNumberOfBitsUsedForDictionaryTokens;
|
sl@0
|
70 |
TUint16* iCachedDictionaryIndex;
|
sl@0
|
71 |
TUint8* iCachedResourceBuffer;
|
sl@0
|
72 |
|
sl@0
|
73 |
};
|
sl@0
|
74 |
|
sl@0
|
75 |
/** @internalComponent */
|
sl@0
|
76 |
class RResourceFileImpl::TExtra
|
sl@0
|
77 |
{
|
sl@0
|
78 |
public:
|
sl@0
|
79 |
TExtra(const TBaAssert& aAssertObj);
|
sl@0
|
80 |
~TExtra();
|
sl@0
|
81 |
TBool ContainsCompressedUnicodeL(TInt aRscIdx, TBool aFirstRscIsGen) const;
|
sl@0
|
82 |
private:
|
sl@0
|
83 |
TExtra(const TExtra&);//prevent default copy constructor
|
sl@0
|
84 |
TExtra& operator=(const TExtra&);//prevent default "=" operator
|
sl@0
|
85 |
public:
|
sl@0
|
86 |
TUidType iUidType;
|
sl@0
|
87 |
HBufC8* iBitArrayOfResourcesContainingCompressedUnicode; // an array of bits, one for each resource in the resource file
|
sl@0
|
88 |
SDictionaryCompressionData iDictionaryCompressionData;
|
sl@0
|
89 |
TInt iFileOffset; // offset of RSC chunk in new AIF file format
|
sl@0
|
90 |
TBaAssert iAssertObj;
|
sl@0
|
91 |
TInt iFileSize; // RSC chunc size - in new AIF file format, file size otherwise
|
sl@0
|
92 |
};
|
sl@0
|
93 |
|
sl@0
|
94 |
/** @internalComponent
|
sl@0
|
95 |
@param aAssertObj Object which will determine RResourceFileImpl::TExtra
|
sl@0
|
96 |
instance's behaviour if something goes wrong - depending on aAssertObj state
|
sl@0
|
97 |
RResourceFileImpl::TExtra methods will leave or panic. */
|
sl@0
|
98 |
RResourceFileImpl::TExtra::TExtra(const TBaAssert& aAssertObj) :
|
sl@0
|
99 |
iUidType(),
|
sl@0
|
100 |
iBitArrayOfResourcesContainingCompressedUnicode(NULL),
|
sl@0
|
101 |
iDictionaryCompressionData(),
|
sl@0
|
102 |
iFileOffset(0),
|
sl@0
|
103 |
iAssertObj(aAssertObj),
|
sl@0
|
104 |
iFileSize(0)
|
sl@0
|
105 |
{
|
sl@0
|
106 |
}
|
sl@0
|
107 |
|
sl@0
|
108 |
/** @internalComponent */
|
sl@0
|
109 |
RResourceFileImpl::TExtra::~TExtra()
|
sl@0
|
110 |
{
|
sl@0
|
111 |
delete iBitArrayOfResourcesContainingCompressedUnicode;
|
sl@0
|
112 |
}
|
sl@0
|
113 |
|
sl@0
|
114 |
/** @internalComponent */
|
sl@0
|
115 |
TBool RResourceFileImpl::TExtra::ContainsCompressedUnicodeL(TInt aRscIdx, TBool aFirstRscIsGen) const
|
sl@0
|
116 |
{
|
sl@0
|
117 |
if (aFirstRscIsGen)
|
sl@0
|
118 |
{
|
sl@0
|
119 |
// dictionary-compressed resource files can have an automatically generated
|
sl@0
|
120 |
//resource which is the bit-array of resources containing compressed Unicode
|
sl@0
|
121 |
//(this automatically generated resource does not have a corresponding bit
|
sl@0
|
122 |
//for itself in the bit-array as it would be self-referring...)
|
sl@0
|
123 |
--aRscIdx;
|
sl@0
|
124 |
if (aRscIdx<0)
|
sl@0
|
125 |
{
|
sl@0
|
126 |
//aRscIdx is referring to the automatically generated resource
|
sl@0
|
127 |
//(which is the bit-array of resources containing compressed Unicode)
|
sl@0
|
128 |
return EFalse;
|
sl@0
|
129 |
}
|
sl@0
|
130 |
}
|
sl@0
|
131 |
iAssertObj.AssertDebL(aRscIdx>=0, EBafPanicNegativeResourceIndex1);
|
sl@0
|
132 |
if (iBitArrayOfResourcesContainingCompressedUnicode==NULL)
|
sl@0
|
133 |
{
|
sl@0
|
134 |
return EFalse;
|
sl@0
|
135 |
}
|
sl@0
|
136 |
TInt index = aRscIdx / 8;
|
sl@0
|
137 |
iAssertObj.AssertDebL(index < iBitArrayOfResourcesContainingCompressedUnicode->Length(), EBafPanicBadIndex);
|
sl@0
|
138 |
return (*iBitArrayOfResourcesContainingCompressedUnicode)[index]&(1<<(aRscIdx%8));
|
sl@0
|
139 |
}
|
sl@0
|
140 |
|
sl@0
|
141 |
/** @internalComponent */
|
sl@0
|
142 |
RResourceFileImpl::RResourceFileImpl() :
|
sl@0
|
143 |
iFile(NULL),
|
sl@0
|
144 |
iSizeOfLargestResourceWhenCompletelyUncompressed(0),
|
sl@0
|
145 |
iIndex(NULL),
|
sl@0
|
146 |
iOffset(0),
|
sl@0
|
147 |
iExtra(NULL),
|
sl@0
|
148 |
iFlagsAndNumberOfResources(0)
|
sl@0
|
149 |
{
|
sl@0
|
150 |
//Fixed class size - because of the BC reasons.
|
sl@0
|
151 |
//RResourceFileImpl size must be the same as RResourceFile size.
|
sl@0
|
152 |
enum
|
sl@0
|
153 |
{
|
sl@0
|
154 |
KRscFileImplSize = 24
|
sl@0
|
155 |
};
|
sl@0
|
156 |
COMPILE_TIME_ASSERT(sizeof(RResourceFileImpl)==KRscFileImplSize);
|
sl@0
|
157 |
// MSVC++ & GCCE can't handle this template instantiation
|
sl@0
|
158 |
#if !defined(__VC32__) && !defined(__GCCE__) && !defined(__X86GCC__)
|
sl@0
|
159 |
//Fixed "iOffset" position - because of the BC reasons.
|
sl@0
|
160 |
COMPILE_TIME_ASSERT(_FOFF(RResourceFileImpl, iOffset)==12);
|
sl@0
|
161 |
#endif
|
sl@0
|
162 |
}
|
sl@0
|
163 |
|
sl@0
|
164 |
/** Closes the resource file reader.
|
sl@0
|
165 |
This function is called after finishing reading all resources.
|
sl@0
|
166 |
@internalComponent */
|
sl@0
|
167 |
void RResourceFileImpl::Close()
|
sl@0
|
168 |
{
|
sl@0
|
169 |
if ((iFile!=NULL) && ((iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsRomFile))==0
|
sl@0
|
170 |
&& (iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsBufferRscFile))==0))
|
sl@0
|
171 |
{
|
sl@0
|
172 |
RFile* const file=STATIC_CAST(RFile*,iFile);
|
sl@0
|
173 |
file->Close();
|
sl@0
|
174 |
delete file;
|
sl@0
|
175 |
}
|
sl@0
|
176 |
//Here it indicates that it is reading from a HBufC8 rsc file buffer so we need to free the heap here
|
sl@0
|
177 |
if ((iFile!=NULL) && ((iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsBufferRscFile))!=0))
|
sl@0
|
178 |
{
|
sl@0
|
179 |
HBufC8* buffer=STATIC_CAST(HBufC8*,iFile);
|
sl@0
|
180 |
delete buffer;
|
sl@0
|
181 |
}
|
sl@0
|
182 |
iFile=NULL;
|
sl@0
|
183 |
iSizeOfLargestResourceWhenCompletelyUncompressed=0;
|
sl@0
|
184 |
delete iIndex;
|
sl@0
|
185 |
iIndex=NULL;
|
sl@0
|
186 |
if (iExtra)
|
sl@0
|
187 |
{
|
sl@0
|
188 |
delete [] iExtra->iDictionaryCompressionData.iCachedResourceBuffer;
|
sl@0
|
189 |
iExtra->iDictionaryCompressionData.iCachedResourceBuffer = NULL;
|
sl@0
|
190 |
delete [] iExtra->iDictionaryCompressionData.iCachedDictionaryIndex;
|
sl@0
|
191 |
iExtra->iDictionaryCompressionData.iCachedDictionaryIndex = 0;
|
sl@0
|
192 |
delete iExtra;
|
sl@0
|
193 |
iExtra=NULL;
|
sl@0
|
194 |
}
|
sl@0
|
195 |
iFlagsAndNumberOfResources=0;
|
sl@0
|
196 |
iOffset=0;
|
sl@0
|
197 |
}
|
sl@0
|
198 |
|
sl@0
|
199 |
/** Opens the resource file reader.
|
sl@0
|
200 |
The resource file reader must be opened before reading resources or
|
sl@0
|
201 |
checking the signature of the resource file. This function initially
|
sl@0
|
202 |
closes the resource-file object if it is currently open. If a leave
|
sl@0
|
203 |
occurs during the function, the object is reverted to its closed state.
|
sl@0
|
204 |
@internalComponent
|
sl@0
|
205 |
@param aFs Handle to a file server session.
|
sl@0
|
206 |
@param aName File to open as a resource file.
|
sl@0
|
207 |
@param aAssert Object which will be used to determine panic/leave behaviour
|
sl@0
|
208 |
of the "L" methods.
|
sl@0
|
209 |
@param aFileOffset The resource file section offset from the beginning of the file.
|
sl@0
|
210 |
@param aFileSize The resource file section size.
|
sl@0
|
211 |
@panic Some BAFL panic codes.
|
sl@0
|
212 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
213 |
The method could panic or leave depending on the state of
|
sl@0
|
214 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
215 |
void RResourceFileImpl::OpenL(RFs &aFs, const TDesC &aName, const TBaAssert& aAssert,
|
sl@0
|
216 |
TUint aFileOffset/* = 0 */, TInt aFileSize/* = 0 */)
|
sl@0
|
217 |
{
|
sl@0
|
218 |
Close();
|
sl@0
|
219 |
CleanupClosePushL(*this);
|
sl@0
|
220 |
RFile* const file=new(ELeave) RFile;
|
sl@0
|
221 |
CleanupStack::PushL(TCleanupItem(CloseAndDeleteFile,file));
|
sl@0
|
222 |
User::LeaveIfError(file->Open(aFs, aName, EFileStream | EFileRead | EFileShareReadersOnly));
|
sl@0
|
223 |
iExtra=new (ELeave) TExtra(aAssert);
|
sl@0
|
224 |
const TBaAssert& assert_obj = iExtra->iAssertObj;
|
sl@0
|
225 |
iExtra->iFileOffset = aFileOffset;
|
sl@0
|
226 |
TInt fileSize = 0;
|
sl@0
|
227 |
if (aFileSize)
|
sl@0
|
228 |
{
|
sl@0
|
229 |
// With new format AIF, the RSC file is part of a larger file, so we need to set the
|
sl@0
|
230 |
// size of the RSC file here.
|
sl@0
|
231 |
fileSize = aFileSize;
|
sl@0
|
232 |
assert_obj.AssertDebL(fileSize > TInt(aFileOffset), EBafPanicBadOpenArg);
|
sl@0
|
233 |
}
|
sl@0
|
234 |
else
|
sl@0
|
235 |
{
|
sl@0
|
236 |
User::LeaveIfError(file->Size(fileSize));
|
sl@0
|
237 |
assert_obj.AssertDebL(fileSize > 0, EBafPanicFileSize2);
|
sl@0
|
238 |
}
|
sl@0
|
239 |
TUint8* romAddress=NULL;
|
sl@0
|
240 |
TInt seekRc(KErrNotSupported);
|
sl@0
|
241 |
|
sl@0
|
242 |
// ESeekAddress in emulator will just get -5 and NULL romAddress.
|
sl@0
|
243 |
// On emulator there is also undesirable effect that after the call the ROM
|
sl@0
|
244 |
// resource file cannot be deleted while emulator is running. Seems base has
|
sl@0
|
245 |
// some kind of handle open on the rsc. One licensee has a use case to
|
sl@0
|
246 |
// re-compile resources while emulator is running. Hence Seek only in hw.
|
sl@0
|
247 |
#ifndef __WINSCW__
|
sl@0
|
248 |
seekRc = file->Seek(ESeekAddress,REINTERPRET_CAST(TInt&,romAddress));
|
sl@0
|
249 |
#endif
|
sl@0
|
250 |
|
sl@0
|
251 |
if (romAddress==NULL || seekRc !=KErrNone)
|
sl@0
|
252 |
{
|
sl@0
|
253 |
iFile=file;
|
sl@0
|
254 |
// At the 1st line of this function we call Close() which sets
|
sl@0
|
255 |
// iFlagsAndNUmberOfResources to zero. Nothing between Close() and here changes
|
sl@0
|
256 |
// iFlagsAndNumberOfResources. So no need to assert EFlagIsRomFile is cleared.
|
sl@0
|
257 |
// assert_obj.AssertDebL((iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsRomFile))==0,
|
sl@0
|
258 |
// EBafPanicBadInitialization1);
|
sl@0
|
259 |
CleanupStack::Pop(file);
|
sl@0
|
260 |
}
|
sl@0
|
261 |
else
|
sl@0
|
262 |
{
|
sl@0
|
263 |
iFile=CONST_CAST(TUint8*,romAddress);
|
sl@0
|
264 |
iFlagsAndNumberOfResources |= static_cast<TUint>(EFlagIsRomFile);
|
sl@0
|
265 |
CleanupStack::PopAndDestroy(file);
|
sl@0
|
266 |
}
|
sl@0
|
267 |
iExtra->iFileSize = fileSize;
|
sl@0
|
268 |
ReadHeaderAndResourceIndexL();
|
sl@0
|
269 |
CleanupStack::Pop(this);
|
sl@0
|
270 |
}
|
sl@0
|
271 |
|
sl@0
|
272 |
/** Opens the resource file reader.
|
sl@0
|
273 |
The resource file reader must be opened before reading resources or
|
sl@0
|
274 |
checking the signature of the resource file. This function initially
|
sl@0
|
275 |
closes the resource-file object if it is currently open. If a leave
|
sl@0
|
276 |
occurs during the function, the object is reverted to its closed state.
|
sl@0
|
277 |
@internalComponent
|
sl@0
|
278 |
@param aRscArchive buffer containing a full rsc file
|
sl@0
|
279 |
@param aAssert Object which will be used to determine panic/leave behaviour
|
sl@0
|
280 |
of the "L" methods.
|
sl@0
|
281 |
@panic Some BAFL panic codes.
|
sl@0
|
282 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
283 |
The method could panic or leave depending on the state of
|
sl@0
|
284 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
285 |
|
sl@0
|
286 |
void RResourceFileImpl::OpenL(const TDesC8& aRscArchive,const TBaAssert& aAssert)
|
sl@0
|
287 |
{
|
sl@0
|
288 |
Close();
|
sl@0
|
289 |
CleanupClosePushL(*this);
|
sl@0
|
290 |
|
sl@0
|
291 |
iExtra=new (ELeave) TExtra(aAssert);
|
sl@0
|
292 |
|
sl@0
|
293 |
//Since we are getting the entire buffer of the rsc file, we can treat
|
sl@0
|
294 |
//this equivalent to a ROM rsc file by pointing the iFile to
|
sl@0
|
295 |
//the start of the aRscArchive. We can depend directly on existing ReadL
|
sl@0
|
296 |
//to retrive the bytes directly from memory. No file open is required
|
sl@0
|
297 |
//and the handling of the rest of the rsc file is an exact copy of the
|
sl@0
|
298 |
//previous OpenL().A good way to reduce ROM size is to split the reading
|
sl@0
|
299 |
//part of the resource file into one separate function.//TODO
|
sl@0
|
300 |
//We also dont care about any fileOffset as the aRscArchive contains only
|
sl@0
|
301 |
//the buffer for one entire rsc file.
|
sl@0
|
302 |
//Get the length of the rsc file
|
sl@0
|
303 |
TInt fileSize=aRscArchive.Length();
|
sl@0
|
304 |
//iFile=STATIC_CAST(TAny*,(aRscArchive.AllocL())->Des()).Ptr());
|
sl@0
|
305 |
iFile = aRscArchive.AllocL();
|
sl@0
|
306 |
iExtra->iFileSize=fileSize;
|
sl@0
|
307 |
iFlagsAndNumberOfResources |= static_cast<TUint>(EFlagIsBufferRscFile);
|
sl@0
|
308 |
|
sl@0
|
309 |
ReadHeaderAndResourceIndexL();
|
sl@0
|
310 |
CleanupStack::Pop(this);
|
sl@0
|
311 |
}
|
sl@0
|
312 |
|
sl@0
|
313 |
/**
|
sl@0
|
314 |
Retrieve the UID tuple of the opened resource file.
|
sl@0
|
315 |
|
sl@0
|
316 |
@internalComponent
|
sl@0
|
317 |
@pre OpenL() has been called successfully.
|
sl@0
|
318 |
@return The UIDs of the loaded resource file.
|
sl@0
|
319 |
@panic BAFL 36 - data members are not initialized(probably - OpenL() hasn't been called). */
|
sl@0
|
320 |
TUidType RResourceFileImpl::UidType() const
|
sl@0
|
321 |
{
|
sl@0
|
322 |
__ASSERT_ALWAYS(iExtra!=NULL,Panic(EBafPanicNotOpened));
|
sl@0
|
323 |
return iExtra->iUidType;
|
sl@0
|
324 |
}
|
sl@0
|
325 |
|
sl@0
|
326 |
/** Reads a resource specified by resource id into the specified descriptor.
|
sl@0
|
327 |
The descriptor must be long enough to contain the entire resource. The
|
sl@0
|
328 |
search for the resource uses the following algorithm: A resource id in
|
sl@0
|
329 |
the range 1 to 4095 is looked up in this resource file. The function
|
sl@0
|
330 |
leaves if there is no matching resource. If the resource id is greater
|
sl@0
|
331 |
than 4095, then the most significant 20 bits of the resource id is
|
sl@0
|
332 |
treated as an offset and the least significant 12 bits is treated as
|
sl@0
|
333 |
the real resource id. If the offset matches the offset value defined
|
sl@0
|
334 |
for this file, then the resource is looked up in this resource file
|
sl@0
|
335 |
using the real resource id (i.e. the least significant 12 bits). If
|
sl@0
|
336 |
the offset does not match, then the function leaves. Note, do not call
|
sl@0
|
337 |
this function until a call to ConfirmSignatureL() has
|
sl@0
|
338 |
completed successfully.
|
sl@0
|
339 |
@internalComponent
|
sl@0
|
340 |
@pre OpenL() is called.
|
sl@0
|
341 |
@param aDes On return, contains the resource that has been read.
|
sl@0
|
342 |
The function leaves if the descriptor is not long
|
sl@0
|
343 |
enough to contain the entire resource.
|
sl@0
|
344 |
@param aResourceId The numeric id of the resource to be read. The
|
sl@0
|
345 |
function leaves if this resource id is not in this resource file.
|
sl@0
|
346 |
@see ConfirmSignatureL()
|
sl@0
|
347 |
@panic Some BAFL panic codes, if the file is corrupted.
|
sl@0
|
348 |
@leave KErrCorrupt The file is corrupted. Some other error codes
|
sl@0
|
349 |
are possible too.
|
sl@0
|
350 |
The method could panic or leave depending on the state of
|
sl@0
|
351 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
352 |
void RResourceFileImpl::ReadL(TDes8 &aDes,TInt aResourceId) const
|
sl@0
|
353 |
{
|
sl@0
|
354 |
HBufC8* const resource=AllocReadLC(aResourceId);
|
sl@0
|
355 |
aDes=*resource;
|
sl@0
|
356 |
CleanupStack::PopAndDestroy(resource);
|
sl@0
|
357 |
}
|
sl@0
|
358 |
|
sl@0
|
359 |
/** Reads a resource into a heap descriptor, returns a pointer to that
|
sl@0
|
360 |
descriptor and pushes the pointer onto the cleanup stack.
|
sl@0
|
361 |
|
sl@0
|
362 |
A heap descriptor of appropriate length is allocated for the resource.
|
sl@0
|
363 |
Ownership of the heap descriptor passes to the caller who must destroy
|
sl@0
|
364 |
it and pop its pointer off the cleanup stack when it is no longer
|
sl@0
|
365 |
needed.The search for the resource uses the following algorithm:A
|
sl@0
|
366 |
resource id in the range 1 to 4095 is looked up in this resource file.
|
sl@0
|
367 |
The function leaves if there is no matching resource.If the resource
|
sl@0
|
368 |
id is greater than 4095, then the most significant 20 bits of the
|
sl@0
|
369 |
resource id is treated as an offset and the least significant 12 bits
|
sl@0
|
370 |
is treated as the real resource id. If the offset matches the offset
|
sl@0
|
371 |
value defined for this file, then the resource is looked up in this
|
sl@0
|
372 |
resource file using the real resource id (i.e. the least significant
|
sl@0
|
373 |
12 bits). If the offset does not match, then the function leaves.Note,
|
sl@0
|
374 |
do not call this function until a call to
|
sl@0
|
375 |
ConfirmSignatureL() has completed successfully.
|
sl@0
|
376 |
|
sl@0
|
377 |
@internalComponent
|
sl@0
|
378 |
@pre OpenL() is called.
|
sl@0
|
379 |
@param aResourceId The numeric id of the resource to be read.
|
sl@0
|
380 |
@return Pointer to a heap descriptor containing the resource.
|
sl@0
|
381 |
@see ConfirmSignatureL()
|
sl@0
|
382 |
@panic Some BAFL panic codes, if the file is corrupted.
|
sl@0
|
383 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
384 |
@leave KErrNotFound There is no resource with aResourceId in the file.
|
sl@0
|
385 |
Some other error codes are possible too.
|
sl@0
|
386 |
The method could panic or leave depending on the state of
|
sl@0
|
387 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
388 |
HBufC8* RResourceFileImpl::AllocReadLC(TInt aResourceId) const
|
sl@0
|
389 |
{
|
sl@0
|
390 |
if (!OwnsResourceIdL(aResourceId))
|
sl@0
|
391 |
{
|
sl@0
|
392 |
User::Leave(KErrNotFound);
|
sl@0
|
393 |
}
|
sl@0
|
394 |
const TBaAssert& assert_obj = iExtra->iAssertObj;
|
sl@0
|
395 |
//"-1" because the first resource has ID 0x*****001 (not 0x*****000)
|
sl@0
|
396 |
TInt resourceIndex=(aResourceId & EIdBits)-1;
|
sl@0
|
397 |
if (iFlagsAndNumberOfResources & EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource)
|
sl@0
|
398 |
{
|
sl@0
|
399 |
assert_obj.AssertDebL(iFlagsAndNumberOfResources & EFlagDictionaryCompressed,
|
sl@0
|
400 |
EBafPanicBadFlags1);
|
sl@0
|
401 |
assert_obj.AssertDebL(iFlagsAndNumberOfResources & EFlagThirdUidIsOffset,
|
sl@0
|
402 |
EBafPanicBadFlags2);
|
sl@0
|
403 |
if (resourceIndex>0)
|
sl@0
|
404 |
{
|
sl@0
|
405 |
--resourceIndex;
|
sl@0
|
406 |
}
|
sl@0
|
407 |
else
|
sl@0
|
408 |
{
|
sl@0
|
409 |
assert_obj.AssertDebL(resourceIndex==0, EBafPanicNegativeResourceIndex2);
|
sl@0
|
410 |
HBufC8* const resourceDataFor_RSS_SIGNATURE=HBufC8::NewMaxLC(8);
|
sl@0
|
411 |
TUint* wordPointer=REINTERPRET_CAST(TUint*,CONST_CAST(
|
sl@0
|
412 |
TUint8*,resourceDataFor_RSS_SIGNATURE->Ptr()));
|
sl@0
|
413 |
wordPointer[0]=4;
|
sl@0
|
414 |
wordPointer[1]=((iExtra->iUidType[2].iUid << 12) | 1);
|
sl@0
|
415 |
return resourceDataFor_RSS_SIGNATURE;
|
sl@0
|
416 |
}
|
sl@0
|
417 |
}
|
sl@0
|
418 |
const TBool firstResourceIsGenerated=
|
sl@0
|
419 |
(iFlagsAndNumberOfResources &
|
sl@0
|
420 |
EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode);
|
sl@0
|
421 |
if (firstResourceIsGenerated)
|
sl@0
|
422 |
{
|
sl@0
|
423 |
assert_obj.AssertDebL(iFlagsAndNumberOfResources &
|
sl@0
|
424 |
EFlagDictionaryCompressed, EBafPanicBadFlags6);
|
sl@0
|
425 |
//dictionary-compressed resource files can have an automatically generated
|
sl@0
|
426 |
//resource which is the bit-array of resources containing compressed Unicode
|
sl@0
|
427 |
//(this automatically generated resource does not have a corresponding bit for
|
sl@0
|
428 |
//itself in the bit-array as it would be self-referring...)
|
sl@0
|
429 |
++resourceIndex;
|
sl@0
|
430 |
}
|
sl@0
|
431 |
assert_obj.AssertDebL(resourceIndex>=0, EBafPanicNegativeResourceIndex3);
|
sl@0
|
432 |
HBufC8* const dictionaryDecompressedResourceData=DictionaryDecompressedResourceDataLC(
|
sl@0
|
433 |
resourceIndex,
|
sl@0
|
434 |
iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),
|
sl@0
|
435 |
iExtra->iDictionaryCompressionData,
|
sl@0
|
436 |
*iIndex);
|
sl@0
|
437 |
if (!iExtra->ContainsCompressedUnicodeL(resourceIndex,firstResourceIsGenerated))
|
sl@0
|
438 |
{
|
sl@0
|
439 |
return dictionaryDecompressedResourceData;
|
sl@0
|
440 |
}
|
sl@0
|
441 |
HBufC8* const finalResourceData=DecompressUnicodeL(
|
sl@0
|
442 |
*dictionaryDecompressedResourceData,
|
sl@0
|
443 |
iSizeOfLargestResourceWhenCompletelyUncompressed);
|
sl@0
|
444 |
CleanupStack::PopAndDestroy(dictionaryDecompressedResourceData);
|
sl@0
|
445 |
CleanupStack::PushL(finalResourceData);
|
sl@0
|
446 |
return finalResourceData;
|
sl@0
|
447 |
}
|
sl@0
|
448 |
|
sl@0
|
449 |
/** @internalComponent
|
sl@0
|
450 |
@return The first resource record.
|
sl@0
|
451 |
@panic Some BAFL panic codes, if the file is corrupted.
|
sl@0
|
452 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
453 |
Some other error codes are possible too.
|
sl@0
|
454 |
The method could panic or leave depending on the state of
|
sl@0
|
455 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
456 |
RResourceFileImpl::SSigRecord RResourceFileImpl::FirstRecordL() const
|
sl@0
|
457 |
{
|
sl@0
|
458 |
// Added to support reading of rel 6.x resource files.
|
sl@0
|
459 |
// rel 6.x files do not have signatures!
|
sl@0
|
460 |
|
sl@0
|
461 |
HBufC8* const firstResource=AllocReadLC(1);
|
sl@0
|
462 |
|
sl@0
|
463 |
// Basic check to test if the signature is of the correct size.
|
sl@0
|
464 |
if (firstResource->Size() != sizeof(SSigRecord))
|
sl@0
|
465 |
{
|
sl@0
|
466 |
User::Leave(KErrCorrupt);
|
sl@0
|
467 |
}
|
sl@0
|
468 |
SSigRecord sigRecord = *reinterpret_cast<const SSigRecord*>(firstResource->Ptr());
|
sl@0
|
469 |
CleanupStack::PopAndDestroy(firstResource);
|
sl@0
|
470 |
return sigRecord;
|
sl@0
|
471 |
}
|
sl@0
|
472 |
|
sl@0
|
473 |
/** Initialises the offset value from the first resource.
|
sl@0
|
474 |
The function assumes that the first resource in the file consists of
|
sl@0
|
475 |
two 32-bit integers. The first integer contains the version number and
|
sl@0
|
476 |
the second is a self-referencing link whose value is the offset for
|
sl@0
|
477 |
the resources in the file, plus 1.This function must be called before
|
sl@0
|
478 |
calling Offset(), AllocReadL(), AllocReadLC() or ReadL().
|
sl@0
|
479 |
@internalComponent
|
sl@0
|
480 |
@pre OpenL() is called.
|
sl@0
|
481 |
@param aSignature This argument value is not used by the function.
|
sl@0
|
482 |
@see Offset()
|
sl@0
|
483 |
@see AllocReadL()
|
sl@0
|
484 |
@see AllocReadLC()
|
sl@0
|
485 |
@see ReadL()
|
sl@0
|
486 |
@panic Some BAFL panic codes, if the file is corrupted.
|
sl@0
|
487 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
488 |
Some other error codes are possible too.
|
sl@0
|
489 |
The method could panic or leave depending on the state of
|
sl@0
|
490 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
491 |
void RResourceFileImpl::ConfirmSignatureL(TInt /*aSignature*/)
|
sl@0
|
492 |
{
|
sl@0
|
493 |
SSigRecord first_record=FirstRecordL();
|
sl@0
|
494 |
// test removed by SC 29/09/98 - assume that existing resource layout and structures
|
sl@0
|
495 |
//are fixed now
|
sl@0
|
496 |
// if (first_record.signature!=aSignature)
|
sl@0
|
497 |
// Leave(KErrBaflWrongResourceFileSignature);
|
sl@0
|
498 |
iOffset=first_record.offset & EOffsetBits;
|
sl@0
|
499 |
}
|
sl@0
|
500 |
|
sl@0
|
501 |
/** Initialises the offset value from the first resource.
|
sl@0
|
502 |
|
sl@0
|
503 |
The function tests to catch cases where the first resource is not an RSS_SIGNATURE.
|
sl@0
|
504 |
It assumes that the first resource in the file consists of
|
sl@0
|
505 |
two 32-bit integers. The first integer contains the version number and
|
sl@0
|
506 |
the second is a self-referencing link whose value is the offset for
|
sl@0
|
507 |
the resources in the file, plus 1.This function must be called before
|
sl@0
|
508 |
calling Offset(), AllocReadL(), AllocReadLC() or ReadL().
|
sl@0
|
509 |
|
sl@0
|
510 |
@see Offset()
|
sl@0
|
511 |
@see AllocReadL()
|
sl@0
|
512 |
@see AllocReadLC()
|
sl@0
|
513 |
@see ReadL()
|
sl@0
|
514 |
@internalComponent
|
sl@0
|
515 |
@pre OpenL() is called.
|
sl@0
|
516 |
@panic Some BAFL panic codes, if the file is corrupted.
|
sl@0
|
517 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
518 |
Some other error codes are possible too.
|
sl@0
|
519 |
The method could panic or leave depending on the state of
|
sl@0
|
520 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
521 |
void RResourceFileImpl::ConfirmSignatureL()
|
sl@0
|
522 |
{
|
sl@0
|
523 |
// Added to support reading of rel 6.x resource files.
|
sl@0
|
524 |
|
sl@0
|
525 |
SSigRecord firstRecord=FirstRecordL();
|
sl@0
|
526 |
|
sl@0
|
527 |
// If the resource offset does not correspond to the first resource
|
sl@0
|
528 |
// this is not a resource signature.
|
sl@0
|
529 |
if ((firstRecord.offset & EIdBits) != 1)
|
sl@0
|
530 |
{
|
sl@0
|
531 |
User::Leave(KErrCorrupt);
|
sl@0
|
532 |
}
|
sl@0
|
533 |
iOffset=(firstRecord.offset & EOffsetBits);
|
sl@0
|
534 |
}
|
sl@0
|
535 |
|
sl@0
|
536 |
/** @internalComponent
|
sl@0
|
537 |
@pre OpenL() is called.
|
sl@0
|
538 |
@panic Some BAFL panic codes, if the file is corrupted.
|
sl@0
|
539 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
540 |
Some other error codes are possible too.
|
sl@0
|
541 |
The method could panic or leave depending on the state of
|
sl@0
|
542 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
543 |
TInt RResourceFileImpl::SignatureL() const
|
sl@0
|
544 |
{
|
sl@0
|
545 |
SSigRecord first_record=FirstRecordL();
|
sl@0
|
546 |
return first_record.signature;
|
sl@0
|
547 |
}
|
sl@0
|
548 |
|
sl@0
|
549 |
/** Tests whether the resource file owns the specified resource id.
|
sl@0
|
550 |
|
sl@0
|
551 |
The resource file owns the resource id if the most significant 20 bits
|
sl@0
|
552 |
of the resource id are zero or match the offset value as returned from
|
sl@0
|
553 |
a call to the Offset() member function or if the resource id is not out of range.
|
sl@0
|
554 |
|
sl@0
|
555 |
@internalComponent
|
sl@0
|
556 |
@see Offset()
|
sl@0
|
557 |
@pre OpenL() is called.
|
sl@0
|
558 |
@param aResourceId The resource id to test.
|
sl@0
|
559 |
@return True, if the resource file owns the id, false otherwise.
|
sl@0
|
560 |
@panic Some BAFL panic codes, if the file is corrupted.
|
sl@0
|
561 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
562 |
Some other error codes are possible too.
|
sl@0
|
563 |
The method could panic or leave depending on the state of
|
sl@0
|
564 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
565 |
TBool RResourceFileImpl::OwnsResourceIdL(TInt aResourceId) const
|
sl@0
|
566 |
{
|
sl@0
|
567 |
// whether owns resource: does so if offset 0, or matches that given,
|
sl@0
|
568 |
//and id is in index
|
sl@0
|
569 |
const TInt offset=(aResourceId & EOffsetBits);
|
sl@0
|
570 |
if ((offset!=0) && (offset!=iOffset))
|
sl@0
|
571 |
{
|
sl@0
|
572 |
return EFalse;
|
sl@0
|
573 |
}
|
sl@0
|
574 |
const TBaAssert& assert_obj = iExtra->iAssertObj;
|
sl@0
|
575 |
const TInt resourceIndex=(aResourceId & EIdBits)-1;
|
sl@0
|
576 |
TInt numberOfResources=(iFlagsAndNumberOfResources & ~EAllFlags);
|
sl@0
|
577 |
if (iFlagsAndNumberOfResources & EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource)
|
sl@0
|
578 |
{
|
sl@0
|
579 |
assert_obj.AssertDebL(iFlagsAndNumberOfResources & EFlagDictionaryCompressed,
|
sl@0
|
580 |
EBafPanicBadFlags3);
|
sl@0
|
581 |
assert_obj.AssertDebL(iFlagsAndNumberOfResources & EFlagThirdUidIsOffset,
|
sl@0
|
582 |
EBafPanicBadFlags4);
|
sl@0
|
583 |
++numberOfResources;
|
sl@0
|
584 |
}
|
sl@0
|
585 |
if (iFlagsAndNumberOfResources &
|
sl@0
|
586 |
EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode)
|
sl@0
|
587 |
{
|
sl@0
|
588 |
iExtra->iAssertObj.AssertDebL(iFlagsAndNumberOfResources & EFlagDictionaryCompressed,
|
sl@0
|
589 |
EBafPanicBadFlags5);
|
sl@0
|
590 |
--numberOfResources;
|
sl@0
|
591 |
}
|
sl@0
|
592 |
return (resourceIndex >= 0) && (resourceIndex < numberOfResources);
|
sl@0
|
593 |
}
|
sl@0
|
594 |
|
sl@0
|
595 |
/** The method will decomress the unicode data (aCompressedUnicode argument) and append
|
sl@0
|
596 |
the decompressed data to the end of aBuffer (aBuffer argument).
|
sl@0
|
597 |
|
sl@0
|
598 |
@internalComponent
|
sl@0
|
599 |
@pre OpenL() is called.
|
sl@0
|
600 |
@param aBuffer Destination buffer.
|
sl@0
|
601 |
@param aCompressedUnicode Compressed unicode buffer.
|
sl@0
|
602 |
@panic Some BAFL panic codes, if the file is corrupted.
|
sl@0
|
603 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
604 |
Some other error codes are possible too.
|
sl@0
|
605 |
The method could panic or leave depending on the state of
|
sl@0
|
606 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
607 |
void RResourceFileImpl::AppendDecompressedUnicodeL(
|
sl@0
|
608 |
TDes8& aBuffer,
|
sl@0
|
609 |
const TDesC8& aCompressedUnicode) const
|
sl@0
|
610 |
{
|
sl@0
|
611 |
const TBaAssert& assert_obj = iExtra->iAssertObj;
|
sl@0
|
612 |
const TInt lengthOfCompressedUnicode=aCompressedUnicode.Length();
|
sl@0
|
613 |
if (lengthOfCompressedUnicode>0)
|
sl@0
|
614 |
{
|
sl@0
|
615 |
const TUint8* startOfDecompressedUnicode=aBuffer.Ptr()+aBuffer.Length();
|
sl@0
|
616 |
if (REINTERPRET_CAST(TUint,startOfDecompressedUnicode) & 0x01)
|
sl@0
|
617 |
{
|
sl@0
|
618 |
assert_obj.AssertDebL(aBuffer.MaxLength() >= (aBuffer.Length() + 1),
|
sl@0
|
619 |
EBafPanicMaxLength2);
|
sl@0
|
620 |
aBuffer.Append(0xab);
|
sl@0
|
621 |
++startOfDecompressedUnicode;
|
sl@0
|
622 |
}
|
sl@0
|
623 |
//works correctly, even if aBuffer.MaxLength()-aBuffer.Length() is an odd number
|
sl@0
|
624 |
const TInt maximumOutputLength=(aBuffer.MaxLength()-aBuffer.Length())/2;
|
sl@0
|
625 |
TMemoryUnicodeSink decompressedUnicode(REINTERPRET_CAST(TUint16*,CONST_CAST(
|
sl@0
|
626 |
TUint8*,startOfDecompressedUnicode)));
|
sl@0
|
627 |
TInt lengthOfDecompressedUnicode;
|
sl@0
|
628 |
TInt numberOfInputBytesConsumed;
|
sl@0
|
629 |
TUnicodeExpander unicodeExpander;
|
sl@0
|
630 |
unicodeExpander.ExpandL(decompressedUnicode,
|
sl@0
|
631 |
aCompressedUnicode.Ptr(),
|
sl@0
|
632 |
maximumOutputLength,
|
sl@0
|
633 |
lengthOfCompressedUnicode,
|
sl@0
|
634 |
&lengthOfDecompressedUnicode,
|
sl@0
|
635 |
&numberOfInputBytesConsumed);
|
sl@0
|
636 |
TInt temp;
|
sl@0
|
637 |
unicodeExpander.FlushL(decompressedUnicode,maximumOutputLength,temp);
|
sl@0
|
638 |
lengthOfDecompressedUnicode+=temp;
|
sl@0
|
639 |
assert_obj.AssertRelL(numberOfInputBytesConsumed==lengthOfCompressedUnicode,
|
sl@0
|
640 |
EBafPanicBadDecompression);
|
sl@0
|
641 |
aBuffer.SetLength(aBuffer.Length()+(lengthOfDecompressedUnicode*2));
|
sl@0
|
642 |
}
|
sl@0
|
643 |
}
|
sl@0
|
644 |
|
sl@0
|
645 |
/** The method will decompress the unicode data (aInputResourceData argument), allocate enough
|
sl@0
|
646 |
memory from the heap for the decompressed data, copy the data there and return a descriptor
|
sl@0
|
647 |
to the decompressed data.
|
sl@0
|
648 |
|
sl@0
|
649 |
The method doesn't own the allocated heap memory for the decompressed data. It's a caller
|
sl@0
|
650 |
responsibility to deallocate the allocated memory.
|
sl@0
|
651 |
|
sl@0
|
652 |
@internalComponent
|
sl@0
|
653 |
@param aInputResourceData Compressed data.
|
sl@0
|
654 |
@param aSizeOfLargestResourceWhenCompletelyUncompressed The size of decomressed data.
|
sl@0
|
655 |
@pre OpenL() is called.
|
sl@0
|
656 |
@panic Some BAFL panic codes, if the file is corrupted.
|
sl@0
|
657 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
658 |
@leave KErrNoMemory There is not enough memory for the decompressed data.
|
sl@0
|
659 |
Some other error codes are possible too.
|
sl@0
|
660 |
The method could panic or leave depending on the state of
|
sl@0
|
661 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
662 |
HBufC8* RResourceFileImpl::DecompressUnicodeL(const TDesC8& aInputResourceData,
|
sl@0
|
663 |
TInt aSizeOfLargestResourceWhenCompletelyUncompressed) const
|
sl@0
|
664 |
{
|
sl@0
|
665 |
const TBaAssert& assert_obj = iExtra->iAssertObj;
|
sl@0
|
666 |
const TInt numberOfBytesInInput=aInputResourceData.Length();
|
sl@0
|
667 |
assert_obj.AssertDebL(aSizeOfLargestResourceWhenCompletelyUncompressed>0,
|
sl@0
|
668 |
EBafPanicBadSizeOfLargestResourceWhenCompletelyUncompressed2);
|
sl@0
|
669 |
HBufC8* const outputResourceData=
|
sl@0
|
670 |
HBufC8::NewLC(aSizeOfLargestResourceWhenCompletelyUncompressed);
|
sl@0
|
671 |
TPtr8 asWritable(outputResourceData->Des());
|
sl@0
|
672 |
const TUint8* input=aInputResourceData.Ptr();
|
sl@0
|
673 |
TInt index=0;
|
sl@0
|
674 |
for (TBool decompressRun=ETrue; ; decompressRun=!decompressRun)
|
sl@0
|
675 |
{
|
sl@0
|
676 |
assert_obj.AssertDebL(index<numberOfBytesInInput, EBafPanicIndexOverRan);
|
sl@0
|
677 |
TInt runLength=input[index];
|
sl@0
|
678 |
if (runLength & 0x80)
|
sl@0
|
679 |
{
|
sl@0
|
680 |
++index;
|
sl@0
|
681 |
if (index>=numberOfBytesInInput)
|
sl@0
|
682 |
{
|
sl@0
|
683 |
User::Leave(KErrCorrupt);
|
sl@0
|
684 |
}
|
sl@0
|
685 |
runLength &= ~0x80;
|
sl@0
|
686 |
runLength <<= 8;
|
sl@0
|
687 |
runLength |= input[index];
|
sl@0
|
688 |
}
|
sl@0
|
689 |
++index;
|
sl@0
|
690 |
if (runLength>0)
|
sl@0
|
691 |
{
|
sl@0
|
692 |
const TPtrC8 run(input+index,runLength);
|
sl@0
|
693 |
if (decompressRun)
|
sl@0
|
694 |
{
|
sl@0
|
695 |
AppendDecompressedUnicodeL(asWritable,run);
|
sl@0
|
696 |
}
|
sl@0
|
697 |
else
|
sl@0
|
698 |
{
|
sl@0
|
699 |
assert_obj.AssertDebL(
|
sl@0
|
700 |
(asWritable.Length() + runLength) <= asWritable.MaxLength(),
|
sl@0
|
701 |
EBafPanicOverflow);
|
sl@0
|
702 |
asWritable.Append(run);
|
sl@0
|
703 |
}
|
sl@0
|
704 |
index+=runLength;
|
sl@0
|
705 |
}
|
sl@0
|
706 |
if (index>numberOfBytesInInput)
|
sl@0
|
707 |
{
|
sl@0
|
708 |
User::Leave(KErrCorrupt);
|
sl@0
|
709 |
}
|
sl@0
|
710 |
if (index>=numberOfBytesInInput)
|
sl@0
|
711 |
{
|
sl@0
|
712 |
break;
|
sl@0
|
713 |
}
|
sl@0
|
714 |
}
|
sl@0
|
715 |
CleanupStack::Pop(outputResourceData);
|
sl@0
|
716 |
return outputResourceData;
|
sl@0
|
717 |
}
|
sl@0
|
718 |
|
sl@0
|
719 |
/** @internalComponent
|
sl@0
|
720 |
@pre OpenL() is called.
|
sl@0
|
721 |
@panic Some BAFL panic codes, if the file is corrupted.
|
sl@0
|
722 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
723 |
@leave KErrNoMemory There is not enough memory for the decompressed data.
|
sl@0
|
724 |
Some other error codes are possible too.
|
sl@0
|
725 |
The method could panic or leave depending on the state of
|
sl@0
|
726 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
727 |
HBufC8* RResourceFileImpl::DictionaryDecompressedResourceDataLC(
|
sl@0
|
728 |
TInt aResourceIndex,
|
sl@0
|
729 |
TUint aFlags,
|
sl@0
|
730 |
const SDictionaryCompressionData& aDictionaryCompressionData,
|
sl@0
|
731 |
const TDesC16& aIndex) const
|
sl@0
|
732 |
{
|
sl@0
|
733 |
const TBaAssert& assert_obj = iExtra->iAssertObj;
|
sl@0
|
734 |
if (aFlags & EFlagDictionaryCompressed)
|
sl@0
|
735 |
{
|
sl@0
|
736 |
assert_obj.AssertDebL(iSizeOfLargestResourceWhenCompletelyUncompressed>0,
|
sl@0
|
737 |
EBafPanicBadSizeOfLargestResourceWhenCompletelyUncompressed3);
|
sl@0
|
738 |
HBufC8* const outputResourceData=
|
sl@0
|
739 |
HBufC8::NewLC(iSizeOfLargestResourceWhenCompletelyUncompressed);
|
sl@0
|
740 |
TPtr8 asWritable(outputResourceData->Des());
|
sl@0
|
741 |
RArray<RDictionaryCompressionBitStream> stackOfDictionaryCompressionBitStreams;
|
sl@0
|
742 |
CleanupStack::PushL(
|
sl@0
|
743 |
TCleanupItem(CloseArrayOfDictionaryCompressionBitStreams,
|
sl@0
|
744 |
&stackOfDictionaryCompressionBitStreams));
|
sl@0
|
745 |
AppendDictionaryCompressionBitStreamL(
|
sl@0
|
746 |
stackOfDictionaryCompressionBitStreams,
|
sl@0
|
747 |
aFlags,
|
sl@0
|
748 |
aDictionaryCompressionData,
|
sl@0
|
749 |
aDictionaryCompressionData.iStartOfResourceData,
|
sl@0
|
750 |
aDictionaryCompressionData.iStartOfResourceIndex,
|
sl@0
|
751 |
aResourceIndex);
|
sl@0
|
752 |
const TBool calypsoFileFormat=(aFlags & EFlagCalypsoFileFormat);
|
sl@0
|
753 |
FOREVER
|
sl@0
|
754 |
{
|
sl@0
|
755 |
const TInt indexOfTopBitStream=stackOfDictionaryCompressionBitStreams.Count()-1;
|
sl@0
|
756 |
assert_obj.AssertDebL(indexOfTopBitStream>=-1, EBafPanicNegativeArrayIndex);
|
sl@0
|
757 |
if (indexOfTopBitStream<0)
|
sl@0
|
758 |
{
|
sl@0
|
759 |
break;
|
sl@0
|
760 |
}
|
sl@0
|
761 |
RDictionaryCompressionBitStream& dictionaryCompressionBitStream=
|
sl@0
|
762 |
stackOfDictionaryCompressionBitStreams[indexOfTopBitStream];
|
sl@0
|
763 |
FOREVER
|
sl@0
|
764 |
{
|
sl@0
|
765 |
if (dictionaryCompressionBitStream.EndOfStreamL())
|
sl@0
|
766 |
{
|
sl@0
|
767 |
dictionaryCompressionBitStream.Close();
|
sl@0
|
768 |
stackOfDictionaryCompressionBitStreams.Remove(indexOfTopBitStream);
|
sl@0
|
769 |
break;
|
sl@0
|
770 |
}
|
sl@0
|
771 |
const TInt indexOfDictionaryEntry=
|
sl@0
|
772 |
dictionaryCompressionBitStream.IndexOfDictionaryEntryL();
|
sl@0
|
773 |
if (indexOfDictionaryEntry<0)
|
sl@0
|
774 |
{
|
sl@0
|
775 |
dictionaryCompressionBitStream.ReadL(asWritable,calypsoFileFormat);
|
sl@0
|
776 |
}
|
sl@0
|
777 |
else
|
sl@0
|
778 |
{
|
sl@0
|
779 |
AppendDictionaryCompressionBitStreamL(
|
sl@0
|
780 |
stackOfDictionaryCompressionBitStreams,
|
sl@0
|
781 |
aFlags,
|
sl@0
|
782 |
aDictionaryCompressionData,
|
sl@0
|
783 |
aDictionaryCompressionData.iStartOfDictionaryData,
|
sl@0
|
784 |
aDictionaryCompressionData.iStartOfDictionaryIndex,
|
sl@0
|
785 |
indexOfDictionaryEntry);
|
sl@0
|
786 |
break;
|
sl@0
|
787 |
}
|
sl@0
|
788 |
}
|
sl@0
|
789 |
}
|
sl@0
|
790 |
CleanupStack::PopAndDestroy(&stackOfDictionaryCompressionBitStreams);
|
sl@0
|
791 |
return outputResourceData;
|
sl@0
|
792 |
}
|
sl@0
|
793 |
assert_obj.AssertDebL(aResourceIndex < aIndex.Length(), EBafPanicBadIndex2);
|
sl@0
|
794 |
const TInt positionOfResourceData=aIndex[aResourceIndex];
|
sl@0
|
795 |
const TInt numberOfBytes=aIndex[aResourceIndex+1]-positionOfResourceData;
|
sl@0
|
796 |
assert_obj.AssertDebL(numberOfBytes >= 0, EBafPanicNegativeNumber3);
|
sl@0
|
797 |
HBufC8* const outputResourceData=HBufC8::NewLC(numberOfBytes);
|
sl@0
|
798 |
TPtr8 asWritable(outputResourceData->Des());
|
sl@0
|
799 |
ReadL(aFlags,positionOfResourceData,asWritable,numberOfBytes);
|
sl@0
|
800 |
return outputResourceData;
|
sl@0
|
801 |
}
|
sl@0
|
802 |
|
sl@0
|
803 |
/** @internalComponent
|
sl@0
|
804 |
@pre OpenL() is called.
|
sl@0
|
805 |
@panic Some BAFL panic codes, if the file is corrupted.
|
sl@0
|
806 |
@leave KErrCorrupt The file is corrupted.
|
sl@0
|
807 |
Some other error codes are possible too.
|
sl@0
|
808 |
The method could panic or leave depending on the state of
|
sl@0
|
809 |
iAssertObj member of RResourceFileImpl::TExtra class. */
|
sl@0
|
810 |
void RResourceFileImpl::AppendDictionaryCompressionBitStreamL(
|
sl@0
|
811 |
RArray<RDictionaryCompressionBitStream>& aStackOfDictionaryCompressionBitStreams,
|
sl@0
|
812 |
TUint aFlags,
|
sl@0
|
813 |
const SDictionaryCompressionData& aDictionaryCompressionData,
|
sl@0
|
814 |
TInt aStartOfBitData,
|
sl@0
|
815 |
TInt aStartOfIndex,
|
sl@0
|
816 |
TInt aIndexEntry) const
|
sl@0
|
817 |
{
|
sl@0
|
818 |
const TBaAssert& assert_obj = iExtra->iAssertObj;
|
sl@0
|
819 |
const TBool isRomFile=(aFlags & static_cast<TUint>(EFlagIsRomFile));
|
sl@0
|
820 |
TBuf8<4> temp;
|
sl@0
|
821 |
assert_obj.AssertDebL(aIndexEntry>=0, EBafPanicNegativeIndexEntry);
|
sl@0
|
822 |
TInt offsetToFirstBit;
|
sl@0
|
823 |
TInt offsetOnePastLastBit;
|
sl@0
|
824 |
if ( aDictionaryCompressionData.iStartOfDictionaryIndex == aStartOfIndex
|
sl@0
|
825 |
&& aDictionaryCompressionData.iCachedDictionaryIndex != 0)
|
sl@0
|
826 |
{
|
sl@0
|
827 |
__ASSERT_DEBUG(!isRomFile,User::Invariant());
|
sl@0
|
828 |
// indices start at 1
|
sl@0
|
829 |
offsetToFirstBit = (aIndexEntry <= 0)
|
sl@0
|
830 |
? 0
|
sl@0
|
831 |
: aDictionaryCompressionData.iCachedDictionaryIndex[aIndexEntry-1];
|
sl@0
|
832 |
offsetOnePastLastBit = aDictionaryCompressionData.iCachedDictionaryIndex[aIndexEntry];
|
sl@0
|
833 |
}
|
sl@0
|
834 |
else
|
sl@0
|
835 |
{
|
sl@0
|
836 |
ReadL(aFlags,aStartOfIndex+((aIndexEntry-1)*2),temp,4);
|
sl@0
|
837 |
offsetToFirstBit=(aIndexEntry > 0) ? LittleEndianTwoByteIntegerL(temp,0) : 0;
|
sl@0
|
838 |
offsetOnePastLastBit=LittleEndianTwoByteIntegerL(temp,2);
|
sl@0
|
839 |
}
|
sl@0
|
840 |
TInt rsc_file_size = iExtra->iFileOffset + iExtra->iFileSize;
|
sl@0
|
841 |
TInt offset_first = offsetToFirstBit / 8 + iExtra->iFileOffset;
|
sl@0
|
842 |
assert_obj.AssertDebL(offset_first < rsc_file_size, EBafPanicBadOffset);
|
sl@0
|
843 |
TInt offset_last = offsetOnePastLastBit / 8 + iExtra->iFileOffset;
|
sl@0
|
844 |
assert_obj.AssertDebL(offset_last <= rsc_file_size, EBafPanicBadOffset2);
|
sl@0
|
845 |
TUint8* buffer = NULL;
|
sl@0
|
846 |
TInt start_pos = 0;
|
sl@0
|
847 |
if (isRomFile)
|
sl@0
|
848 |
{
|
sl@0
|
849 |
TInt startOfBitData = aStartOfBitData + iExtra->iFileOffset;
|
sl@0
|
850 |
assert_obj.AssertDebL(startOfBitData < rsc_file_size, EBafPanicStartPos);
|
sl@0
|
851 |
//for some reason, GCC gives a warning if the
|
sl@0
|
852 |
//STATIC_CAST(const TUint8*,aFile) is used instead of STATIC_CAST(TUint8*,aFile)
|
sl@0
|
853 |
buffer = STATIC_CAST(TUint8*,iFile) + startOfBitData;
|
sl@0
|
854 |
}
|
sl@0
|
855 |
else
|
sl@0
|
856 |
{
|
sl@0
|
857 |
const TInt offsetToByteContainingFirstBit=offsetToFirstBit/8;
|
sl@0
|
858 |
const TInt offsetToOnePastByteContainingLastBit=((offsetOnePastLastBit-1)/8)+1;
|
sl@0
|
859 |
const TInt numberOfBytesToLoad=
|
sl@0
|
860 |
offsetToOnePastByteContainingLastBit-offsetToByteContainingFirstBit;
|
sl@0
|
861 |
assert_obj.AssertDebL(numberOfBytesToLoad >= 0, EBafPanicNegativeNumber2);
|
sl@0
|
862 |
buffer=new(ELeave) TUint8[numberOfBytesToLoad];
|
sl@0
|
863 |
CleanupArrayDeletePushL(buffer);
|
sl@0
|
864 |
if( iExtra->iDictionaryCompressionData.iCachedResourceBuffer == 0)
|
sl@0
|
865 |
{
|
sl@0
|
866 |
iExtra->iDictionaryCompressionData.iCachedResourceBuffer=new(ELeave) TUint8[rsc_file_size]; // reserver buffer for whole file
|
sl@0
|
867 |
TPtr8 JKasWritable(iExtra->iDictionaryCompressionData.iCachedResourceBuffer,rsc_file_size);
|
sl@0
|
868 |
User::LeaveIfError(
|
sl@0
|
869 |
STATIC_CAST(RFile*,iFile)->Read(
|
sl@0
|
870 |
0,
|
sl@0
|
871 |
JKasWritable,
|
sl@0
|
872 |
rsc_file_size));
|
sl@0
|
873 |
}
|
sl@0
|
874 |
start_pos = aStartOfBitData + offsetToByteContainingFirstBit + iExtra->iFileOffset;
|
sl@0
|
875 |
assert_obj.AssertDebL(start_pos < rsc_file_size, EBafPanicStartPos2);
|
sl@0
|
876 |
assert_obj.AssertDebL((start_pos + numberOfBytesToLoad) <= rsc_file_size, EBafPanicFileSize4);
|
sl@0
|
877 |
const TInt numberOfBitsFromStartOfBitDataToFirstLoadedByte=
|
sl@0
|
878 |
offsetToByteContainingFirstBit*8;
|
sl@0
|
879 |
offsetToFirstBit-=numberOfBitsFromStartOfBitDataToFirstLoadedByte;
|
sl@0
|
880 |
offsetOnePastLastBit-=numberOfBitsFromStartOfBitDataToFirstLoadedByte;
|
sl@0
|
881 |
|
sl@0
|
882 |
Mem::Copy( buffer, iExtra->iDictionaryCompressionData.iCachedResourceBuffer + start_pos, numberOfBytesToLoad);
|
sl@0
|
883 |
}
|
sl@0
|
884 |
RDictionaryCompressionBitStream stream;
|
sl@0
|
885 |
stream.OpenL(
|
sl@0
|
886 |
aDictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens,
|
sl@0
|
887 |
offsetToFirstBit,
|
sl@0
|
888 |
offsetOnePastLastBit,
|
sl@0
|
889 |
!isRomFile,
|
sl@0
|
890 |
buffer,
|
sl@0
|
891 |
assert_obj);
|
sl@0
|
892 |
User::LeaveIfError(aStackOfDictionaryCompressionBitStreams.Append(stream));
|
sl@0
|
893 |
if (!isRomFile)
|
sl@0
|
894 |
{
|
sl@0
|
895 |
CleanupStack::Pop(buffer); // buffer deleted in RDictionaryCompressionBitStream::close
|
sl@0
|
896 |
}
|
sl@0
|
897 |
}
|
sl@0
|
898 |
|
sl@0
|
899 |
/** @internalComponent
|
sl@0
|
900 |
@pre OpenL() is called. */
|
sl@0
|
901 |
TInt RResourceFileImpl::LittleEndianTwoByteIntegerL(
|
sl@0
|
902 |
const TDesC8& aBuffer,
|
sl@0
|
903 |
TInt aIndexOfFirstByte) const
|
sl@0
|
904 |
{
|
sl@0
|
905 |
iExtra->iAssertObj.AssertDebL((aIndexOfFirstByte + 1) < aBuffer.Length(), EBafPanicBadIndex3);
|
sl@0
|
906 |
return aBuffer[aIndexOfFirstByte] | (aBuffer[aIndexOfFirstByte+1]<<8);
|
sl@0
|
907 |
}
|
sl@0
|
908 |
|
sl@0
|
909 |
/** @internalComponent
|
sl@0
|
910 |
@pre OpenL() is called. */
|
sl@0
|
911 |
void RResourceFileImpl::ReadL(TUint aFlags,TInt aPos,TDes8& aDes,TInt aLength) const
|
sl@0
|
912 |
{
|
sl@0
|
913 |
aPos += iExtra->iFileOffset;
|
sl@0
|
914 |
const TBaAssert& assert_obj = iExtra->iAssertObj;
|
sl@0
|
915 |
assert_obj.AssertDebL(aPos >= iExtra->iFileOffset, EBafPanicNegativePos);
|
sl@0
|
916 |
assert_obj.AssertDebL(aLength >= 0, EBafPanicNegativeLength);
|
sl@0
|
917 |
assert_obj.AssertDebL(aLength <= aDes.MaxLength(), EBafPanicMaxLength);
|
sl@0
|
918 |
assert_obj.AssertDebL((aPos + aLength) <= (iExtra->iFileOffset + iExtra->iFileSize), EBafPanicFileSize3);
|
sl@0
|
919 |
if (aFlags & static_cast<TUint>(EFlagIsRomFile))
|
sl@0
|
920 |
{
|
sl@0
|
921 |
//for some reason, GCC gives a warning if the
|
sl@0
|
922 |
//STATIC_CAST(const TUint8*,aFile) is used instead of STATIC_CAST(TUint8*,aFile)
|
sl@0
|
923 |
aDes.Copy(STATIC_CAST(TUint8*,iFile)+aPos,aLength);
|
sl@0
|
924 |
}
|
sl@0
|
925 |
else if (aFlags & static_cast<TUint>(EFlagIsBufferRscFile))
|
sl@0
|
926 |
{
|
sl@0
|
927 |
HBufC8* buffer=STATIC_CAST(HBufC8*,iFile);
|
sl@0
|
928 |
aDes.Copy(CONST_CAST(TUint8*,buffer->Ptr())+aPos,aLength);
|
sl@0
|
929 |
}
|
sl@0
|
930 |
else
|
sl@0
|
931 |
{
|
sl@0
|
932 |
User::LeaveIfError(STATIC_CAST(RFile*,iFile)->Read(aPos,aDes,aLength));
|
sl@0
|
933 |
}
|
sl@0
|
934 |
}
|
sl@0
|
935 |
|
sl@0
|
936 |
/** @internalComponent
|
sl@0
|
937 |
@pre OpenL() is called. */
|
sl@0
|
938 |
void RResourceFileImpl::ReadL(TInt aPos,TDes8& aDes,TInt aLength) const
|
sl@0
|
939 |
{
|
sl@0
|
940 |
ReadL(iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),aPos,aDes,aLength);
|
sl@0
|
941 |
}
|
sl@0
|
942 |
|
sl@0
|
943 |
/** Returns the offset value defined for this resource file.
|
sl@0
|
944 |
|
sl@0
|
945 |
This function must not be called until a call to
|
sl@0
|
946 |
ConfirmSignatureL() has completed successfully, otherwise
|
sl@0
|
947 |
the value returned by this function may be meaningless.
|
sl@0
|
948 |
|
sl@0
|
949 |
@see ConfirmSignatureL()
|
sl@0
|
950 |
@internalComponent
|
sl@0
|
951 |
@pre OpenL() is called.
|
sl@0
|
952 |
@return The offset value defined for this resource file.
|
sl@0
|
953 |
*/
|
sl@0
|
954 |
TInt RResourceFileImpl::Offset() const
|
sl@0
|
955 |
{
|
sl@0
|
956 |
return iOffset;
|
sl@0
|
957 |
}
|
sl@0
|
958 |
|
sl@0
|
959 |
/** Function to retrieve the header information of the rsc file and all the
|
sl@0
|
960 |
resource index information in the rsc file. This function is created to
|
sl@0
|
961 |
handle the common functionality in the two OpenL() method.
|
sl@0
|
962 |
@internalComponent
|
sl@0
|
963 |
@pre OpenL() is called.
|
sl@0
|
964 |
*/
|
sl@0
|
965 |
void RResourceFileImpl::ReadHeaderAndResourceIndexL()
|
sl@0
|
966 |
{
|
sl@0
|
967 |
SDictionaryCompressionData dictionaryCompressionData;
|
sl@0
|
968 |
const TBaAssert& assert_obj = iExtra->iAssertObj;
|
sl@0
|
969 |
TUidType uidType;
|
sl@0
|
970 |
//dictionary-compressed resource files have a 21-byte header,
|
sl@0
|
971 |
//16 bytes of checked UIDs followed by a 1-byte field and two 2-byte fields
|
sl@0
|
972 |
TBuf8<21> header;
|
sl@0
|
973 |
if(iExtra->iFileSize >= 16)
|
sl@0
|
974 |
{
|
sl@0
|
975 |
ReadL(0,header,Min(header.MaxLength(),iExtra->iFileSize));
|
sl@0
|
976 |
uidType=TCheckedUid(header.Left(16)).UidType();
|
sl@0
|
977 |
if (uidType[0].iUid==0x101f4a6b)
|
sl@0
|
978 |
{
|
sl@0
|
979 |
iFlagsAndNumberOfResources |= EFlagPotentiallyContainsCompressedUnicode;
|
sl@0
|
980 |
assert_obj.AssertDebL(header.Length() >= 18, EBafPanicBadHeader1);
|
sl@0
|
981 |
iSizeOfLargestResourceWhenCompletelyUncompressed=
|
sl@0
|
982 |
LittleEndianTwoByteIntegerL(header,16+1);
|
sl@0
|
983 |
}
|
sl@0
|
984 |
else if (uidType[0].iUid==0x101f5010)
|
sl@0
|
985 |
{
|
sl@0
|
986 |
iFlagsAndNumberOfResources |=
|
sl@0
|
987 |
EFlagPotentiallyContainsCompressedUnicode | EFlagDictionaryCompressed;
|
sl@0
|
988 |
assert_obj.AssertDebL(header.Length() >= 18, EBafPanicBadHeader2);
|
sl@0
|
989 |
iSizeOfLargestResourceWhenCompletelyUncompressed=
|
sl@0
|
990 |
LittleEndianTwoByteIntegerL(header,16+1);
|
sl@0
|
991 |
}
|
sl@0
|
992 |
else if (uidType[0]!=TUid::Null())
|
sl@0
|
993 |
{
|
sl@0
|
994 |
User::Leave(KErrNotSupported);
|
sl@0
|
995 |
}
|
sl@0
|
996 |
//the "signature" of Calypso's resource files
|
sl@0
|
997 |
else if (LittleEndianTwoByteIntegerL(header,0)==4)
|
sl@0
|
998 |
{
|
sl@0
|
999 |
iFlagsAndNumberOfResources |= EFlagDictionaryCompressed | EFlagCalypsoFileFormat;
|
sl@0
|
1000 |
iSizeOfLargestResourceWhenCompletelyUncompressed=
|
sl@0
|
1001 |
LittleEndianTwoByteIntegerL(header,8);
|
sl@0
|
1002 |
}
|
sl@0
|
1003 |
}
|
sl@0
|
1004 |
|
sl@0
|
1005 |
//It seems that the following AssertDebL() call never fails,
|
sl@0
|
1006 |
//because LittleEndianTwoByteIntegerL always
|
sl@0
|
1007 |
//returns zero or positive value.
|
sl@0
|
1008 |
assert_obj.AssertDebL(iSizeOfLargestResourceWhenCompletelyUncompressed>=0,
|
sl@0
|
1009 |
EBafPanicBadSizeOfLargestResourceWhenCompletelyUncompressed1);
|
sl@0
|
1010 |
TInt numberOfResources=0;
|
sl@0
|
1011 |
HBufC8* bitArrayOfResourcesContainingCompressedUnicode=NULL;
|
sl@0
|
1012 |
if (iFlagsAndNumberOfResources & EFlagDictionaryCompressed)
|
sl@0
|
1013 |
{
|
sl@0
|
1014 |
if (iFlagsAndNumberOfResources & EFlagCalypsoFileFormat)
|
sl@0
|
1015 |
{
|
sl@0
|
1016 |
assert_obj.AssertDebL(header.Length() > 10, EBafPanicBadHeader3);
|
sl@0
|
1017 |
numberOfResources=LittleEndianTwoByteIntegerL(header,2);
|
sl@0
|
1018 |
const TInt numberOfBitsUsedForDictionaryTokens = header[10];
|
sl@0
|
1019 |
const TInt numberOfDictionaryEntries =
|
sl@0
|
1020 |
(1 << numberOfBitsUsedForDictionaryTokens) - header[5];
|
sl@0
|
1021 |
assert_obj.AssertDebL(numberOfDictionaryEntries >= 0, EBafPanicBadHeader4);
|
sl@0
|
1022 |
// "+2" because the first entry in the dictionary-index in this file format
|
sl@0
|
1023 |
//is the number of bits from the start of the dictionary data to the start
|
sl@0
|
1024 |
//of the first dictionary entry which is always zero, and thus unnecessary
|
sl@0
|
1025 |
const TInt startOfDictionaryData=4+7+2;
|
sl@0
|
1026 |
// "+2" because the first entry in the resource-index in this file format is
|
sl@0
|
1027 |
//the number of bits from the start of the resource data to the start of the
|
sl@0
|
1028 |
//first resource which is always zero, and thus unnecessary
|
sl@0
|
1029 |
const TInt startOfResourceIndex=LittleEndianTwoByteIntegerL(header,6)+2;
|
sl@0
|
1030 |
assert_obj.AssertDebL(startOfResourceIndex >= 0, EBafPanicBadHeader5);
|
sl@0
|
1031 |
dictionaryCompressionData.iStartOfDictionaryData=
|
sl@0
|
1032 |
startOfDictionaryData+(numberOfDictionaryEntries*2);
|
sl@0
|
1033 |
dictionaryCompressionData.iStartOfDictionaryIndex=startOfDictionaryData;
|
sl@0
|
1034 |
dictionaryCompressionData.iNumberOfDictionaryEntries=numberOfDictionaryEntries;
|
sl@0
|
1035 |
dictionaryCompressionData.iStartOfResourceData=
|
sl@0
|
1036 |
startOfResourceIndex+(numberOfResources*2);
|
sl@0
|
1037 |
dictionaryCompressionData.iStartOfResourceIndex=startOfResourceIndex;
|
sl@0
|
1038 |
dictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens=
|
sl@0
|
1039 |
numberOfBitsUsedForDictionaryTokens;
|
sl@0
|
1040 |
|
sl@0
|
1041 |
if ((iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsRomFile)) == 0)
|
sl@0
|
1042 |
{
|
sl@0
|
1043 |
// attempt to cache dictionary index
|
sl@0
|
1044 |
// allocate and populate the dictionary index buffer
|
sl@0
|
1045 |
dictionaryCompressionData.iCachedDictionaryIndex = new TUint16[numberOfDictionaryEntries];
|
sl@0
|
1046 |
if (dictionaryCompressionData.iCachedDictionaryIndex != 0)
|
sl@0
|
1047 |
{
|
sl@0
|
1048 |
TInt length = numberOfDictionaryEntries * 2;
|
sl@0
|
1049 |
TPtr8 ptr8((TUint8*)dictionaryCompressionData.iCachedDictionaryIndex, 0, length);
|
sl@0
|
1050 |
ReadL(
|
sl@0
|
1051 |
iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags), // aFlags
|
sl@0
|
1052 |
startOfDictionaryData, // aPos
|
sl@0
|
1053 |
ptr8,
|
sl@0
|
1054 |
length); // aLength
|
sl@0
|
1055 |
}
|
sl@0
|
1056 |
} // if (iFlagsAndNumberOfResources & EFlagIsRomFile)
|
sl@0
|
1057 |
}
|
sl@0
|
1058 |
else
|
sl@0
|
1059 |
{
|
sl@0
|
1060 |
assert_obj.AssertDebL(header.Length()==16+1+2+2, EBafPanicBadHeaderLength);
|
sl@0
|
1061 |
const TUint firstByteAfterUids=header[16];
|
sl@0
|
1062 |
if (firstByteAfterUids & 0x80)
|
sl@0
|
1063 |
{
|
sl@0
|
1064 |
// this flag is only set if the resource file is dictionary-compressed
|
sl@0
|
1065 |
iFlagsAndNumberOfResources |= EFlagThirdUidIsOffset;
|
sl@0
|
1066 |
}
|
sl@0
|
1067 |
if (firstByteAfterUids & 0x40)
|
sl@0
|
1068 |
{
|
sl@0
|
1069 |
// this flag is only set if the resource file is dictionary-compressed
|
sl@0
|
1070 |
iFlagsAndNumberOfResources |= EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource;
|
sl@0
|
1071 |
}
|
sl@0
|
1072 |
if (firstByteAfterUids & 0x20)
|
sl@0
|
1073 |
{
|
sl@0
|
1074 |
iFlagsAndNumberOfResources |=
|
sl@0
|
1075 |
EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode;
|
sl@0
|
1076 |
}
|
sl@0
|
1077 |
dictionaryCompressionData.iStartOfResourceData=
|
sl@0
|
1078 |
LittleEndianTwoByteIntegerL(header,16+1+2);
|
sl@0
|
1079 |
TBuf8<2> temp;
|
sl@0
|
1080 |
ReadL((iExtra->iFileSize)-2,temp,2);
|
sl@0
|
1081 |
const TInt numberOfBitsOfResourceData=LittleEndianTwoByteIntegerL(temp,0);
|
sl@0
|
1082 |
dictionaryCompressionData.iStartOfResourceIndex=
|
sl@0
|
1083 |
dictionaryCompressionData.iStartOfResourceData+
|
sl@0
|
1084 |
((numberOfBitsOfResourceData+7)/8);
|
sl@0
|
1085 |
numberOfResources=(iExtra->iFileSize-dictionaryCompressionData.iStartOfResourceIndex)/2;
|
sl@0
|
1086 |
dictionaryCompressionData.iStartOfDictionaryData=16+5;
|
sl@0
|
1087 |
if ((numberOfResources>0) &&
|
sl@0
|
1088 |
!(iFlagsAndNumberOfResources &
|
sl@0
|
1089 |
EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode))
|
sl@0
|
1090 |
{
|
sl@0
|
1091 |
const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
|
sl@0
|
1092 |
bitArrayOfResourcesContainingCompressedUnicode=
|
sl@0
|
1093 |
HBufC8::NewLC(lengthOfBitArrayInBytes);
|
sl@0
|
1094 |
TPtr8 asWritable(bitArrayOfResourcesContainingCompressedUnicode->Des());
|
sl@0
|
1095 |
ReadL(16+5,asWritable,lengthOfBitArrayInBytes);
|
sl@0
|
1096 |
dictionaryCompressionData.iStartOfDictionaryData+=lengthOfBitArrayInBytes;
|
sl@0
|
1097 |
}
|
sl@0
|
1098 |
ReadL(dictionaryCompressionData.iStartOfResourceData-2,temp,2);
|
sl@0
|
1099 |
const TInt numberOfBitsOfDictionaryData=LittleEndianTwoByteIntegerL(temp,0);
|
sl@0
|
1100 |
dictionaryCompressionData.iStartOfDictionaryIndex=
|
sl@0
|
1101 |
dictionaryCompressionData.iStartOfDictionaryData+
|
sl@0
|
1102 |
((numberOfBitsOfDictionaryData+7)/8);
|
sl@0
|
1103 |
dictionaryCompressionData.iNumberOfDictionaryEntries=
|
sl@0
|
1104 |
(dictionaryCompressionData.iStartOfResourceData-
|
sl@0
|
1105 |
dictionaryCompressionData.iStartOfDictionaryIndex)/2;
|
sl@0
|
1106 |
//the bottom 3 bits of firstByteAfterUids stores the number of bits used for
|
sl@0
|
1107 |
//dictionary tokens as an offset from 3, e.g. if 2 is stored in these three bits
|
sl@0
|
1108 |
//then the number of bits per dictionary token would be 3+2=5 - this allows a
|
sl@0
|
1109 |
//range of 3-11 bits per dictionary token (the maximum number of dictionary
|
sl@0
|
1110 |
//tokens therefore ranging from 8-2048) - the spec currently only supports 5-9
|
sl@0
|
1111 |
//bits per dictionary token, however
|
sl@0
|
1112 |
dictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens=
|
sl@0
|
1113 |
3 + (firstByteAfterUids & 0x07);
|
sl@0
|
1114 |
if ((numberOfResources>0) &&
|
sl@0
|
1115 |
(iFlagsAndNumberOfResources &
|
sl@0
|
1116 |
EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode))
|
sl@0
|
1117 |
{
|
sl@0
|
1118 |
bitArrayOfResourcesContainingCompressedUnicode=
|
sl@0
|
1119 |
DictionaryDecompressedResourceDataLC(
|
sl@0
|
1120 |
0,
|
sl@0
|
1121 |
iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),
|
sl@0
|
1122 |
dictionaryCompressionData,
|
sl@0
|
1123 |
KNullDesC16);
|
sl@0
|
1124 |
}
|
sl@0
|
1125 |
}
|
sl@0
|
1126 |
}
|
sl@0
|
1127 |
else
|
sl@0
|
1128 |
{
|
sl@0
|
1129 |
assert_obj.AssertDebL((iExtra->iFileSize + iExtra->iFileOffset) > 2, EBafPanicFileSize);
|
sl@0
|
1130 |
// This format of resource file is likely to be used for non-ROM resource files,
|
sl@0
|
1131 |
//so cache the resource-index (in iIndex) to minimize disk access.
|
sl@0
|
1132 |
// Ignore the flags in non-dictionary-compressed resource files - they are to
|
sl@0
|
1133 |
//be used only by a dictionary-compressing program rather than to be used directly
|
sl@0
|
1134 |
//by Bafl when reading non-dictionary-compressed resource files (as output by Rcomp).
|
sl@0
|
1135 |
const TInt KMaximumNumberOfBytesCached=256;
|
sl@0
|
1136 |
TBuf8<KMaximumNumberOfBytesCached> cache;
|
sl@0
|
1137 |
const TInt numberOfBytesCached=Min(iExtra->iFileSize,KMaximumNumberOfBytesCached);
|
sl@0
|
1138 |
ReadL(iExtra->iFileSize-numberOfBytesCached,cache,numberOfBytesCached);
|
sl@0
|
1139 |
assert_obj.AssertDebL(cache.Length()==numberOfBytesCached, EBafPanicBadCacheLength);
|
sl@0
|
1140 |
const TInt positionOfStartOfIndex=
|
sl@0
|
1141 |
((cache[numberOfBytesCached-1]<<8) | cache[numberOfBytesCached-2]);
|
sl@0
|
1142 |
const TInt numberOfBytesOfIndex=iExtra->iFileSize-positionOfStartOfIndex;
|
sl@0
|
1143 |
assert_obj.AssertDebL(numberOfBytesOfIndex%2==0, EBafPanicIndexIsOddNumberOfBytes);
|
sl@0
|
1144 |
assert_obj.AssertDebL(numberOfBytesOfIndex>=0, EBafPanicNegativeNumber);
|
sl@0
|
1145 |
const TInt numberOfBytesOfIndexStillToRetrieve=
|
sl@0
|
1146 |
numberOfBytesOfIndex-numberOfBytesCached;
|
sl@0
|
1147 |
if (numberOfBytesOfIndexStillToRetrieve<=0)
|
sl@0
|
1148 |
{
|
sl@0
|
1149 |
const TPtrC8 indexAsBinaryBuffer(cache.Right(numberOfBytesOfIndex));
|
sl@0
|
1150 |
iIndex=HBufC16::NewMaxL(numberOfBytesOfIndex/2);
|
sl@0
|
1151 |
//indexAsBinaryBuffer.Ptr() may not be 2-byte aligned, hence why we can't do
|
sl@0
|
1152 |
//iIndex=TPtrC16(REINTERPRET_CAST(const TUint16*,indexAsBinaryBuffer.Ptr()),
|
sl@0
|
1153 |
//numberOfBytesOfIndex/2).AllocL()
|
sl@0
|
1154 |
Mem::Copy(CONST_CAST(TUint16*,iIndex->Ptr()),indexAsBinaryBuffer.Ptr(),
|
sl@0
|
1155 |
numberOfBytesOfIndex);
|
sl@0
|
1156 |
}
|
sl@0
|
1157 |
else
|
sl@0
|
1158 |
{
|
sl@0
|
1159 |
HBufC16* const index=HBufC16::NewMaxLC(numberOfBytesOfIndex/2);
|
sl@0
|
1160 |
TPtr8 indexAsWritableBinaryBuffer(REINTERPRET_CAST(TUint8*,CONST_CAST
|
sl@0
|
1161 |
(TUint16*,index->Ptr())),numberOfBytesOfIndex);
|
sl@0
|
1162 |
ReadL(positionOfStartOfIndex,indexAsWritableBinaryBuffer,
|
sl@0
|
1163 |
numberOfBytesOfIndexStillToRetrieve);
|
sl@0
|
1164 |
assert_obj.AssertDebL(
|
sl@0
|
1165 |
indexAsWritableBinaryBuffer.Length()==numberOfBytesOfIndexStillToRetrieve,
|
sl@0
|
1166 |
EBafPanicBadIndexLength1);
|
sl@0
|
1167 |
indexAsWritableBinaryBuffer.Append(cache);
|
sl@0
|
1168 |
assert_obj.AssertDebL(indexAsWritableBinaryBuffer.Length()==numberOfBytesOfIndex,
|
sl@0
|
1169 |
EBafPanicBadIndexLength2);
|
sl@0
|
1170 |
assert_obj.AssertDebL(indexAsWritableBinaryBuffer.Length()==index->Length()*2,
|
sl@0
|
1171 |
EBafPanicBadIndexLength3);
|
sl@0
|
1172 |
iIndex=index;
|
sl@0
|
1173 |
CleanupStack::Pop(index);
|
sl@0
|
1174 |
}
|
sl@0
|
1175 |
//"-1" because the last thing in the index (which is in fact the last thing in the
|
sl@0
|
1176 |
//file itself) is the position of the start of the index which is therefore not
|
sl@0
|
1177 |
//pointing to a resource
|
sl@0
|
1178 |
numberOfResources=(numberOfBytesOfIndex/2) - 1;
|
sl@0
|
1179 |
if ((numberOfResources>0) &&
|
sl@0
|
1180 |
(iFlagsAndNumberOfResources & EFlagPotentiallyContainsCompressedUnicode))
|
sl@0
|
1181 |
{
|
sl@0
|
1182 |
const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
|
sl@0
|
1183 |
bitArrayOfResourcesContainingCompressedUnicode=
|
sl@0
|
1184 |
HBufC8::NewLC(lengthOfBitArrayInBytes);
|
sl@0
|
1185 |
TPtr8 bitArray(bitArrayOfResourcesContainingCompressedUnicode->Des());
|
sl@0
|
1186 |
//"16+1+2": 16 bytes of checked-UID + 1 byte of flags (these flags are for a
|
sl@0
|
1187 |
//dictionary-compressing program's use rather than directly for Bafl's use,
|
sl@0
|
1188 |
//so we ignore them) + 2 bytes containing the size of the largest resource when
|
sl@0
|
1189 |
//uncompressed
|
sl@0
|
1190 |
ReadL(16+1+2,bitArray,lengthOfBitArrayInBytes);
|
sl@0
|
1191 |
}
|
sl@0
|
1192 |
}
|
sl@0
|
1193 |
assert_obj.AssertDebL((numberOfResources & EAllFlags)==0, EBafPanicBadNumberOfResources);
|
sl@0
|
1194 |
assert_obj.AssertDebL((iFlagsAndNumberOfResources & ~EAllFlags)==0,
|
sl@0
|
1195 |
EBafPanicBadInitialization2);
|
sl@0
|
1196 |
iFlagsAndNumberOfResources |= (numberOfResources & ~EAllFlags);
|
sl@0
|
1197 |
iExtra->iUidType = uidType;
|
sl@0
|
1198 |
iExtra->iBitArrayOfResourcesContainingCompressedUnicode = bitArrayOfResourcesContainingCompressedUnicode;
|
sl@0
|
1199 |
iExtra->iDictionaryCompressionData = dictionaryCompressionData;
|
sl@0
|
1200 |
if (bitArrayOfResourcesContainingCompressedUnicode!=NULL)
|
sl@0
|
1201 |
{
|
sl@0
|
1202 |
CleanupStack::Pop(bitArrayOfResourcesContainingCompressedUnicode);
|
sl@0
|
1203 |
}
|
sl@0
|
1204 |
//iOffset is set by calling ConfirmSignatureL
|
sl@0
|
1205 |
assert_obj.AssertDebL(iOffset==0, EBafPanicBadInitialization3);
|
sl@0
|
1206 |
}
|