changed: gcc8 base update
[opensg.git] / Source / System / FileIO / OSB / OSGOSBRootElement.cpp
blobaa55feb743f297375f08258d161d9f614e69af20
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2007 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 #include "OSGOSBRootElement.h"
41 #include "OSGOSBElementFactory.h"
42 #include "OSGContainerPtrFuncs.h"
44 #include "OSGAttachmentContainer.h"
45 #include "OSGAttachment.h"
46 #include "OSGFieldContainerSFields.h"
48 OSG_USING_NAMESPACE
50 /*-------------------------------------------------------------------------*/
51 /* OSBRootElement */
52 /*-------------------------------------------------------------------------*/
54 /*! \class OSG::OSBRootElement
55 The root element is different from the other elements for it is not
56 responsible for loading a certain type of FieldContainer but instead holds
57 the shared state of the OSB IO subsystem. All elements (including the
58 root element itself) have a pointer to it and can access the shared state
59 through it.
62 /*-------------------------------------------------------------------------*/
63 /* Static members */
65 OSBElementRegistrationHelper<OSBRootElement>
66 OSBRootElement::_regHelper =
67 OSBElementRegistrationHelper<OSBRootElement>("RootElement");
69 /*-------------------------------------------------------------------------*/
70 /* Constructor */
72 /*! Constructor.
74 OSBRootElement::OSBRootElement(OSBRootElement * /* root */) :
75 Inherited (this, Inherited::OSGOSBHeaderVersion200),
77 _readHandler (NULL ),
78 _writeHandler (NULL ),
80 _options ( ),
81 _elements ( ),
82 _idElemMap ( ),
84 _readHeaderVersion(0 ),
85 _readIdMap ( ),
86 _readPtrFields ( ),
88 _writeFCList ( ),
89 _writeIdSet ( )
92 // nothing to do.
95 /*-------------------------------------------------------------------------*/
96 /* Destructor */
98 /*! Destructor.
100 OSBRootElement::~OSBRootElement(void)
102 // nothing to do.
105 /*-------------------------------------------------------------------------*/
106 /* Reading */
108 /*! Initializes this root element for a read operation from \a inStream.
109 This must be called before OSBRootElement::read(const std::string&).
111 \param[in] inStream Stream to read data from.
113 void
114 OSBRootElement::initialiseRead(std::istream &inStream)
116 _readHandler = new BinaryReadHandler(inStream);
118 _elements .clear();
119 _readIdMap .clear();
120 _readPtrFields.clear();
123 /*! Performs clean up tasks after a read operation. This must be called after
124 OSBRootElement::postRead(void).
126 void
127 OSBRootElement::terminateRead(void)
129 ElementListIt eI = editElementList().begin();
130 ElementListIt eE = editElementList().end ();
132 for(; eI != eE; ++eI)
134 OSBElementFactory::the()->release(*eI);
137 _elements .clear();
138 _readIdMap .clear();
139 _readPtrFields.clear();
141 delete _readHandler;
142 _readHandler = 0;
145 /*! Reads from the stream set by a preceding call to initialiseRead. Since the
146 root element is the first one created it reads the file header and
147 creates the elements to read the data following the header.
149 \param[in] typeName The argument is ignored.
151 void
152 OSBRootElement::read(const std::string &/*typeName*/)
154 OSG_OSB_LOG(("OSBRootElement::read\n"));
156 BinaryReadHandler *rh = getReadHandler();
157 std::string headerMarker;
159 rh->getValue(headerMarker);
161 if(headerMarker == OSGOSB_HEADER_ID_1)
163 OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
164 OSGOSBHeaderVersion100));
165 setHeaderVersion(OSGOSBHeaderVersion100);
167 else if(headerMarker == OSGOSB_HEADER_ID_2)
169 OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
170 OSGOSBHeaderVersion200));
171 setHeaderVersion(OSGOSBHeaderVersion200);
173 // else if(headerMarker == OSGOSB_HEADER_ID_201)
174 // {
175 // OSG_OSB_LOG(("OSBRootElement::read: Header version: [%u]\n",
176 // OSGOSBHeaderVersion201));
177 // setHeaderVersion(OSGOSBHeaderVersion201);
178 // }
179 else
181 FWARNING(("OSBRootElement::read: Unrecognized file header, could not "
182 "load file.\n"));
183 return;
186 std::string headerName;
187 rh->getValue(headerName);
188 std::string headerOptions;
189 rh->getValue(headerOptions);
190 UInt64 fileSize;
191 rh->getValue(fileSize);
193 OSG_OSB_LOG(("OSBRootElement::read: headerName: [%s]\n",
194 headerName.c_str()));
195 OSG_OSB_LOG(("OSBRootElement::read: headerOptions: [%s]\n",
196 headerOptions.c_str()));
197 OSG_OSB_LOG(("OSBRootElement::read: fileSize: [%" PRISize "]\n",
198 fileSize));
200 std::string fcTypeName;
201 UInt32 fcIdFile; // id used in the file
202 UInt32 fcIdSystem; // id used in the system
203 OSBElementBase *elem;
205 while(true)
207 if(!readFieldContainerHeader(fcTypeName, fcIdFile))
208 break;
210 OSG_OSB_LOG(("OSBRootElement::read: fcTypeName [%s] fcIdFile: [%u]\n",
211 fcTypeName.c_str(), fcIdFile));
213 elem = OSBElementFactory::the()->acquire(fcTypeName, this);
214 elem->setFCIdFile(fcIdFile );
215 elem->read (fcTypeName);
217 if(elem->getContainer() != NULL)
219 fcIdSystem = elem->getContainer()->getId();
221 OSG_OSB_LOG(("OSBRootElement::read: fcIdFile: [%u] fcIdSystem: [%u]\n",
222 fcIdFile, fcIdSystem));
224 editIdMap().insert(
225 FieldContainerIdMap::value_type(fcIdFile, fcIdSystem));
227 if(getContainer() == NULL)
229 setContainer(elem->getContainer());
232 editElementList().push_back(elem );
233 editIdElemMap ().insert (std::make_pair(fcIdFile, elem));
238 /*! Performs post processing for all elements created during the previous
239 call to read.
240 Specifically all these elements have their postRead function called and
241 afterwards pointer field remapping is performed. This process fills all
242 fields that hold pointers to FieldContainers with the correct values.
244 void
245 OSBRootElement::postRead(void)
247 OSG_OSB_LOG(("OSBRootElement::postRead\n"));
249 ElementListConstIt elemIt = getElementList().begin();
250 ElementListConstIt elemEnd = getElementList().end ();
252 for(; elemIt != elemEnd; ++elemIt)
254 (*elemIt)->postRead();
257 dumpIdMap();
259 PtrFieldListConstIt ptrFieldIt = getPtrFieldList().begin();
260 PtrFieldListConstIt ptrFieldEnd = getPtrFieldList().end ();
262 for(; ptrFieldIt != ptrFieldEnd; ++ptrFieldIt)
264 mapPtrField(*ptrFieldIt);
267 this->postMap();
270 void OSBRootElement::postMap(void)
272 OSG_OSB_LOG(("OSBRootElement::postMap\n"));
274 ElementListConstIt elemIt = getElementList().begin();
275 ElementListConstIt elemEnd = getElementList().end ();
277 for(; elemIt != elemEnd; ++elemIt)
279 (*elemIt)->postMap();
283 /*-------------------------------------------------------------------------*/
284 /* Writing */
286 /*! Initializes this root element for a write operation to \a outStream.
287 This must be called before
288 OSBRootElement::preWrite(const FieldContainerPtr&).
290 \param[in] outStream Stream to write data to.
292 void
293 OSBRootElement::initialiseWrite(std::ostream &outStream)
295 _writeHandler = new BinaryWriteHandler(outStream);
297 _writeFCList.clear();
298 _writeIdSet .clear();
301 /*! Performs clean up tasks after a write operation. This must be called after
302 OSBRootElement::write(void).
304 void
305 OSBRootElement::terminateWrite(void)
307 ElementListIt eI = editElementList().begin();
308 ElementListIt eE = editElementList().end ();
310 for(; eI != eE; ++eI)
312 OSBElementFactory::the()->release(*eI);
315 _elements .clear();
316 _writeFCList.clear();
317 _writeIdSet .clear();
319 _writeHandler->flush();
321 delete _writeHandler;
322 _writeHandler = 0;
325 /*! Collects all containers that are reachable from \a fc and schedules them
326 for writing. For each container an approriate element is created and
327 its preWrite method is called, thus recursively discovering all reachable
328 containers.
330 \param[in] fc FieldContainer that is inspected for reachable containers.
332 void
333 OSBRootElement::preWrite(FieldContainer * const fc)
335 OSG_OSB_LOG(("OSBRootElement::preWrite\n"));
337 if(fc == NULL)
338 return;
340 const std::string &typeName = fc->getType().getName();
341 OSBElementBase *elem = OSBElementFactory::the()->acquire(
342 typeName, this);
344 editElementList().push_back(elem);
345 elem->setContainer(fc );
346 elem->setFCIdFile (fc->getId());
347 elem->preWrite (fc );
350 /*! Writes the containers collected with the previous call to preWrite to the
351 stream set by initialiseWrite.
352 First the file header is written, then for each element created during
353 preWrite the write function is called.
355 void
356 OSBRootElement::write(void)
358 OSG_OSB_LOG(("OSBRootElement::write\n"));
360 BinaryWriteHandler *wh = getWriteHandler();
362 wh->putValue(OSGOSB_HEADER_ID_2 ); // version
363 wh->putValue(std::string("") ); // name
364 wh->putValue(std::string("") ); // options
365 wh->putValue(static_cast<UInt64>(0)); // size
367 ElementListConstIt elemIt = getElementList().begin();
368 ElementListConstIt elemEnd = getElementList().end ();
370 for(; elemIt != elemEnd; ++elemIt)
372 writeFieldContainerHeader((*elemIt)->getContainer());
373 (*elemIt)->write();
377 /*-------------------------------------------------------------------------*/
378 /* Helper methods */
380 /*! Fills the "pointer field" described by \a ptrField with the correct
381 pointers.
383 \param[in] ptrField Field to fill.
385 void
386 OSBRootElement::mapPtrField(const PtrFieldInfo &ptrField)
388 OSG_OSB_LOG(("OSBRootElement::mapPtrField\n"));
390 PtrFieldInfo::PtrIdStoreConstIt idIt = ptrField.beginIdStore();
391 PtrFieldInfo::PtrIdStoreConstIt idEnd = ptrField.endIdStore ();
393 PtrFieldInfo::BindingStoreConstIt bindingIt = ptrField.beginBindingStore();
394 PtrFieldInfo::BindingStoreConstIt bindingEnd = ptrField.endBindingStore ();
396 const FieldContainerIdMap &idMap = getIdMap();
397 FieldContainerIdMapConstIt idMapIt;
398 FieldContainerIdMapConstIt idMapEnd = idMap.end();
400 if(bindingIt != bindingEnd)
402 if(ptrField.getHandledField() == true)
404 FieldContainer *fieldCon = ptrField.getContainer();
405 UInt32 fieldId = ptrField.getFieldId();
407 EditFieldHandlePtr fHandle = fieldCon->editField(fieldId);
409 EditMapFieldHandlePtr sfMapField =
410 boost::dynamic_pointer_cast<EditMapFieldHandle>(fHandle);
412 if(sfMapField == NULL || sfMapField->isValid() == false)
413 return;
415 sfMapField->fillFrom(ptrField.getBindingStore(),
416 ptrField.getIdStore (),
417 idMap);
419 else
421 Attachment *att = NULL;
422 AttachmentContainer *attCon =
423 dynamic_cast<AttachmentContainer *>(ptrField.getContainer());
425 for(; (idIt != idEnd) && (bindingIt != bindingEnd); ++idIt,
426 ++bindingIt)
428 if(*idIt != 0)
430 idMapIt = idMap.find(*idIt);
432 if(idMapIt != idMapEnd)
434 att = dynamic_cast<Attachment *>(
435 FieldContainerFactory::the()->getContainer(
436 idMapIt->second));
438 else
440 FWARNING(("OSBRootElement::mapPtrField: could not find "
441 "FieldContainer with id [%u]\n", *idIt));
442 att = NULL;
445 else
447 att = NULL;
450 if(att != NULL)
452 OSG_OSB_LOG(("OSBRootElement::mapPtrField: adding "
453 "attchment [%u] [%u]\n",
454 att->getType().getGroupId(), *bindingIt));
457 attCon->addAttachment(att, *bindingIt);
461 else
463 FieldContainer *fc = NULL;
464 FieldContainer *fieldCon = ptrField.getContainer();
465 UInt32 fieldId = ptrField.getFieldId();
467 EditFieldHandlePtr fHandle = fieldCon->editField(fieldId);
469 FieldContainerPtrSFieldBase::EditHandlePtr pSFHandle =
470 boost::dynamic_pointer_cast<
471 FieldContainerPtrSFieldBase::EditHandle>(fHandle);
473 FieldContainerPtrMFieldBase::EditHandlePtr pMFHandle =
474 boost::dynamic_pointer_cast<
475 FieldContainerPtrMFieldBase::EditHandle>(fHandle);
477 for(; idIt != idEnd; ++idIt)
479 if(*idIt != 0)
481 idMapIt = idMap.find(*idIt);
483 if(idMapIt != idMapEnd)
485 fc = FieldContainerFactory::the()->getContainer(
486 idMapIt->second);
488 else
490 FWARNING(("OSBRootElement::mapPtrField: could not find "
491 "FieldContainer with (file) id [%u]\n", *idIt));
492 fc = NULL;
495 else
497 fc = NULL;
500 if(pSFHandle != NULL && pSFHandle->isValid())
502 pSFHandle->set(fc);
504 else if(pMFHandle != NULL && pMFHandle->isValid())
506 pMFHandle->add(fc);
508 else
510 FWARNING(("OSBRootElement::mapPtrField: FieldHandles invalid, "
511 "can not set pointer - target fc [%u][%s] "
512 "fieldId [%u][%s] file id [%u] system id [%u]\n",
513 (fc != NULL ? fc->getId() : 0),
514 (fc != NULL ? fc->getType().getCName() : ""),
515 fieldId,
516 (fc != NULL ?
517 fc->getType().getFieldDesc(fieldId)->getCName() : ""),
518 *idIt,
519 (idMapIt != idMapEnd ? idMapIt->second : 0) ));
525 /*! Prints the map showing the relation between FieldContainer ids in the file
526 and the system, which is used by mapPtrField to fill in the right pointers.
528 void
529 OSBRootElement::dumpIdMap(void) const
531 OSG_OSB_LOG(("OSBRootElement::dumpIdMap\n"));
533 FieldContainerIdMapConstIt mapIt = getIdMap().begin();
534 FieldContainerIdMapConstIt mapEnd = getIdMap().end ();
536 for(; mapIt != mapEnd; ++mapIt)
538 OSG_OSB_LOG((" file id %u -> %u system id\n", mapIt->first, mapIt->second));