|
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 * As specified in SGL.GT0188.251 |
|
19 * |
|
20 */ |
|
21 |
|
22 |
|
23 /** |
|
24 @file |
|
25 @publishedPartner |
|
26 @released |
|
27 */ |
|
28 |
|
29 #ifndef __SISARRAY_H__ |
|
30 #define __SISARRAY_H__ |
|
31 |
|
32 #include "container.h" |
|
33 #include "element.h" |
|
34 |
|
35 #include <strstream> |
|
36 |
|
37 #define SisArrayMemSize(aType) ContainerMemSize(CElement <aType>, CSISFieldRoot::ESISArray) |
|
38 #define SisArrayMem(aType) ContainerMem(CElement <aType>, CSISFieldRoot::ESISArray) |
|
39 #define SisArrayIter(aType) ContainerIter(CElement <aType>) |
|
40 |
|
41 template <class T, CSISFieldRoot::TFieldType FieldType> class CSISArray : |
|
42 public CContainer <CElement <T>, CSISFieldRoot::ESISArray> |
|
43 { |
|
44 public: |
|
45 typedef CSISUInt32 TMemberCount; |
|
46 |
|
47 public: |
|
48 /** |
|
49 * Default Constructor |
|
50 */ |
|
51 CSISArray (); |
|
52 /** |
|
53 * Parameterised constructor. |
|
54 * @param - Tells if the structure is required or not. |
|
55 */ |
|
56 CSISArray (const bool aRequired); |
|
57 |
|
58 /** |
|
59 * Internalize the array content |
|
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 array content |
|
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 size); |
|
82 /** |
|
83 * Calculate CRC for this structure. |
|
84 * @param aCRC CRC value of the structure. |
|
85 * @param aIsArrayElement whether the structure is part of an array or not. |
|
86 */ |
|
87 virtual void CalculateCrc (TUint16& aCRC, const bool aIsArrayElement) const; |
|
88 /** |
|
89 * Class Name |
|
90 */ |
|
91 virtual std::string Name () const; |
|
92 /** |
|
93 * Adds package entry related to this structure. |
|
94 * @param aStream stream into which the package details need to be written. |
|
95 * @param aVerbose If this option is set then detail description of pkg |
|
96 * will be written into the stream. |
|
97 */ |
|
98 void AddPackageEntry(std::wostream& aStream, bool aVerbose) const; |
|
99 |
|
100 /** |
|
101 * Operator to access content of this array |
|
102 * @param aIndex index of the item to be retrieved. |
|
103 */ |
|
104 const T& operator [] (const SisArrayMemSize(T)& aIndex) const; |
|
105 /** |
|
106 * Operator to access content of this array |
|
107 * @param aIndex index of the item to be retrieved. |
|
108 */ |
|
109 T& operator [] (const SisArrayMemSize(T)& aIndex); |
|
110 |
|
111 /** |
|
112 * Adds the element into the array |
|
113 * @param aData element to be added into the array |
|
114 */ |
|
115 void Push (const T& aData); |
|
116 /** |
|
117 * Adds an empty element into the array |
|
118 */ |
|
119 void Push (); |
|
120 /** |
|
121 * Retrieves the last element of this array |
|
122 * @return array element |
|
123 */ |
|
124 const T& Last () const; |
|
125 /** |
|
126 * Retrieves the last element of this array |
|
127 * @return array element |
|
128 */ |
|
129 T& Last (); |
|
130 }; |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 template <class T, CSISFieldRoot::TFieldType FieldType> inline |
|
136 CSISArray <T, FieldType>::CSISArray () |
|
137 { |
|
138 } |
|
139 |
|
140 |
|
141 template <class T, CSISFieldRoot::TFieldType FieldType> inline |
|
142 CSISArray <T, FieldType>::CSISArray (const bool aRequired) : |
|
143 CContainer <CElement <T>, CSISFieldRoot::ESISArray> (aRequired) |
|
144 { |
|
145 } |
|
146 |
|
147 template <class T, CSISFieldRoot::TFieldType FieldType> |
|
148 void CSISArray <T, FieldType>::Read (TSISStream& aFile, const CSISFieldRoot::TFieldSize& aContainerSize, const CSISFieldRoot::TFieldType aArrayType) |
|
149 { |
|
150 SetPreHeaderPos (aFile.tell ()); |
|
151 |
|
152 CSISHeader header (aArrayType); |
|
153 if (! IsDataThere (aFile, header, aArrayType)) |
|
154 { |
|
155 if (! Required () && (header.DataSize () == 0)) |
|
156 { |
|
157 return; |
|
158 } |
|
159 throw CSISException (CSISException::EFileFormat, "Array expected"); |
|
160 } |
|
161 TSISStream::pos_type pos = aFile.tell (); |
|
162 |
|
163 SetPostHeaderPos (pos); |
|
164 |
|
165 TSISStream::pos_type done = aFile.tell () + static_cast <TSISStream::pos_type> (AlignedSize (header.DataSize ())); |
|
166 CSISFieldRoot::TFieldType type; |
|
167 aFile >> type; |
|
168 CSISException::ThrowIf (type != FieldType, CSISException::EFileFormat, "unexpected element type"); |
|
169 #ifdef _DEBUG |
|
170 pos = aFile.tell (); |
|
171 assert (done >= pos); |
|
172 #endif |
|
173 while (done > aFile.tell ()) |
|
174 { |
|
175 Push (T ()); |
|
176 Last ().Read (aFile, header.DataSize (), FieldType); |
|
177 ReadFiller (aFile); |
|
178 } |
|
179 #ifdef _DEBUG |
|
180 TSISStream::pos_type here = aFile.tell (); |
|
181 assert (done == here); |
|
182 #endif |
|
183 } |
|
184 |
|
185 template <class T, CSISFieldRoot::TFieldType FieldType> |
|
186 void CSISArray <T, FieldType>::Write (TSISStream& aFile, const bool aIsArrayElement) const |
|
187 { |
|
188 if (! WasteOfSpace ()) |
|
189 { |
|
190 #ifdef _DEBUG |
|
191 TSISStream::pos_type before = aFile.tell (); |
|
192 #endif |
|
193 #ifdef GENERATE_ERRORS |
|
194 bool arrLenBug; |
|
195 if (arrLenBug = CSISFieldRoot::IsBugToBeCreated (CSISFieldRoot::EBugArrayCount)) |
|
196 { |
|
197 CSISHeader (CSISFieldRoot::ESISArray, rand ()).Write (aFile, aIsArrayElement); |
|
198 } |
|
199 else |
|
200 #endif // GENERATE_ERRORS |
|
201 { |
|
202 CSISHeader (CSISFieldRoot::ESISArray, ByteCount (true)).Write (aFile, aIsArrayElement); |
|
203 } |
|
204 #ifdef _DEBUG |
|
205 TSISStream::pos_type pos = aFile.tell (); |
|
206 TSISStream::pos_type expected = pos + static_cast <TSISStream::pos_type> (AlignedSize (ByteCount (true))); |
|
207 #endif |
|
208 aFile << FieldType; |
|
209 for (SisArrayIter(T) iterMemb = SisArrayMem(T).begin (); iterMemb != SisArrayMem(T).end (); iterMemb++) |
|
210 { |
|
211 (**iterMemb) -> Write (aFile, true); |
|
212 } |
|
213 TSISStream::pos_type beforeFiller = aFile.tell(); |
|
214 WriteFiller (aFile); |
|
215 #ifdef _DEBUG |
|
216 TSISStream::pos_type actual = aFile.tell (); |
|
217 |
|
218 #ifdef GENERATE_ERRORS |
|
219 if (! IsAnyBugSet ()) |
|
220 { |
|
221 assert (expected == actual); |
|
222 } |
|
223 else |
|
224 { |
|
225 if (expected != actual) |
|
226 { |
|
227 aFile.seek (before); |
|
228 // If we wanted to corrupt the array length, then we don't much care here. |
|
229 // if the length we expected is wrong |
|
230 if (!arrLenBug) |
|
231 { |
|
232 CSISHeader (CSISFieldRoot::ESISArray, beforeFiller - pos).Write (aFile, aIsArrayElement); |
|
233 } |
|
234 aFile.seek (actual); |
|
235 } |
|
236 } |
|
237 |
|
238 #else |
|
239 assert (expected == actual); |
|
240 #endif //GENERATE_ERRORS |
|
241 #endif // DEBUG |
|
242 } |
|
243 } |
|
244 |
|
245 template <class T, CSISFieldRoot::TFieldType FieldType> |
|
246 CSISFieldRoot::TFieldSize CSISArray<T, FieldType>::ByteCount (const bool aInsideArray) const |
|
247 { |
|
248 if (WasteOfSpace ()) |
|
249 { |
|
250 return 0; |
|
251 } |
|
252 return CSISUInt32 (FieldType).ByteCount (aInsideArray) + |
|
253 CContainer <CElement <T>, CSISFieldRoot::ESISArray>::ByteCount (true); |
|
254 } |
|
255 |
|
256 template <class T, CSISFieldRoot::TFieldType FieldType> |
|
257 void CSISArray <T, FieldType>::SetByteCount (const CSISFieldRoot::TFieldSize aSize) |
|
258 { |
|
259 CContainer <CElement <T>, CSISFieldRoot::ESISArray>::SetByteCount (aSize - CSISFieldRoot::SizeOfFieldType ()); |
|
260 } |
|
261 |
|
262 template <class T, CSISFieldRoot::TFieldType FieldType> |
|
263 void CSISArray <T, FieldType>::CalculateCrc (TCRC& aCRC, const bool aIsArrayElement) const |
|
264 { |
|
265 if(!WasteOfSpace()) |
|
266 { |
|
267 CSISHeader (CSISFieldRoot::ESISArray, ByteCount (false)).CalculateCrc (aCRC, aIsArrayElement); |
|
268 CSISUInt32 (FieldType).CalculateCrc (aCRC, false); |
|
269 CContainer <CElement <T>, CSISFieldRoot::ESISArray>::CalculateCrc (aCRC, true); |
|
270 } |
|
271 } |
|
272 |
|
273 template <class T, CSISFieldRoot::TFieldType FieldType> inline |
|
274 void CSISArray<T, FieldType>::Push (const T& aData) |
|
275 { |
|
276 T* ptr = new T (aData); |
|
277 try |
|
278 { |
|
279 CContainer <CElement <T>, CSISFieldRoot::ESISArray>::Push (new CElement <T> (ptr)); |
|
280 } |
|
281 catch (...) |
|
282 { |
|
283 delete ptr; |
|
284 throw; |
|
285 } |
|
286 } |
|
287 |
|
288 template <class T, CSISFieldRoot::TFieldType FieldType> inline |
|
289 void CSISArray<T, FieldType>::Push () |
|
290 { |
|
291 T* ptr = new T (); |
|
292 try |
|
293 { |
|
294 CContainer <CElement <T>, CSISFieldRoot::ESISArray>::Push (new CElement <T> (ptr)); |
|
295 } |
|
296 catch (...) |
|
297 { |
|
298 delete ptr; |
|
299 throw; |
|
300 } |
|
301 } |
|
302 |
|
303 template <class T, CSISFieldRoot::TFieldType FieldType> inline |
|
304 const T& CSISArray<T, FieldType>::Last () const |
|
305 { |
|
306 return * (CContainer <CElement <T>, CSISFieldRoot::ESISArray>::Last ()); |
|
307 } |
|
308 |
|
309 template <class T, CSISFieldRoot::TFieldType FieldType> inline |
|
310 T& CSISArray<T, FieldType>::Last () |
|
311 { |
|
312 return * (CContainer <CElement <T>, CSISFieldRoot::ESISArray>::Last ()); |
|
313 } |
|
314 |
|
315 template <class T, CSISFieldRoot::TFieldType FieldType> |
|
316 std::string CSISArray<T, FieldType>::Name () const |
|
317 { |
|
318 std::strstream brook; |
|
319 brook << "Array of " << size (); |
|
320 return std::string (brook.str (), brook.pcount ()); |
|
321 } |
|
322 |
|
323 template <class T, CSISFieldRoot::TFieldType FieldType> inline |
|
324 const T& CSISArray<T, FieldType>::operator [] (const SisArrayMemSize(T)& aIndex) const |
|
325 { |
|
326 return * (CContainer <CElement <T>, CSISFieldRoot::ESISArray>::operator [] (aIndex)); |
|
327 } |
|
328 |
|
329 template <class T, CSISFieldRoot::TFieldType FieldType> inline |
|
330 T& CSISArray<T, FieldType>::operator [] (const SisArrayMemSize(T)& aIndex) |
|
331 { |
|
332 return * (CContainer <CElement <T>, CSISFieldRoot::ESISArray>::operator [] (aIndex)); |
|
333 } |
|
334 |
|
335 template <class T, CSISFieldRoot::TFieldType FieldType> |
|
336 void CSISArray <T, FieldType>::AddPackageEntry(std::wostream& aStream, bool aVerbose) const |
|
337 { |
|
338 for (SisArrayIter(T) iterMemb = SisArrayMem(T).begin (); iterMemb != SisArrayMem(T).end (); iterMemb++) |
|
339 { |
|
340 (**iterMemb)->AddPackageEntry(aStream, aVerbose); |
|
341 } |
|
342 } |
|
343 |
|
344 #endif // __SISARRAY_H__ |
|
345 |