Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGBINWriter.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041 
00042 #include <string>
00043 #include <map>
00044 #include <vector>
00045 #include <fstream>
00046 
00047 #include <OSGNode.h>
00048 #include <OSGBaseFunctions.h>
00049 #include <OSGFieldContainer.h>
00050 #include <OSGSFFieldContainerPtr.h>
00051 #include <OSGMFFieldContainerPtr.h>
00052 #include <OSGIDString.h>
00053 #include <OSGBinaryDataHandler.h>
00054 #include <OSGVRMLNodeDescs.h>
00055 
00056 #include <OSGConfig.h>
00057 #include "OSGBINWriter.h"
00058 
00059 OSG_USING_NAMESPACE
00060 
00067 /*-------------------------------------------------------------------------*/
00068 /*                            Constructors/Destructor                      */
00069 
00070 BINWriter::BINWriter(std::ostream &os) :
00071     _fcMap(),
00072     _fcIdMap(),
00073     _outFileHandler(os),
00074     _vec_pRootNodes(),
00075     _valid_stream(os != false)
00076 {
00077 }
00078 
00081 BINWriter::~BINWriter(void)
00082 {
00083 }
00084 
00085 /*-------------------------------------------------------------------------*/
00086 /*                            write                                        */
00087 
00090 bool BINWriter::write(NodePtr node)
00091 {
00092     if(!_valid_stream)
00093     {
00094         SWARNING << "BINLoader::write : Stream is invalid!" << std::endl;
00095         return false;
00096     }
00097 
00098     _fcMap.clear();
00099     _fcIdMap.clear();
00100     _vec_pRootNodes.clear();
00101     _vec_pRootNodes.push_back(node);
00102 
00103     // traverse and index containers to write
00104     doIndexFC(node);
00105 
00106     // write the header with number and type of containers
00107     writeFileHeader();
00108 
00109     // write the containers and flush the filehandler
00110     doWriteIndexedFC();
00111     _outFileHandler.flush();
00112 
00113     return true;
00114 }
00115 
00118 bool BINWriter::write(std::vector<NodePtr> nodes)
00119 {
00120     if(!_valid_stream)
00121     {
00122         SWARNING << "BINLoader::write : Stream is invalid!" << std::endl;
00123         return false;
00124     }
00125 
00126     //does the same as write(NodePtr) for every Node in the vector
00127     _fcMap.clear();
00128     _fcIdMap.clear();
00129     _vec_pRootNodes.clear();
00130     _vec_pRootNodes = nodes;
00131 
00132     std::vector < NodePtr >::const_iterator iter = nodes.begin();
00133     for(; iter != nodes.end(); ++iter)
00134     {
00135         doIndexFC(*iter);
00136     }
00137 
00138     writeFileHeader();
00139     doWriteIndexedFC();
00140     _outFileHandler.flush();
00141 
00142     return true;
00143 }
00144 
00145 /*-------------------------------------------------------------------------*/
00146 /*                           Helper                                        */
00147 
00150 void BINWriter::addToIdMap(FieldContainerPtr fcPtr)
00151 {
00152     if(fcPtr == NullFC)
00153     {
00154         SWARNING << "ERROR in BINWriter::addToIdMap : NullFC" << std::endl;
00155         return;
00156     }
00157 
00158     FCTypeIdMap::iterator   iIdMap;
00159 
00160     // add new ContainerType
00161     if(_fcIdMap.find(fcPtr->getType().getCName()) == _fcIdMap.end())
00162     {
00163         std::vector < UInt32 > idVec;
00164         idVec.push_back(0);
00165         if(!(_fcIdMap.insert(std::pair < std::string,
00166                              std::vector < UInt32 > >
00167                              (fcPtr->getType().getCName(), idVec)).second))
00168         {
00169             SWARNING <<
00170                 "BINWriter::addToIdMap(FieldContainerPtr):" <<
00171                 std::endl <<
00172                 "ERROR while inserting into _fcIdMap" <<
00173                 std::endl;
00174         };
00175     }
00176 
00177     // add container to the vector of appropriate type
00178     iIdMap = _fcIdMap.find(fcPtr->getType().getCName());
00179     iIdMap->second.push_back(fcPtr.getFieldContainerId());
00180 
00181     //increase the 0th entry of the vector (number of entries)
00182     iIdMap->second[0]++;
00183 }
00184 
00202 void BINWriter::writeFileHeader(void)
00203 {
00204     FCTypeIdMap::iterator   iIdMap = _fcIdMap.begin();
00205     std::vector < NodePtr >::iterator iRoots = _vec_pRootNodes.begin();
00206 
00207     UInt32  mapSize = _fcIdMap.size();
00208     UInt32  numOfRoots = _vec_pRootNodes.size();
00209     UInt32  i = 0;
00210 
00211     _outFileHandler.putValue(numOfRoots);
00212     for(i = 0; i != numOfRoots; ++i, ++iRoots)
00213     {
00214         _outFileHandler.putValue(iRoots->getFieldContainerId());
00215     }
00216 
00217     _outFileHandler.putValue(mapSize);
00218     for(i = 0; i < mapSize; ++i, ++iIdMap)
00219     {
00220         _outFileHandler.putValue(iIdMap->first);
00221 
00222         std::vector < UInt32 >::iterator intIt = iIdMap->second.begin();
00223         std::vector < UInt32 >::iterator intEnd = iIdMap->second.end();
00224 
00225         while(intIt != intEnd)
00226         {
00227             _outFileHandler.putValue(*intIt);
00228 
00229             ++intIt;
00230         }
00231     }
00232 }
00233 
00236 void BINWriter::doIndexFC(FieldContainerPtr fieldConPtr)
00237 {
00238     // traverse
00239     if(fieldConPtr == NullFC)
00240     {
00241         // nothing to do
00242         return;
00243     }
00244 
00245     FieldContainerType  &fcType = fieldConPtr->getType();
00246     UInt32 i;
00247 
00248     // insert into map
00249     std::pair < std::map<UInt32, FCInfo>::iterator, bool > element = _fcMap.
00250         insert(std::pair < UInt32,
00251                    FCInfo > (fieldConPtr.getFieldContainerId(), FCInfo()));
00252 
00253     // avoid loop. Element was already in the map
00254     if(element.second == false)
00255     {
00256         return;
00257     }
00258 
00259     // get inserted element
00260     FCInfo  &fcInfo = element.first->second;
00261 
00262     //go through all fields
00263     for(i = 1; i <= fcType.getNumFieldDescs(); ++i)
00264     {
00265         FieldDescription    *fDesc = fcType.getFieldDescription(i);
00266         Field               *fieldPtr = fieldConPtr->getField(i);
00267         const FieldType     &fType = fieldPtr->getType();
00268 
00269         // process all containers
00270         if(!fDesc->isInternal())
00271         {
00272             //detect referenced containers #DIRTY-HACK#
00273             if(strstr(fType.getCName(), "Ptr") != NULL)
00274             {
00275                 //traverse the referenced SF/MF-containers
00276                 if(fieldPtr->getCardinality() == FieldType::SINGLE_FIELD)
00277                 {
00278                     doIndexFC(((SFFieldContainerPtr *) fieldPtr)->getValue());
00279                 }
00280                 else if(fieldPtr->getCardinality() == FieldType::MULTI_FIELD)
00281                 {
00282                     UInt32 j;
00283                     for(j = 0; j < ((MFFieldContainerPtr *) fieldPtr)->size();
00284                                             ++j)
00285                     {
00286                         doIndexFC((*(((MFFieldContainerPtr *) fieldPtr)))[j]);
00287                     }
00288                 }
00289             }
00290 
00291             //attachments
00292             if(strcmp(fDesc->getCName(), "attachments") == 0)
00293             {
00294                 AttachmentMap::const_iterator   mapIt =
00295                     ((SFAttachmentMap *) fieldPtr)->getValue().begin();
00296                 AttachmentMap::const_iterator   mapEnd =
00297                     ((SFAttachmentMap *) fieldPtr)->getValue().end();
00298 
00299                 for(; mapIt != mapEnd; ++mapIt)
00300                 {
00301                     /*
00302                     fprintf(stderr, "Write %s %s\n",
00303                                                 mapIt->second->getType().getCName(),
00304                                                 GenericAtt::getClassType().getCName());
00305                     */
00306 
00307                     doIndexFC(mapIt->second);
00308                 }
00309             }
00310         }
00311 
00312         // create field mask
00313         // ignore internal fields except parent fields
00314         if(fDesc->isInternal() &&
00315                    strcmp(fDesc->getCName(), "parent") != 0 &&
00316                    strcmp(fDesc->getCName(), "parents") != 0)
00317         {
00318             continue;
00319         }
00320 
00321         // ignore node volume
00322         if(fcType == Node::getClassType() &&
00323                    fcType.getFieldDescription(i)->getFieldMask()
00324                        == Node::VolumeFieldMask)
00325         {
00326             continue;
00327         }
00328 
00329         // ignore empty mfields
00330         if(fieldPtr->getCardinality() == FieldType::MULTI_FIELD &&
00331                    fieldPtr->isEmpty() == true)
00332         {
00333             continue;
00334         }
00335 
00336         // add field to fieldmask
00337         fcInfo.mask =
00338             (
00339                 fcInfo.mask |
00340                 fcType.getFieldDescription(i)->getFieldMask()
00341             );
00342     }
00343 
00344     // add container to the Map of containers to write
00345     fcInfo.ptr = fieldConPtr;
00346     fcInfo.type = fieldConPtr->getType().getName();
00347 
00348     // add container id to index
00349     addToIdMap(fcInfo.ptr);
00350 }
00351 
00354 void BINWriter::doWriteIndexedFC(void)
00355 {
00356     FCInfoMap::const_iterator   i = _fcMap.begin();
00357     UInt32 mapSize = _fcMap.size(), count = 1;
00358 
00359     for(; i != _fcMap.end(); ++i, ++count)
00360     {
00361         SINFO <<
00362             "writing container " <<
00363             std::setw(4) <<
00364             count <<
00365             "/" <<
00366             mapSize <<
00367             "..." <<
00368             std::endl;
00369 
00370         //for each entry in _fcMap
00371         //write ID
00372         _outFileHandler.putValue(i->first);
00373 
00374         //write FieldMask
00375         _outFileHandler.putValue(i->second.mask);
00376 
00377         //write data
00378         i->second.ptr->copyToBin(_outFileHandler, i->second.mask);
00379     }
00380 }
00381 
00382 /*-------------------------------------------------------------------------*/
00383 /*                            FCInfo                                       */
00384 
00387 BINWriter::FCInfo::FCInfo(void) :
00388     type(OSG::IDString()),
00389     ptr(NullFC),
00390     mask(FieldBits::NoField)
00391 {
00392 }
00393 
00394 /*-------------------------------------------------------------------------*/
00395 /*                           BinaryFileHandler                             */
00396 
00399 BINWriter::BinaryFileHandler::BinaryFileHandler(std::ostream &os) :
00400     BinaryDataHandler(0),
00401     _os(os)
00402 {
00403     _writeMemory.resize(10000);
00404     writeBufAdd(&_writeMemory[0], _writeMemory.size());
00405 }
00406 
00409 BINWriter::BinaryFileHandler::~BinaryFileHandler(void)
00410 {
00411 }
00412 
00415 void BINWriter::BinaryFileHandler::write(MemoryHandle mem, UInt32 size)
00416 {
00417     _os.write((const char *) mem, size);
00418 }
00419 
00420 /*-------------------------------------------------------------------------*/
00421 /*                              cvs id's                                   */
00422 
00423 #ifdef __sgi
00424 #pragma set woff 1174
00425 #endif
00426 #ifdef OSG_LINUX_ICC
00427 #pragma warning(disable : 177)
00428 #endif
00429 
00430 namespace
00431 {
00432     static Char8 cvsid_cpp[] = "@(#)$Id: $";
00433     static Char8 cvsid_hpp[] = OSGBINWRITER_HEADER_CVSID;
00434 }

Generated on Thu Aug 25 04:01:19 2005 for OpenSG by  doxygen 1.4.3