Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * The Contents of this file are made available subject to the terms of
5 : : * either of the following licenses
6 : : *
7 : : * - GNU Lesser General Public License Version 2.1
8 : : * - Sun Industry Standards Source License Version 1.1
9 : : *
10 : : * Sun Microsystems Inc., October, 2000
11 : : *
12 : : * GNU Lesser General Public License Version 2.1
13 : : * =============================================
14 : : * Copyright 2000 by Sun Microsystems, Inc.
15 : : * 901 San Antonio Road, Palo Alto, CA 94303, USA
16 : : *
17 : : * This library is free software; you can redistribute it and/or
18 : : * modify it under the terms of the GNU Lesser General Public
19 : : * License version 2.1, as published by the Free Software Foundation.
20 : : *
21 : : * This library is distributed in the hope that it will be useful,
22 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : : * Lesser General Public License for more details.
25 : : *
26 : : * You should have received a copy of the GNU Lesser General Public
27 : : * License along with this library; if not, write to the Free Software
28 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 : : * MA 02111-1307 USA
30 : : *
31 : : *
32 : : * Sun Industry Standards Source License Version 1.1
33 : : * =================================================
34 : : * The contents of this file are subject to the Sun Industry Standards
35 : : * Source License Version 1.1 (the "License"); You may not use this file
36 : : * except in compliance with the License. You may obtain a copy of the
37 : : * License at http://www.openoffice.org/license.html.
38 : : *
39 : : * Software provided under this License is provided on an "AS IS" basis,
40 : : * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
41 : : * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
42 : : * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
43 : : * See the License for the specific provisions governing your rights and
44 : : * obligations concerning the Software.
45 : : *
46 : : * The Initial Developer of the Original Code is: IBM Corporation
47 : : *
48 : : * Copyright: 2008 by IBM Corporation
49 : : *
50 : : * All Rights Reserved.
51 : : *
52 : : * Contributor(s): _______________________________________
53 : : *
54 : : *
55 : : ************************************************************************/
56 : : #include "first.hxx"
57 : : #include "assert.h"
58 : : namespace OpenStormBento
59 : : {
60 : :
61 : : BenError
62 : 12 : CBenTOCReader::ReadLabelAndTOC()
63 : : {
64 : : BenError Err;
65 : :
66 : : unsigned long TOCOffset;
67 [ + - ][ - + ]: 12 : if ((Err = ReadLabel(&TOCOffset, &cTOCSize)) != BenErr_OK)
68 : 0 : return Err;
69 : :
70 [ + - ][ - + ]: 12 : if ((Err = cpContainer->SeekToPosition(TOCOffset)) != BenErr_OK)
71 : 0 : return Err;
72 : :
73 [ + - ]: 12 : cpTOC = new BenByte[cTOCSize];
74 [ + - ][ - + ]: 12 : if ((Err = cpContainer->ReadKnownSize(cpTOC, cTOCSize)) != BenErr_OK)
75 : 0 : return Err;
76 : :
77 [ + - ][ - + ]: 12 : if ((Err = ReadTOC()) != BenErr_OK)
78 : 0 : return Err;
79 : :
80 : 12 : return BenErr_OK;
81 : : }
82 : :
83 : : BenError
84 : 12 : CBenTOCReader::ReadLabel(unsigned long * pTOCOffset, unsigned long * pTOCSize)
85 : : {
86 : : // If seek fails, then probably because stream is smaller than
87 : : // BEN_LABEL_SIZE and thus can't be Bento container
88 : : BenError Err;
89 [ + - ][ - + ]: 12 : if ((Err = cpContainer->SeekFromEnd(-BEN_LABEL_SIZE)) != BenErr_OK)
90 : 0 : return BenErr_NotBentoContainer;
91 : :
92 : : BenByte Label[BEN_LABEL_SIZE];
93 [ + - ][ - + ]: 12 : if ((Err = cpContainer->ReadKnownSize(Label, BEN_LABEL_SIZE)) != BenErr_OK)
94 : 0 : return Err;
95 : :
96 [ - + ]: 12 : if (memcmp(Label, gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) != 0)
97 [ # # ][ # # ]: 0 : if ((Err = SearchForLabel(Label)) != BenErr_OK)
98 : 0 : return Err;
99 : :
100 : 12 : BenByte * pCurrLabel = Label + BEN_MAGIC_BYTES_SIZE;
101 : :
102 : : #ifndef NDEBUG
103 : : BenWord Flags =
104 : : #endif
105 : 12 : UtGetIntelWord(pCurrLabel); pCurrLabel += 2; // Flags
106 : : // Newer files are 0x0101--indicates if big or little endian. Older
107 : : // files are 0x0 for flags
108 : : assert(Flags == 0x0101 || Flags == 0x0);
109 : :
110 : 12 : cBlockSize = UtGetIntelWord(pCurrLabel) * 1024; pCurrLabel += 2;
111 : :
112 : : // Check major version
113 [ - + ]: 12 : if (UtGetIntelWord(pCurrLabel) != BEN_CURR_MAJOR_VERSION)
114 : 0 : return BenErr_UnknownBentoFormatVersion;
115 : 12 : pCurrLabel += 2;
116 : :
117 : 12 : UtGetIntelWord(pCurrLabel); pCurrLabel += 2; // Minor version
118 : :
119 : 12 : *pTOCOffset = UtGetIntelDWord(pCurrLabel); pCurrLabel += 4;
120 : 12 : *pTOCSize = UtGetIntelDWord(pCurrLabel);
121 : :
122 : : assert(pCurrLabel + 4 == Label + BEN_LABEL_SIZE);
123 : :
124 : 12 : return BenErr_OK;
125 : : }
126 : :
127 : : #define LABEL_READ_BUFFER_SIZE 500
128 : : #define MAX_SEARCH_AMOUNT 1024 * 1024
129 : :
130 : : BenError
131 : 0 : CBenTOCReader::SearchForLabel(BenByte * pLabel)
132 : : {
133 : : BenError Err;
134 : :
135 : : sal_uLong Length;
136 [ # # ][ # # ]: 0 : if ((Err = cpContainer->GetSize(&Length)) != BenErr_OK)
137 : 0 : return Err;
138 : :
139 : : // Always ready to check for MagicBytes from
140 : : // CurrOffset - BEN_MAGIC_BYTES_SIZE to CurrOffset - 1
141 : : unsigned long CurrOffset = Length - BEN_LABEL_SIZE + BEN_MAGIC_BYTES_SIZE -
142 : 0 : 1;
143 : :
144 : : char Buffer[LABEL_READ_BUFFER_SIZE];
145 : :
146 : 0 : unsigned long BufferStartOffset = Length; // Init to big value
147 : :
148 [ # # ]: 0 : while (CurrOffset >= BEN_MAGIC_BYTES_SIZE)
149 : : {
150 : : // Don't search backwards more than 1 meg
151 [ # # ]: 0 : if (Length - CurrOffset > MAX_SEARCH_AMOUNT)
152 : 0 : break;
153 : :
154 : :
155 : : // If before beginning of buffer
156 [ # # ]: 0 : if (CurrOffset - BEN_MAGIC_BYTES_SIZE < BufferStartOffset)
157 : : {
158 : : unsigned long UsedBufferSize;
159 [ # # ]: 0 : if (CurrOffset < LABEL_READ_BUFFER_SIZE)
160 : 0 : UsedBufferSize = CurrOffset;
161 : 0 : else UsedBufferSize = LABEL_READ_BUFFER_SIZE;
162 : :
163 [ # # ][ # # ]: 0 : if ((Err = cpContainer->SeekToPosition(CurrOffset - UsedBufferSize))
164 : : != BenErr_OK)
165 : 0 : return Err;
166 : :
167 [ # # ][ # # ]: 0 : if ((Err = cpContainer->ReadKnownSize(Buffer, UsedBufferSize)) !=
168 : : BenErr_OK)
169 : 0 : return Err;
170 : :
171 : 0 : BufferStartOffset = CurrOffset - UsedBufferSize;
172 : : }
173 : :
174 [ # # ]: 0 : if (memcmp(Buffer + (CurrOffset - BEN_MAGIC_BYTES_SIZE -
175 : 0 : BufferStartOffset), gsBenMagicBytes, BEN_MAGIC_BYTES_SIZE) == 0)
176 : : {
177 [ # # ][ # # ]: 0 : if ((Err = cpContainer->SeekToPosition(CurrOffset -
178 : 0 : BEN_MAGIC_BYTES_SIZE)) != BenErr_OK)
179 : 0 : return Err;
180 : :
181 [ # # ]: 0 : return cpContainer->ReadKnownSize(pLabel, BEN_LABEL_SIZE);
182 : : }
183 : :
184 : 0 : --CurrOffset;
185 : : }
186 : :
187 : 0 : return BenErr_NotBentoContainer; // Didn't find magic bytes
188 : : }
189 : :
190 : : BenError
191 : 12 : CBenTOCReader::ReadTOC()
192 : : {
193 : : BenError Err;
194 : 12 : BenByte LookAhead = GetCode();
195 : 12 : BenGeneration Generation = 0;
196 : :
197 : : // Read in all objects
198 [ + + ]: 702 : while (LookAhead == BEN_NEW_OBJECT)
199 : : {
200 : : BenObjectID ObjectID;
201 [ - + ]: 690 : if ((Err = GetDWord(&ObjectID)) != BenErr_OK)
202 : 0 : return Err;
203 : 690 : pCBenObject pObject = NULL;
204 : :
205 : : // Read in all properties for object
206 [ + + ]: 831 : do
207 : : {
208 : : BenObjectID PropertyID;
209 : :
210 [ - + ]: 831 : if ((Err = GetDWord(&PropertyID)) != BenErr_OK)
211 : 0 : return Err;
212 : 831 : pCBenProperty pProperty = NULL;
213 : :
214 : : // Read in all values for property
215 [ - + ]: 831 : do
216 : : {
217 : 831 : BenObjectID ReferencedListID = 0;
218 : :
219 : : BenObjectID TypeID;
220 [ - + ]: 831 : if ((Err = GetDWord(&TypeID)) != BenErr_OK)
221 : 0 : return Err;
222 : 831 : LookAhead = GetCode();
223 : :
224 [ + + ]: 831 : if (LookAhead == BEN_EXPLICIT_GEN)
225 : : {
226 [ - + ]: 21 : if ((Err = GetDWord(&Generation)) != BenErr_OK)
227 : 0 : return Err;
228 : 21 : LookAhead = GetCode();
229 : : }
230 : :
231 [ + + ]: 831 : if (LookAhead == BEN_REFERENCE_LIST_ID)
232 : : {
233 : : // Eat it, unless BENUTIL_SUPPORT turned on
234 [ - + ]: 90 : if ((Err = GetDWord(&ReferencedListID)) != BenErr_OK)
235 : 0 : return Err;
236 : 90 : LookAhead = GetCode();
237 : : }
238 : :
239 [ + + ][ + + ]: 831 : if (PropertyID == BEN_PROPID_GLOBAL_PROPERTY_NAME ||
240 : : PropertyID == BEN_PROPID_GLOBAL_TYPE_NAME)
241 : : {
242 : : // Read property or type name
243 : :
244 [ + - ][ + - ]: 162 : if (pObject != NULL || TypeID != BEN_TYPEID_7_BIT_ASCII ||
[ - + ]
245 : : LookAhead != BEN_OFFSET4_LEN4)
246 : 0 : return BenErr_NamedObjectError;
247 : :
248 : : BenContainerPos Pos;
249 : : unsigned long Length;
250 : :
251 [ - + ]: 162 : if ((Err = GetDWord(&Pos)) != BenErr_OK)
252 : 0 : return Err;
253 [ - + ]: 162 : if ((Err = GetDWord(&Length)) != BenErr_OK)
254 : 0 : return Err;
255 : 162 : LookAhead = GetCode();
256 : :
257 [ - + ][ + - ]: 162 : if ((Err = cpContainer->SeekToPosition(Pos)) != BenErr_OK)
258 : 0 : return Err;
259 : :
260 : : #define STACK_BUFFER_SIZE 256
261 : : char sStackBuffer[STACK_BUFFER_SIZE];
262 : : char * sAllocBuffer;
263 : : char * sBuffer;
264 [ - + ]: 162 : if (Length > STACK_BUFFER_SIZE)
265 : : {
266 [ # # ]: 0 : sBuffer = new char[Length];
267 : 0 : sAllocBuffer = sBuffer;
268 : : }
269 : : else
270 : : {
271 : 162 : sBuffer = sStackBuffer;
272 : 162 : sAllocBuffer = NULL;
273 : : }
274 : :
275 [ + - ][ - + ]: 162 : if ((Err = cpContainer->ReadKnownSize(sBuffer, Length)) !=
276 : : BenErr_OK)
277 : : {
278 [ # # ]: 0 : delete[] sAllocBuffer;
279 : 0 : return Err;
280 : : }
281 : :
282 : : pCBenNamedObjectListElmt pPrevNamedObjectListElmt;
283 [ - + ]: 162 : if (FindNamedObject(cpContainer->GetNamedObjects(),
284 [ + - ]: 162 : sBuffer, &pPrevNamedObjectListElmt) != NULL)
285 : : {
286 [ # # ]: 0 : delete[] sAllocBuffer;
287 : 0 : return BenErr_DuplicateName;
288 : : }
289 : :
290 : : pCBenObject pPrevObject = (pCBenObject) cpContainer->
291 : 162 : GetObjects()->GetLast();
292 : :
293 [ + + ]: 162 : if (PropertyID == BEN_PROPID_GLOBAL_PROPERTY_NAME)
294 : : pObject = new CBenPropertyName(cpContainer, ObjectID,
295 [ + - ][ + - ]: 132 : pPrevObject, sBuffer, pPrevNamedObjectListElmt);
296 : : else pObject = new CBenTypeName(cpContainer, ObjectID,
297 [ + - ][ + - ]: 30 : pPrevObject, sBuffer, pPrevNamedObjectListElmt);
298 : :
299 [ - + ]: 162 : delete[] sAllocBuffer;
300 : : }
301 : : // If BENUTIL_SUPPORT turned on, read in references object
302 : : // like regular object
303 : : #ifndef BENUTIL_SUPPORT
304 [ + + ]: 669 : else if (PropertyID == BEN_PROPID_OBJ_REFERENCES)
305 : : {
306 : : // Don't need to read in references object--we assume
307 : : // that all references use object ID as key
308 [ + - ][ - + ]: 90 : if ((Err = ReadSegments(NULL, &LookAhead)) != BenErr_OK)
309 : 0 : return Err;
310 : : }
311 : : #endif
312 [ + + ]: 579 : else if (ObjectID == BEN_OBJID_TOC)
313 : : {
314 [ + + ]: 60 : if (PropertyID == BEN_PROPID_TOC_SEED)
315 : : {
316 [ + - ][ - + ]: 12 : if (TypeID != BEN_TYPEID_TOC_TYPE ||
317 : : LookAhead != BEN_IMMEDIATE4)
318 : 0 : return BenErr_TOCSeedError;
319 : :
320 : : BenDWord Data;
321 [ - + ]: 12 : if ((Err = GetDWord(&Data)) != BenErr_OK)
322 : 0 : return Err;
323 : 12 : LookAhead = GetCode();
324 : :
325 : 12 : cpContainer->SetNextAvailObjectID(Data);
326 : : }
327 : : else
328 : : {
329 : : // Ignore the other BEN_OBJID_TOC properties
330 [ + - ][ - + ]: 48 : if ((Err = ReadSegments(NULL, &LookAhead)) != BenErr_OK)
331 : 0 : return Err;
332 : : }
333 : : }
334 : : else
335 : : {
336 [ - + ]: 519 : if (pProperty != NULL)
337 : 0 : return BenErr_PropertyWithMoreThanOneValue;
338 : :
339 [ + + ]: 519 : if (pObject == NULL)
340 : : pObject = new CBenObject(cpContainer, ObjectID,
341 [ + - ][ + - ]: 426 : (pCBenObject) cpContainer->GetObjects()->GetLast());
342 : :
343 : : pProperty = new CBenProperty(pObject, PropertyID, TypeID,
344 [ + - ][ + - ]: 519 : (pCBenProperty) pObject->GetProperties()->GetLast());
345 : :
346 : : #ifdef BENUTIL_SUPPORT
347 : : pProperty->UseValue()->
348 : : SetReferencedListObjectID(ReferencedListID);
349 : : #endif
350 : :
351 [ - + ][ + - ]: 519 : if ((Err = ReadSegments(pProperty->UseValue(),
352 : 519 : &LookAhead)) != BenErr_OK)
353 : 0 : return Err;
354 : : }
355 : : } while (LookAhead == BEN_NEW_TYPE);
356 : : } while (LookAhead == BEN_NEW_PROPERTY);
357 : : }
358 : :
359 [ + - ]: 12 : if (LookAhead == BEN_READ_PAST_END_OF_TOC)
360 : 12 : return BenErr_OK;
361 : 12 : else return BenErr_InvalidTOC;
362 : : }
363 : :
364 : : BenError
365 : 657 : CBenTOCReader::ReadSegments(pCBenValue pValue, BenByte * pLookAhead)
366 : : {
367 : : BenError Err;
368 : :
369 [ + + ][ + + ]: 1314 : while (*pLookAhead >= BEN_SEGMENT_CODE_START &&
[ + + ]
370 : : *pLookAhead <= BEN_SEGMENT_CODE_END)
371 : : {
372 [ - + ]: 657 : if ((Err = ReadSegment(pValue, pLookAhead)) !=
373 : : BenErr_OK)
374 : 0 : return Err;
375 : : }
376 : :
377 : 657 : return BenErr_OK;
378 : : }
379 : :
380 : : BenError
381 : 657 : CBenTOCReader::ReadSegment(pCBenValue pValue, BenByte * pLookAhead)
382 : : {
383 : : BenError Err;
384 : :
385 : 657 : UtBool Immediate = UT_FALSE;
386 : 657 : UtBool EightByteOffset = UT_FALSE;
387 : 657 : unsigned long Offset(0), Length(0);
388 : :
389 [ + - - - : 657 : switch (*pLookAhead)
- + - - ]
390 : : {
391 : : case BEN_CONT_OFFSET4_LEN4:
392 : : case BEN_OFFSET4_LEN4:
393 [ - + ]: 633 : if ((Err = GetDWord(&Offset)) != BenErr_OK)
394 : 0 : return Err;
395 [ - + ]: 633 : if ((Err = GetDWord(&Length)) != BenErr_OK)
396 : 0 : return Err;
397 : 633 : break;
398 : :
399 : : case BEN_IMMEDIATE0:
400 : 0 : Length = 0; Immediate = UT_TRUE;
401 : 0 : break;
402 : :
403 : : case BEN_IMMEDIATE1:
404 : 0 : Length = 1; Immediate = UT_TRUE;
405 : 0 : break;
406 : :
407 : : case BEN_IMMEDIATE2:
408 : 0 : Length = 2; Immediate = UT_TRUE;
409 : 0 : break;
410 : :
411 : : case BEN_IMMEDIATE3:
412 : 0 : Length = 3; Immediate = UT_TRUE;
413 : 0 : break;
414 : :
415 : : case BEN_CONT_IMMEDIATE4:
416 : : case BEN_IMMEDIATE4:
417 : 24 : Length = 4; Immediate = UT_TRUE;
418 : 24 : break;
419 : :
420 : : case BEN_CONT_OFFSET8_LEN4:
421 : : case BEN_OFFSET8_LEN4:
422 : 0 : EightByteOffset = UT_TRUE;
423 : 0 : break;
424 : :
425 : : default:
426 : 0 : return BenErr_OK;
427 : : }
428 : :
429 : : BenByte ImmData[4];
430 [ + + ][ + - ]: 657 : if (Immediate && Length != 0)
431 [ - + ]: 24 : if ((Err = GetData(ImmData, 4)) != BenErr_OK)
432 : 0 : return Err;
433 : :
434 : 657 : *pLookAhead = GetCode();
435 : :
436 [ - + ]: 657 : if (EightByteOffset)
437 : 0 : return BenErr_64BitOffsetNotSupported;
438 : :
439 [ + + ]: 657 : if (pValue != NULL)
440 : : {
441 [ + - ]: 519 : if (! Immediate)
442 [ + - ][ + - ]: 519 : new CBenValueSegment(pValue, Offset, Length);
443 [ # # ]: 0 : else if (Length != 0)
444 : : {
445 : : assert(Length <= 4);
446 [ # # ][ # # ]: 0 : new CBenValueSegment(pValue, ImmData, (unsigned short) Length);
447 : : }
448 : : }
449 : :
450 : 657 : return BenErr_OK;
451 : : }
452 : :
453 : : UtBool
454 : 5895 : CBenTOCReader::CanGetData(unsigned long Amt)
455 : : {
456 : 5895 : return cCurr + Amt <= cTOCSize;
457 : : }
458 : :
459 : : BenError
460 : 1806 : CBenTOCReader::GetByte(BenByte * pByte)
461 : : {
462 [ + + ]: 1806 : if (! CanGetData(1))
463 : 12 : return BenErr_ReadPastEndOfTOC;
464 : :
465 : 1794 : *pByte = UtGetIntelByte(cpTOC + cCurr);
466 : 1794 : ++cCurr;
467 : 1806 : return BenErr_OK;
468 : : }
469 : :
470 : : BenError
471 : 4065 : CBenTOCReader::GetDWord(BenDWord * pDWord)
472 : : {
473 [ - + ]: 4065 : if (! CanGetData(4))
474 : 0 : return BenErr_ReadPastEndOfTOC;
475 : :
476 : 4065 : *pDWord = UtGetIntelDWord(cpTOC + cCurr);
477 : 4065 : cCurr += 4;
478 : 4065 : return BenErr_OK;
479 : : }
480 : :
481 : : BenByte
482 : 1806 : CBenTOCReader::GetCode()
483 : : {
484 : : BenByte Code;
485 [ + - ][ + + ]: 1794 : do
[ + + ]
486 : : {
487 [ + + ]: 1806 : if (GetByte(&Code) != BenErr_OK)
488 : 12 : return BEN_READ_PAST_END_OF_TOC;
489 : :
490 [ + + ]: 1794 : if (Code == BEN_END_OF_BUFFER)
491 : : // Advance to next block
492 : : cCurr = cBlockSize * ((cCurr + (cBlockSize - 1)) /
493 : 21 : cBlockSize);
494 : : }
495 : : while (Code == BEN_NOOP || Code == BEN_END_OF_BUFFER);
496 : 1785 : return Code;
497 : : }
498 : :
499 : : BenError
500 : 24 : CBenTOCReader::GetData(BenDataPtr pBuffer, unsigned long Amt)
501 : : {
502 [ - + ]: 24 : if (! CanGetData(Amt))
503 : 0 : return BenErr_ReadPastEndOfTOC;
504 : :
505 : 24 : UtHugeMemcpy(pBuffer, cpTOC + cCurr, Amt);
506 : 24 : cCurr += Amt;
507 : 24 : return BenErr_OK;
508 : : }
509 : : }//end OpenStormBento namespace
510 : :
511 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|