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
00040
00041
00042
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045
00046 #include <fstream>
00047
00048 #include "OSGConfig.h"
00049
00050 #include <OSGLog.h>
00051 #include <OSGBaseTypes.h>
00052 #include <OSGPathHandler.h>
00053 #include <OSGGraphOpSeq.h>
00054 #include <OSGStripeGraphOp.h>
00055 #include <OSGImageFileHandler.h>
00056
00057 #include "OSGSceneFileHandler.h"
00058 #include "OSGZStream.h"
00059
00060 #include <OSGNode.h>
00061 #include <OSGThread.h>
00062 #include <OSGThreadManager.h>
00063 #include <OSGBaseFunctions.h>
00064
00065 OSG_USING_NAMESPACE
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 GraphOpSeq *SceneFileHandler::_defaultgraphOpSeq = NULL;
00097 SceneFileHandler * SceneFileHandler::_the = NULL;
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 SceneFileType *SceneFileHandler::getFileType(const Char8 *fileNameOrExtension)
00131 {
00132 const Char8 separator = '.';
00133
00134 if(fileNameOrExtension == NULL)
00135 return NULL;
00136
00137 std::string fe = fileNameOrExtension;
00138
00139 Int32 p = fe.rfind(separator);
00140
00141 std::string ext;
00142
00143 if(p != -1)
00144 ext = fe.substr(p+1, fe.length() - p - 1);
00145 else
00146 ext = fe;
00147
00148
00149 if(ext == "gz")
00150 {
00151 fe = fe.substr(0, p);
00152 p = fe.rfind(separator);
00153 if(p != -1)
00154 ext = fe.substr(p+1, fe.length() - p - 1);
00155 else
00156 ext = fe;
00157 }
00158
00159 IDString suffix;
00160 suffix.set(ext.c_str());
00161 suffix.toLower();
00162
00163 FileTypeMap::iterator sI = _suffixTypeMap.find(suffix);
00164 SceneFileType *type = (sI == _suffixTypeMap.end()) ? 0 : sI->second->front();
00165
00166 return type;
00167 }
00168
00169
00170 #ifdef OSG_WIN32_ICL
00171 #pragma warning (disable : 383)
00172 #endif
00173
00174 Int32 SceneFileHandler::getSuffixList(std::list<const Char8 *> & suffixList,
00175 UInt32 flags)
00176 {
00177 Int32 count = 0;
00178 FileTypeMap::iterator sI;
00179
00180 suffixList.clear();
00181
00182 for ( sI = _suffixTypeMap.begin(); sI != _suffixTypeMap.end(); ++sI)
00183 {
00184 SceneFileType *type = sI->second->front();
00185 if((type->getFlags() & flags) == flags)
00186 {
00187 suffixList.push_back(sI->first.str());
00188 count++;
00189 }
00190 }
00191
00192 return count;
00193 }
00194
00195 #ifdef OSG_WIN32_ICL
00196 #pragma warning (default : 383)
00197 #endif
00198
00199
00200 NodePtr SceneFileHandler::read(std::istream &is, const Char8* fileNameOrExtension,
00201 GraphOpSeq *graphOpSeq)
00202 {
00203 SceneFileType *type = getFileType(fileNameOrExtension);
00204 NodePtr scene = NullFC;
00205
00206 if(!fileNameOrExtension)
00207 {
00208 SWARNING << "cannot read NULL extension" << std::endl;
00209 return NullFC;
00210 }
00211
00212 if (type)
00213 {
00214 SINFO << "try to read stream as " << type->getName() << std::endl;
00215
00216 if(isGZip(is))
00217 {
00218 SINFO << "Detected gzip compressed stream." << std::endl;
00219
00220 #ifdef OSG_ZSTREAM_SUPPORTED
00221 startReadProgressThread(is);
00222 zip_istream unzipper(is);
00223 scene = type->read(unzipper, fileNameOrExtension);
00224 if(scene != NullFC)
00225 {
00226 if(unzipper.check_crc())
00227 SINFO << "Compressed stream has correct checksum." << std::endl;
00228 else
00229 SFATAL << "Compressed stream has wrong checksum." << std::endl;
00230 }
00231 stopReadProgressThread();
00232 #else
00233 SFATAL << "Compressed streams are not supported! Configure with --enable-png --with-png=DIR options." << std::endl;
00234 #endif
00235 }
00236 else
00237 {
00238 startReadProgressThread(is);
00239 scene = type->read(is, fileNameOrExtension);
00240 stopReadProgressThread();
00241 }
00242
00243 if(scene != NullFC)
00244 {
00245 if(graphOpSeq != NULL)
00246 graphOpSeq->run(scene);
00247
00248 SINFO << "read ok:" << std::endl;
00249 }
00250 else
00251 {
00252 SWARNING << "could not read " << std::endl;
00253 }
00254 }
00255 else
00256 {
00257 SWARNING << "could not read unknown file format" << std::endl;
00258 }
00259
00260 return scene;
00261 }
00262
00263
00264 SceneFileHandler::FCPtrStore SceneFileHandler::readTopNodes(
00265 std::istream &is, const Char8 *fileNameOrExtension,
00266 GraphOpSeq *graphOpSeq)
00267 {
00268 std::vector<FieldContainerPtr> nodeVec;
00269 NodePtr scene = read(is, fileNameOrExtension);
00270 if(scene == NullFC)
00271 return nodeVec;
00272
00273 while(scene->getNChildren() > 0)
00274 {
00275 NodePtr child = scene->getChild(0);
00276 NodePtr newChild = Node::create();
00277 while(child->getNChildren() > 0)
00278 newChild->addChild(child->getChild(0));
00279 newChild->setCore(child->getCore());
00280 if(graphOpSeq != NULL)
00281 graphOpSeq->run(newChild);
00282 nodeVec.push_back(newChild);
00283 scene->subChild(child);
00284 }
00285
00286 return nodeVec;
00287 }
00288
00289 NodePtr SceneFileHandler::read(const Char8 *fileName,
00290 GraphOpSeq *graphOpSeq)
00291 {
00292 if(!fileName)
00293 {
00294 SWARNING << "cannot read NULL file" << std::endl;
00295 return NullFC;
00296 }
00297
00298 std::string fullFilePath = initPathHandler(fileName);
00299 if(fullFilePath.empty())
00300 {
00301 SWARNING << "Couldn't open file " << fileName << std::endl;
00302 return NullFC;
00303 }
00304
00305 SceneFileType *type = getFileType(fullFilePath.c_str());
00306 NodePtr scene = NullFC;
00307
00308 if (type)
00309 {
00310 SINFO << "try to read " << fullFilePath
00311 << " as " << type->getName() << std::endl;
00312
00313 std::ifstream in(fullFilePath.c_str(), std::ios::binary);
00314
00315 if(in)
00316 {
00317 scene = read(in, fullFilePath.c_str(), graphOpSeq);
00318 in.close();
00319
00320 if(scene != NullFC)
00321 return scene;
00322 }
00323 else
00324 {
00325 SWARNING << "Couldn't open input stream for file " << fullFilePath << std::endl;
00326 }
00327
00328 #ifndef OSG_DISABLE_DEPRECATED
00329
00330 if(scene == NullFC)
00331 scene = type->readFile(fullFilePath.c_str());
00332
00333 if (scene != NullFC)
00334 {
00335 if(graphOpSeq != NULL)
00336 graphOpSeq->run(scene);
00337
00338 SINFO << "read ok:" << std::endl;
00339 }
00340 else
00341 {
00342 SWARNING << "could not read " << std::endl;
00343 }
00344 #endif
00345 }
00346 else
00347 {
00348 SWARNING << "could not read " << fullFilePath
00349 << "; unknown file format" << std::endl;
00350 }
00351
00352 return scene;
00353 }
00354
00355 SceneFileHandler::FCPtrStore SceneFileHandler::readTopNodes(
00356 const Char8 *fileName,
00357 GraphOpSeq *graphOpSeq)
00358 {
00359 std::vector<FieldContainerPtr> nodeVec;
00360
00361 if(!fileName)
00362 {
00363 SWARNING << "cannot read NULL file" << std::endl;
00364 return nodeVec;
00365 }
00366
00367 std::string fullFilePath = initPathHandler(fileName);
00368 if(fullFilePath.empty())
00369 {
00370 SWARNING << "Couldn't open file " << fileName << std::endl;
00371 return nodeVec;
00372 }
00373
00374 std::ifstream in(fullFilePath.c_str(), std::ios::binary);
00375
00376 if(in)
00377 {
00378 nodeVec = readTopNodes(in, fullFilePath.c_str(), graphOpSeq);
00379 in.close();
00380 }
00381 else
00382 {
00383 SWARNING << "Couldn't open input stream for file " << fullFilePath << std::endl;
00384 }
00385
00386
00387 if(nodeVec.empty())
00388 {
00389 NodePtr scene = read(fullFilePath.c_str());
00390 if(scene == NullFC)
00391 return nodeVec;
00392
00393 while(scene->getNChildren() > 0)
00394 {
00395 NodePtr child = scene->getChild(0);
00396 NodePtr newChild = Node::create();
00397 while(child->getNChildren() > 0)
00398 newChild->addChild(child->getChild(0));
00399 newChild->setCore(child->getCore());
00400 if(graphOpSeq != NULL)
00401 graphOpSeq->run(newChild);
00402 nodeVec.push_back(newChild);
00403 scene->subChild(child);
00404 }
00405 }
00406
00407 return nodeVec;
00408 }
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 bool SceneFileHandler::write(const NodePtr &node, std::ostream &os,
00431 const Char8 *fileNameOrExtension, bool compress)
00432 {
00433 bool retCode = false;
00434 SceneFileType *type = getFileType(fileNameOrExtension);
00435
00436 if(type)
00437 {
00438 SINFO << "try to write stream as " << type->getName() << std::endl;
00439 if(compress)
00440 {
00441 #ifdef OSG_ZSTREAM_SUPPORTED
00442 SINFO << "writing compressed stream." << std::endl;
00443 zip_ostream zipper(os, true);
00444 retCode = type->write(node, zipper, fileNameOrExtension);
00445 zipper.zflush();
00446 #else
00447 SFATAL << "Compressed streams are not supported! Configure with --enable-png --with-png=DIR options." << std::endl;
00448 #endif
00449 }
00450 else
00451 {
00452 retCode = type->write(node, os, fileNameOrExtension);
00453 }
00454 }
00455 else
00456 SWARNING << "can't write stream unknown scene format" << std::endl;
00457
00458 return retCode;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 bool SceneFileHandler::write (const NodePtr &node, const Char8 *fileName, bool compress)
00482 {
00483 bool retCode = false;
00484 SceneFileType *type = getFileType(fileName);
00485
00486 if (type)
00487 {
00488 SINFO << "try to write " << fileName << " as " << type->getName() << std::endl;
00489
00490 std::ofstream out(fileName, std::ios::binary);
00491 if(out)
00492 {
00493 retCode = write(node, out, fileName, compress);
00494 out.close();
00495 }
00496 else
00497 {
00498 SWARNING << "Can not open output stream for file '" << fileName << "'!" << std::endl;
00499 }
00500
00501 #ifndef OSG_DISABLE_DEPRECATED
00502 if(!retCode)
00503 retCode = type->writeFile(node, fileName);
00504 #endif
00505
00506 if(!retCode)
00507 SWARNING << "Couldn't write " << fileName << std::endl;
00508 }
00509 else
00510 SWARNING << "can't write " << fileName << "; unknown scene format"
00511 << std::endl;
00512
00513 return retCode;
00514 }
00515
00519 PathHandler *SceneFileHandler::getPathHandler(void)
00520 {
00521 if(_pathHandler == NULL)
00522 return &_defaultPathHandler;
00523 else
00524 return _pathHandler;
00525 }
00526
00527
00531 void SceneFileHandler::setPathHandler(PathHandler *pathHandler)
00532 {
00533 _pathHandler = pathHandler;
00534 }
00535
00539 std::string SceneFileHandler::initPathHandler(const Char8 *fileName)
00540 {
00541 std::string fullFilePath;
00542 if(_pathHandler != NULL)
00543 {
00544
00545 if(ImageFileHandler::the().getPathHandler() == NULL)
00546 ImageFileHandler::the().setPathHandler(_pathHandler);
00547
00548 fullFilePath = _pathHandler->findFile(fileName);
00549 }
00550 else
00551 {
00552
00553 if(ImageFileHandler::the().getPathHandler() == NULL)
00554 ImageFileHandler::the().setPathHandler(&_defaultPathHandler);
00555
00556 _defaultPathHandler.clearPathList();
00557 _defaultPathHandler.push_frontCurrentDir();
00558 _defaultPathHandler.setBaseFile(fileName);
00559 fullFilePath = _defaultPathHandler.findFile(fileName);
00560 }
00561
00562 return fullFilePath;
00563 }
00564
00565 GraphOpSeq *SceneFileHandler::getDefaultGraphOp(void)
00566 {
00567 return _defaultgraphOpSeq;
00568 }
00569
00570 void SceneFileHandler::setDefaultGraphOp(GraphOpSeq *graphOpSeq)
00571 {
00572 _defaultgraphOpSeq = graphOpSeq;
00573 }
00574
00575
00576 bool SceneFileHandler::setOptions(const Char8 *suffix, const Char8 *options)
00577 {
00578 if(suffix == NULL)
00579 return false;
00580
00581 SceneFileType *type = getFileType(suffix);
00582 if(type == NULL)
00583 return false;
00584
00585 type->setOptions(options);
00586
00587 return true;
00588 }
00589
00590 const Char8 *SceneFileHandler::getOptions(const Char8 *suffix)
00591 {
00592 if(suffix == NULL)
00593 return NULL;
00594
00595 SceneFileType *type = getFileType(suffix);
00596
00597 if(type == NULL)
00598 return NULL;
00599
00600 return type->getOptions();
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 void SceneFileHandler::print (void )
00624 {
00625 FileTypeMap::iterator sI;
00626
00627 for(sI = _suffixTypeMap.begin(); sI != _suffixTypeMap.end(); sI++)
00628 {
00629 std::string rw;
00630 SceneFileType *type = sI->second->front();
00631 if((type->getFlags() & SceneFileType::OSG_READ_SUPPORTED) &&
00632 (type->getFlags() & SceneFileType::OSG_WRITE_SUPPORTED))
00633 {
00634 rw = "reader and writer";
00635 }
00636 else
00637 {
00638 if(type->getFlags() & SceneFileType::OSG_READ_SUPPORTED)
00639 rw = "reader";
00640 if(type->getFlags() & SceneFileType::OSG_WRITE_SUPPORTED)
00641 rw = "writer";
00642 }
00643
00644 std::cerr << "suffix: " << sI->first.str()
00645 << ", type: " << sI->second->front()->getName()
00646 << " " << rw << std::endl;
00647 }
00648 }
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 bool SceneFileHandler::FindOverride::operator() (SceneFileType *fileTypeP)
00682 {
00683 if(fileTypeP == NULL)
00684 return false;
00685
00686 if(fileTypeP->doOverride() == false)
00687 return true;
00688
00689 if(fileTypeP->getOverridePriority() <= uiRefPriority)
00690 return true;
00691
00692 return false;
00693 }
00694
00695
00696 #ifdef OSG_WIN32_ICL
00697 #pragma warning (disable : 383)
00698 #endif
00699
00700 bool SceneFileHandler::addSceneFileType(SceneFileType &fileType)
00701 {
00702 bool retCode = false;
00703
00704 std::list<IDString>::iterator sI;
00705 FileTypeMap ::iterator smI;
00706
00707 IDString suffix;
00708
00709 for( sI = fileType.suffixList().begin();
00710 sI != fileType.suffixList().end();
00711 ++sI)
00712 {
00713 suffix.set(sI->str());
00714 suffix.toLower();
00715
00716 smI = the()._suffixTypeMap.find(suffix);
00717
00718 if (smI != the()._suffixTypeMap.end())
00719 {
00720 if(fileType.doOverride() == true)
00721 {
00722 FindOverride overrideFinder;
00723 FileTypeList::iterator lIt;
00724
00725 overrideFinder.uiRefPriority = fileType.getOverridePriority();
00726
00727 lIt = std::find_if(the()._suffixTypeMap[suffix]->begin(),
00728 the()._suffixTypeMap[suffix]->end(),
00729 overrideFinder);
00730
00731 the()._suffixTypeMap[suffix]->insert(lIt, &fileType);
00732
00733 SWARNING << "Added an file type with suffix "
00734 << suffix
00735 << " overriding "
00736 << std::endl;
00737 }
00738 else
00739 {
00740 the()._suffixTypeMap[suffix]->push_back(&fileType);
00741
00742 SWARNING << "Added an file type with suffix "
00743 << suffix
00744 << " non overriding at the end of the list"
00745 << std::endl;
00746 }
00747 }
00748 else
00749 {
00750 FileTypeList *pTmpList = new FileTypeList;
00751
00752 pTmpList->push_back(&fileType);
00753
00754 the()._suffixTypeMap[suffix] = pTmpList;
00755
00756 retCode = true;
00757 }
00758 }
00759
00760 return retCode;
00761 }
00762
00763 bool SceneFileHandler::subSceneFileType(SceneFileType &fileType)
00764 {
00765 bool retCode = false;
00766
00767 std::list<IDString>::iterator sI;
00768 FileTypeMap ::iterator smI;
00769
00770 IDString suffix;
00771
00772 for( sI = fileType.suffixList().begin();
00773 sI != fileType.suffixList().end();
00774 ++sI)
00775 {
00776 suffix.set(sI->str());
00777 suffix.toLower();
00778
00779 smI = the()._suffixTypeMap.find(suffix);
00780 if (smI != the()._suffixTypeMap.end())
00781 {
00782 the()._suffixTypeMap.erase(smI);
00783 retCode = true;
00784 }
00785 }
00786 return retCode;
00787 }
00788
00789 #ifdef OSG_WIN32_ICL
00790 #pragma warning (default : 383)
00791 #endif
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826 SceneFileHandler::SceneFileHandler (void) :
00827 _readProgressFP(NULL),
00828 _progressData(),
00829 _readReady(false),
00830 _pathHandler(NULL),
00831 _defaultPathHandler()
00832 {
00833 if(_defaultgraphOpSeq == NULL)
00834 {
00835 _defaultgraphOpSeq = new GraphOpSeq;
00836
00837 _defaultgraphOpSeq->addGraphOp(new StripeGraphOp);
00838 }
00839
00840 return;
00841 }
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863 SceneFileHandler::SceneFileHandler (const SceneFileHandler & )
00864 {
00865 SWARNING << "In copy constructor; I shouldn't be in this corner" << std::endl;
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889 SceneFileHandler &SceneFileHandler::the(void)
00890 {
00891 if(_the == NULL)
00892 {
00893 _the = new SceneFileHandler;
00894 }
00895
00896 return *_the;
00897 }
00898
00899 void SceneFileHandler::setReadProgressCB(progresscbfp fp)
00900 {
00901 stopReadProgressThread();
00902 _readProgressFP = fp;
00903 }
00904
00905 SceneFileHandler::progresscbfp SceneFileHandler::getReadProgressCB(void)
00906 {
00907 return _readProgressFP;
00908 }
00909
00910 void SceneFileHandler::startReadProgressThread(std::istream &is)
00911 {
00912 if(_readProgressFP == NULL)
00913 return;
00914
00915
00916 _progressData.is = &is;
00917 is.seekg(0, std::ios::end);
00918 _progressData.length = is.tellg();
00919 is.seekg(0, std::ios::beg);
00920
00921 Thread *pt = Thread::find("osg::FileIOReadProgressThread");
00922 if(pt == NULL)
00923 pt = OSG::Thread::get("osg::FileIOReadProgressThread");
00924
00925 _readReady = false;
00926 if(pt != NULL)
00927 pt->runFunction(readProgress, 0, NULL);
00928 else
00929 SWARNING << "Couldn't create read progress thread!" << std::endl;
00930 }
00931
00932 void SceneFileHandler::stopReadProgressThread(void)
00933 {
00934 if(_readProgressFP == NULL)
00935 return;
00936
00937 Thread *pt = Thread::find("osg::FileIOReadProgressThread");
00938
00939 if(pt != NULL)
00940 {
00941
00942 _readReady = true;
00943 Thread::join(pt);
00944 }
00945 }
00946
00947 void SceneFileHandler::readProgress(void * OSG_CHECK_ARG(data))
00948 {
00949 UInt32 p = 0;
00950 while(p < 100 && !the()._readReady)
00951 {
00952 if(!the()._progressData.is->eof() &&
00953 !the()._progressData.is->bad())
00954 {
00955 UInt64 pos = the()._progressData.is->tellg();
00956 p = UInt32((pos * 100) / the()._progressData.length);
00957 if(p > 100)
00958 p = 100;
00959 }
00960 else
00961 {
00962 p = 100;
00963 }
00964
00965 the()._readProgressFP(p);
00966 osgsleep(100);
00967 }
00968 if(p < 100)
00969 the()._readProgressFP(100);
00970 }
00971
00972 SceneFileHandler::~SceneFileHandler(void)
00973 {
00974 }
00975
00976
00977
00978
00979
00980 #ifdef __sgi
00981 #pragma set woff 1174
00982 #endif
00983
00984 #ifdef OSG_LINUX_ICC
00985 #pragma warning( disable : 177 )
00986 #endif
00987
00988 namespace
00989 {
00990 static Char8 cvsid_cpp[] = "@(#)$Id: $";
00991 static Char8 cvsid_hpp[] = OSGSCENEFILEHANDLER_HEADER_CVSID;
00992 }