00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
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
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
00104 doIndexFC(node);
00105
00106
00107 writeFileHeader();
00108
00109
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
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
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
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
00178 iIdMap = _fcIdMap.find(fcPtr->getType().getCName());
00179 iIdMap->second.push_back(getContainerId(fcPtr));
00180
00181
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(getContainerId(*iRoots));
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
00239 if(fieldConPtr == NullFC)
00240 {
00241
00242 return;
00243 }
00244
00245 FieldContainerType &fcType = fieldConPtr->getType();
00246 UInt32 i;
00247
00248
00249 std::pair < std::map<UInt32, FCInfo>::iterator, bool > element = _fcMap.
00250 insert(std::pair < UInt32,
00251 FCInfo > (getContainerId(fieldConPtr), FCInfo()));
00252
00253
00254 if(element.second == false)
00255 {
00256 return;
00257 }
00258
00259
00260 FCInfo &fcInfo = element.first->second;
00261
00262
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
00270 if(!fDesc->isInternal())
00271 {
00272
00273 if(strstr(fType.getCName(), "Ptr") != NULL)
00274 {
00275
00276 if(fieldPtr->getCardinality() == FieldType::SINGLE_FIELD)
00277 {
00278 doIndexFC(static_cast<SFFieldContainerPtr *>(fieldPtr)->getValue());
00279 }
00280 else if(fieldPtr->getCardinality() == FieldType::MULTI_FIELD)
00281 {
00282 UInt32 j;
00283 for(j = 0; j < static_cast<MFFieldContainerPtr *>(fieldPtr)->size();
00284 ++j)
00285 {
00286 doIndexFC((*(static_cast<MFFieldContainerPtr *>(fieldPtr)))[j]);
00287 }
00288 }
00289 }
00290
00291
00292 if(strcmp(fDesc->getCName(), "attachments") == 0)
00293 {
00294 AttachmentMap::const_iterator mapIt =
00295 static_cast<SFAttachmentMap *>(fieldPtr)->getValue().begin();
00296 AttachmentMap::const_iterator mapEnd =
00297 static_cast<SFAttachmentMap *>(fieldPtr)->getValue().end();
00298
00299 for(; mapIt != mapEnd; ++mapIt)
00300 {
00301
00302
00303
00304
00305
00306
00307 doIndexFC(mapIt->second);
00308 }
00309 }
00310 }
00311
00312
00313
00314 if(fDesc->isInternal() &&
00315 strcmp(fDesc->getCName(), "parent") != 0 &&
00316 strcmp(fDesc->getCName(), "parents") != 0)
00317 {
00318 continue;
00319 }
00320
00321
00322 if(fcType == Node::getClassType() &&
00323 fcType.getFieldDescription(i)->getFieldMask()
00324 == Node::VolumeFieldMask)
00325 {
00326 continue;
00327 }
00328
00329
00330 if(fieldPtr->getCardinality() == FieldType::MULTI_FIELD &&
00331 fieldPtr->isEmpty() == true)
00332 {
00333 continue;
00334 }
00335
00336
00337 fcInfo.mask =
00338 (
00339 fcInfo.mask |
00340 fcType.getFieldDescription(i)->getFieldMask()
00341 );
00342 }
00343
00344
00345 fcInfo.ptr = fieldConPtr;
00346 fcInfo.type = fieldConPtr->getType().getName();
00347
00348
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
00371
00372 _outFileHandler.putValue(i->first);
00373
00374
00375 _outFileHandler.putValue(i->second.mask);
00376
00377
00378 i->second.ptr->copyToBin(_outFileHandler, i->second.mask);
00379 }
00380 }
00381
00382
00383
00384
00387 BINWriter::FCInfo::FCInfo(void) :
00388 type(OSG::IDString()),
00389 ptr(NullFC),
00390 mask(FieldBits::NoField)
00391 {
00392 }
00393
00394
00395
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(reinterpret_cast<const char *>(mem), size);
00418 }
00419
00420
00421
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 }