|
1 /* |
|
2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * Note: This file may contain code to generate corrupt files for test purposes. |
|
16 * Such code is excluded from production builds by use of compiler defines; |
|
17 * it is recommended that such code should be removed if this code is ever published publicly. |
|
18 * generic base for all SIS binary large objects |
|
19 * |
|
20 */ |
|
21 |
|
22 |
|
23 /** |
|
24 @file |
|
25 @publishedPartner |
|
26 @released |
|
27 */ |
|
28 |
|
29 #ifndef __BLOB_H__ |
|
30 #define __BLOB_H__ |
|
31 |
|
32 #include <iostream> |
|
33 #include <algorithm> |
|
34 #include <assert.h> |
|
35 #include "utility_interface.h" |
|
36 |
|
37 #include "field.h" |
|
38 #include "exception.h" |
|
39 #include "utility.h" |
|
40 |
|
41 template <CSISFieldRoot::TFieldType FieldType> class CBlob : public CSISField <FieldType> |
|
42 { |
|
43 public: |
|
44 /** |
|
45 * Default constructor. |
|
46 */ |
|
47 CBlob (); |
|
48 /** |
|
49 * Copy constructor |
|
50 */ |
|
51 CBlob (const CBlob& aInitialiser); |
|
52 /** |
|
53 * Destructor |
|
54 */ |
|
55 virtual ~CBlob (); |
|
56 |
|
57 public: |
|
58 /** |
|
59 * Internalize the class |
|
60 * @param aFile File stream from where data needs to be read. |
|
61 * @param aContainerSize size of the content to be read. |
|
62 * @param aArrayType Type of the array |
|
63 */ |
|
64 virtual void Read (TSISStream& aFile, const CSISFieldRoot::TFieldSize& aContainerSize, const CSISFieldRoot::TFieldType aArrayType = CSISFieldRoot::ESISUndefined); |
|
65 /** |
|
66 * Externalize the class |
|
67 * @param aFile File stream to which the data needs to be written. |
|
68 * @param aIsArrayElement whether the structure is part of an array or not. |
|
69 */ |
|
70 virtual void Write (TSISStream& aFile, const bool aIsArrayElement) const; |
|
71 /** |
|
72 * Retrieves the size of the structure. |
|
73 * @param aInsideArray - whether the structure is part of an array or not. |
|
74 * @return byte count. |
|
75 */ |
|
76 virtual CSISFieldRoot::TFieldSize ByteCount (const bool aInsideArray) const; |
|
77 /** |
|
78 * Sets the size of the structure. |
|
79 * @param size - size of the structure. |
|
80 */ |
|
81 virtual void SetByteCount (const CSISFieldRoot::TFieldSize aSize); |
|
82 /** |
|
83 * Dump the entire content in hex format into the stream |
|
84 */ |
|
85 virtual void Dump (std::ostream& aStream, const int aLevel) const; |
|
86 /** |
|
87 * Checks if the structure is required or not. Used for externalizing |
|
88 * the class. If its a waste of space then we need not write this into |
|
89 * the file. |
|
90 */ |
|
91 virtual bool WasteOfSpace () const; |
|
92 /** |
|
93 * This function verifies the structure |
|
94 * @param aLanguage - language |
|
95 */ |
|
96 virtual void Verify (const TUint32 aLanguages) const; |
|
97 /** |
|
98 * Calculates CRC of the content |
|
99 * @param aCRC CRC value of the content |
|
100 * @param aIsArrayElement whether the structure is part of an array or not. |
|
101 */ |
|
102 virtual void CalculateCrc (TCRC& aCRC, const bool aIsArrayElement) const; |
|
103 /** |
|
104 * Class name |
|
105 */ |
|
106 virtual std::string Name () const; |
|
107 |
|
108 /** |
|
109 * Named destructor. Deletes the buffer and resets the state. |
|
110 */ |
|
111 void Dispose (); |
|
112 /** |
|
113 * Load the file into memory. |
|
114 * @param aFileName file name which needs to be loaded |
|
115 * @param size file size. |
|
116 */ |
|
117 void Load (const std::wstring& aFileName, TUint64* size = NULL); |
|
118 /** |
|
119 * @return data buffer |
|
120 */ |
|
121 const TUint8* Data () const; |
|
122 /** |
|
123 * @return data buffer |
|
124 */ |
|
125 TUint8* Data (); |
|
126 /** |
|
127 * Replace the existing data with this data. |
|
128 * @param aData data pointer |
|
129 * @param aSize size of data |
|
130 */ |
|
131 void Assign (const TUint8* aData, const CSISFieldRoot::TFieldSize aSize); |
|
132 /** |
|
133 * Append the data after the existing data. |
|
134 * @param aData data pointer |
|
135 * @param aSize size of data |
|
136 */ |
|
137 void Append (const TUint8* aData, const CSISFieldRoot::TFieldSize aSize); |
|
138 /** |
|
139 * Append the data before the existing data. |
|
140 * @param aData data pointer |
|
141 * @param aSize size of data |
|
142 */ |
|
143 void Prepend(const TUint8* aData, const CSISFieldRoot::TFieldSize aSize); |
|
144 /** |
|
145 * Delete the previous content and allocate the new memory |
|
146 * @param aData data pointer |
|
147 * @param aSize size of data |
|
148 */ |
|
149 void Alloc (const CSISFieldRoot::TFieldSize aSize); |
|
150 /** |
|
151 * Delete the previous content and allocate the new memory. |
|
152 * And also copy the content of the previous memory into the new memory |
|
153 * @param aData data pointer |
|
154 * @param aSize size of data |
|
155 */ |
|
156 void ReAlloc (const CSISFieldRoot::TFieldSize aSize); |
|
157 /** |
|
158 * @return data size. |
|
159 */ |
|
160 TUint64 Size () const; |
|
161 /** |
|
162 * Reset all the offset and data pointers. It does not delete any pointers. |
|
163 * Can be used in ownership transfer. |
|
164 */ |
|
165 TUint8* GiveAway (); |
|
166 /** |
|
167 * Compare the data for equality |
|
168 */ |
|
169 bool operator==(const CBlob& aBlob) const; |
|
170 /** |
|
171 * Adds the write the package details into the stream. |
|
172 * @param aStream - Stream in which the package entries need to be written. |
|
173 * @param aVerbose - If this option is set then detail description of pkg |
|
174 * will be written into the stream. |
|
175 */ |
|
176 void AddPackageEntry(std::wostream& aStream, bool aVerbose) const; |
|
177 |
|
178 private: |
|
179 void Duplicate (const CBlob <FieldType>& aInitialiser); |
|
180 |
|
181 private: |
|
182 TUint8* iData; |
|
183 CSISFieldRoot::TFieldSize iSize; |
|
184 }; |
|
185 |
|
186 |
|
187 |
|
188 template <CSISFieldRoot::TFieldType FieldType> inline |
|
189 CBlob <FieldType>::CBlob () : |
|
190 iData (NULL), |
|
191 iSize (0) |
|
192 { |
|
193 } |
|
194 |
|
195 |
|
196 template <CSISFieldRoot::TFieldType FieldType> inline |
|
197 CBlob <FieldType>::CBlob (const CBlob <FieldType>& aInitialiser) : |
|
198 CSISField <FieldType> (aInitialiser), |
|
199 iData (NULL), |
|
200 iSize (0) |
|
201 { |
|
202 Duplicate (aInitialiser); |
|
203 } |
|
204 |
|
205 |
|
206 template <CSISFieldRoot::TFieldType FieldType> inline |
|
207 void CBlob <FieldType>::Alloc (const CSISFieldRoot::TFieldSize aSize) |
|
208 { |
|
209 if (iSize != aSize) |
|
210 { |
|
211 Dispose (); |
|
212 if (aSize != 0) |
|
213 { |
|
214 iData = new TUint8 [aSize]; |
|
215 iSize = aSize; |
|
216 memset (iData, 0, iSize); |
|
217 } |
|
218 } |
|
219 } |
|
220 |
|
221 |
|
222 template <CSISFieldRoot::TFieldType FieldType> inline |
|
223 void CBlob <FieldType>::ReAlloc (const CSISFieldRoot::TFieldSize aSize) |
|
224 { |
|
225 if (aSize <= iSize) |
|
226 { |
|
227 return; |
|
228 } |
|
229 if (aSize == 0) |
|
230 { |
|
231 Dispose (); |
|
232 } |
|
233 else |
|
234 { |
|
235 TUint8* data = new TUint8 [aSize]; |
|
236 if (aSize > iSize) |
|
237 { |
|
238 memset (&data [iSize], 0, aSize - iSize); |
|
239 } |
|
240 memcpy (data, iData, std::min (aSize, iSize)); |
|
241 Dispose (); |
|
242 iData = data; |
|
243 iSize = aSize; |
|
244 } |
|
245 } |
|
246 |
|
247 |
|
248 template <CSISFieldRoot::TFieldType FieldType> |
|
249 void CBlob <FieldType>::Duplicate (const CBlob <FieldType>& aInitialiser) |
|
250 { |
|
251 try |
|
252 { |
|
253 Assign (aInitialiser.iData, aInitialiser.iSize); |
|
254 } |
|
255 catch (...) |
|
256 { |
|
257 iSize = 0; |
|
258 delete iData; |
|
259 iData = NULL; |
|
260 } |
|
261 } |
|
262 |
|
263 template <CSISFieldRoot::TFieldType FieldType> inline |
|
264 CBlob <FieldType>::~CBlob () |
|
265 { |
|
266 Dispose (); |
|
267 } |
|
268 |
|
269 template <CSISFieldRoot::TFieldType FieldType> |
|
270 void CBlob <FieldType>::Dispose () |
|
271 { |
|
272 delete [] iData; |
|
273 iData = NULL; |
|
274 iSize = 0; |
|
275 } |
|
276 |
|
277 template <CSISFieldRoot::TFieldType FieldType> |
|
278 void CBlob <FieldType>::Read (TSISStream& aFile, const TUint64& aContainerSize, const CSISFieldRoot::TFieldType aArrayType) |
|
279 { |
|
280 CSISHeader header (aArrayType); |
|
281 header.Read (aFile, aContainerSize, aArrayType); |
|
282 SetByteCount (header.DataSize ()); |
|
283 if (! WasteOfSpace ()) |
|
284 { |
|
285 assert (! IsBadWritePtr (iData, iSize)); |
|
286 aFile.read (iData, iSize); |
|
287 ReadFiller (aFile); |
|
288 } |
|
289 } |
|
290 |
|
291 template <CSISFieldRoot::TFieldType FieldType> |
|
292 void CBlob <FieldType>::Write (TSISStream& aFile, const bool aIsArrayElement) const |
|
293 { |
|
294 if (! WasteOfSpace ()) |
|
295 { |
|
296 #ifdef GENERATE_ERRORS |
|
297 if (CSISFieldRoot::IsBugToBeCreated (CSISFieldRoot::EBugInsaneBlob)) |
|
298 { |
|
299 CSISHeader (FieldType, rand ()).Write (aFile, aIsArrayElement); |
|
300 } |
|
301 else |
|
302 #endif // GENERATE_ERRORS |
|
303 { |
|
304 CSISHeader (FieldType, ByteCount (false)).Write (aFile, aIsArrayElement); |
|
305 } |
|
306 assert (! IsBadReadPtr (iData, iSize)); |
|
307 aFile.write (iData, iSize); |
|
308 WriteFiller (aFile); |
|
309 } |
|
310 } |
|
311 |
|
312 template <CSISFieldRoot::TFieldType FieldType> inline |
|
313 CSISFieldRoot::TFieldSize CBlob <FieldType>::ByteCount (const bool aInsideArray) const |
|
314 { |
|
315 return iSize; |
|
316 } |
|
317 |
|
318 template <CSISFieldRoot::TFieldType FieldType> inline |
|
319 void CBlob <FieldType>::SetByteCount (const CSISFieldRoot::TFieldSize aSize) |
|
320 { |
|
321 Alloc (aSize); |
|
322 } |
|
323 |
|
324 template <CSISFieldRoot::TFieldType FieldType> |
|
325 void CBlob <FieldType>::Dump (std::ostream& aStream, const int aLevel) const |
|
326 { |
|
327 aStream << iSize << ": "; |
|
328 const TUint64 size = 20; |
|
329 for (unsigned index = 0; index < std::min (size, iSize); index++) |
|
330 { |
|
331 #define HEX(x) (((x)<10)?((x)+'0'):((x)-10+'A')) |
|
332 aStream << static_cast <char> (HEX ((iData [index] >> 4) & 0xF)); |
|
333 aStream << static_cast <char> (HEX (iData [index] & 0xF)); |
|
334 #undef HEX |
|
335 } |
|
336 if (20 < iSize) |
|
337 { |
|
338 aStream << "..."; |
|
339 } |
|
340 } |
|
341 |
|
342 template <CSISFieldRoot::TFieldType FieldType> inline |
|
343 bool CBlob <FieldType>::WasteOfSpace () const |
|
344 { |
|
345 return ! Required () && (iSize == 0); |
|
346 } |
|
347 |
|
348 template <CSISFieldRoot::TFieldType FieldType> inline |
|
349 void CBlob <FieldType>::Verify (const TUint32 aLanguages) const |
|
350 { |
|
351 assert ((! iData) == (! iSize)); |
|
352 } |
|
353 |
|
354 template <CSISFieldRoot::TFieldType FieldType> |
|
355 void CBlob <FieldType>::CalculateCrc (TCRC& aCRC, const bool aIsArrayElement) const |
|
356 { |
|
357 if(!WasteOfSpace()) |
|
358 { |
|
359 CSISHeader (CSISFieldRoot::ESISBlob, iSize).CalculateCrc (aCRC, aIsArrayElement); |
|
360 CSISFieldRoot::DoPaddedCrc (aCRC, iData, iSize); |
|
361 } |
|
362 } |
|
363 |
|
364 |
|
365 template <CSISFieldRoot::TFieldType FieldType> |
|
366 void CBlob <FieldType>::Load (const std::wstring& aFileName, TUint64* aSize) |
|
367 { |
|
368 TUint64 blobSize; |
|
369 HANDLE file = OpenFileAndGetSize (aFileName, &blobSize); |
|
370 SetByteCount (blobSize); |
|
371 ReadAndCloseFile (file, blobSize, iData); |
|
372 if (aSize) |
|
373 { |
|
374 *aSize = blobSize; |
|
375 } |
|
376 } |
|
377 |
|
378 |
|
379 template <CSISFieldRoot::TFieldType FieldType> inline |
|
380 std::string CBlob <FieldType>::Name () const |
|
381 { |
|
382 return "Binary"; |
|
383 } |
|
384 |
|
385 template <CSISFieldRoot::TFieldType FieldType> inline |
|
386 const TUint8* CBlob <FieldType>::Data () const |
|
387 { |
|
388 return iData; |
|
389 } |
|
390 |
|
391 template <CSISFieldRoot::TFieldType FieldType> inline |
|
392 TUint8* CBlob <FieldType>::Data () |
|
393 { |
|
394 return iData; |
|
395 } |
|
396 |
|
397 template <CSISFieldRoot::TFieldType FieldType> |
|
398 void CBlob <FieldType>::Assign (const TUint8* aData, const CSISFieldRoot::TFieldSize aSize) |
|
399 { |
|
400 Alloc (aSize); |
|
401 if (aSize != 0) |
|
402 { |
|
403 memcpy (iData, aData, iSize); |
|
404 } |
|
405 } |
|
406 |
|
407 template <CSISFieldRoot::TFieldType FieldType> |
|
408 void CBlob <FieldType>::Append (const TUint8* aData, const CSISFieldRoot::TFieldSize aSize) |
|
409 { |
|
410 CSISFieldRoot::TFieldSize oldSize = iSize; |
|
411 ReAlloc (aSize + iSize); |
|
412 if (aSize > 0) |
|
413 { |
|
414 memcpy (&iData [oldSize], aData, aSize); |
|
415 } |
|
416 } |
|
417 |
|
418 template <CSISFieldRoot::TFieldType FieldType> |
|
419 void CBlob <FieldType>::Prepend (const TUint8* aData, const CSISFieldRoot::TFieldSize aSize) |
|
420 { |
|
421 |
|
422 if (aSize > 0) |
|
423 { |
|
424 |
|
425 TUint8* data = new TUint8[iSize + aSize]; |
|
426 memcpy(data, aData, aSize); |
|
427 memcpy(&(data[aSize]), iData, iSize); |
|
428 |
|
429 CSISFieldRoot::TFieldSize oldSize = iSize; |
|
430 |
|
431 Dispose(); |
|
432 iData = data; |
|
433 iSize = aSize + oldSize; |
|
434 |
|
435 } |
|
436 |
|
437 } |
|
438 |
|
439 template <CSISFieldRoot::TFieldType FieldType> |
|
440 TUint8* CBlob <FieldType>::GiveAway () |
|
441 { |
|
442 TUint8* data = iData; |
|
443 iData = NULL; |
|
444 iSize = 0; |
|
445 return data; |
|
446 } |
|
447 |
|
448 template <CSISFieldRoot::TFieldType FieldType> inline |
|
449 TUint64 CBlob <FieldType>::Size () const |
|
450 { |
|
451 return iSize; |
|
452 } |
|
453 |
|
454 |
|
455 template <CSISFieldRoot::TFieldType FieldType> inline |
|
456 bool CBlob <FieldType>::operator==(const CBlob& aBlob) const |
|
457 { |
|
458 // Return false if the size of the data in each blob doesn't match. |
|
459 if (iSize != aBlob.iSize) |
|
460 { |
|
461 return false; |
|
462 } |
|
463 |
|
464 // Compare the data |
|
465 return (!(memcmp(iData, aBlob.iData, iSize ))); |
|
466 |
|
467 } |
|
468 |
|
469 template <CSISFieldRoot::TFieldType FieldType> inline |
|
470 void CBlob <FieldType>::AddPackageEntry(std::wostream& aStream, bool aVerbose) const |
|
471 { |
|
472 if(aVerbose) |
|
473 { |
|
474 aStream << std::hex; |
|
475 for (TUint32 i=0; i<iSize; i++) |
|
476 { |
|
477 aStream.fill('0'); |
|
478 aStream.width(2); |
|
479 aStream << (iData[i] & 0xFF); |
|
480 } |
|
481 aStream.width(0); |
|
482 aStream << std::dec; |
|
483 } |
|
484 } |
|
485 |
|
486 #endif // __SISBLOB_H__ |