root/OpenSceneGraph/trunk/src/osgDB/Registry.cpp @ 2962

Revision 2962, 56.7 kB (checked in by robert, 11 years ago)

Added support for osgDB::ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osg/Notify>
15#include <osg/Object>
16#include <osg/Image>
17#include <osg/Node>
18#include <osg/Group>
19#include <osg/Geode>
20#include <osg/ApplicationUsage>
21
22#include <osgDB/Registry>
23#include <osgDB/FileUtils>
24#include <osgDB/FileNameUtils>
25
26#include <stdio.h>
27
28#include <algorithm>
29#include <set>
30
31using namespace osg;
32using namespace osgDB;
33
34class AvailableReaderWriterIterator
35{
36public:
37    AvailableReaderWriterIterator(Registry::ReaderWriterList& rwList):
38        _rwList(rwList) {}
39
40
41    ReaderWriter& operator * () { return *get(); }
42    ReaderWriter* operator -> () { return get(); }
43   
44    bool valid() { return get()!=0; }
45   
46    void operator ++()
47    {
48        _rwUsed.insert(get());
49    }
50   
51
52protected:
53
54    Registry::ReaderWriterList&     _rwList;
55    std::set<ReaderWriter*>         _rwUsed;
56
57    ReaderWriter* get()
58    {
59        Registry::ReaderWriterList::iterator itr=_rwList.begin();
60        for(;itr!=_rwList.end();++itr)
61        {
62            if (_rwUsed.find(itr->get())==_rwUsed.end())
63            {
64                return itr->get();
65            }
66        }
67        return 0;
68    }
69
70};
71
72#if 0
73    // temporary test of autoregistering, not compiled by default.
74    enum Methods
75    {
76        SET_1,
77        SET_2,
78        END
79    };
80
81
82    typedef std::pair<Methods,std::string> MethodPair;
83
84    class Proxy
85    {
86    public:
87        Proxy(MethodPair* methods)
88        {
89            std::cout<<"methods "<<methods<<std::endl;
90            for(int i=0;methods[i].first!=END;++i)
91            {
92                std::cout<<"\t"<<methods[i].first<<"\t"<<methods[i].second<<std::endl;
93            }
94        }
95    };
96
97
98    static MethodPair methods[] =
99    {
100        MethodPair(SET_1,"SET_1"),
101        MethodPair(SET_2,"SET_2"),
102        MethodPair(END,"")
103    };
104
105    Proxy myproxy(methods);
106
107#endif
108
109void PrintFilePathList(std::ostream& stream,const FilePathList& filepath)
110{
111    for(FilePathList::const_iterator itr=filepath.begin();
112        itr!=filepath.end();
113        ++itr)
114    {
115        stream << "    "<< *itr<<std::endl;
116    }
117}
118
119Registry* Registry::instance(bool erase)
120{
121    static ref_ptr<Registry> s_nodeFactory = new Registry;
122    if (erase)
123    {
124        s_nodeFactory->closeAllLibraries();
125        s_nodeFactory = 0;
126    }
127    return s_nodeFactory.get(); // will return NULL on erase
128}
129
130
131// definition of the Registry
132Registry::Registry()
133{
134    // comment out because it was causing problems under OSX - causing it to crash osgconv when constucting ostream in osg::notify().
135    // notify(INFO) << "Constructing osg::Registry"<<std::endl;
136
137    _createNodeFromImage = false;
138    _openingLibrary = false;
139   
140    _useObjectCacheHint = CACHE_NONE;
141
142    initFilePathLists();
143
144    // register file extension alias.
145    addFileExtensionAlias("sgi""rgb");
146    addFileExtensionAlias("rgba", "rgb");
147    addFileExtensionAlias("int""rgb");
148    addFileExtensionAlias("inta", "rgb");
149    addFileExtensionAlias("bw",   "rgb");
150
151    addFileExtensionAlias("ivz",   "gz");
152    addFileExtensionAlias("ozg",   "gz");
153   
154#if defined(DARWIN_QUICKTIME)
155    addFileExtensionAlias("jpg""qt");
156    addFileExtensionAlias("jpe""qt");
157    addFileExtensionAlias("jpeg", "qt");
158    addFileExtensionAlias("tif""qt");
159    addFileExtensionAlias("tiff", "qt");
160    addFileExtensionAlias("gif""qt");
161    addFileExtensionAlias("png""qt");
162    addFileExtensionAlias("mov""qt");
163    addFileExtensionAlias("mpg""qt");
164    addFileExtensionAlias("mpv""qt");
165    addFileExtensionAlias("dv",   "qt");
166#else
167    addFileExtensionAlias("jpg""jpeg");
168    addFileExtensionAlias("jpe""jpeg");
169    addFileExtensionAlias("tif""tiff");
170    addFileExtensionAlias("mpg""mpeg");
171    addFileExtensionAlias("mpv""mpeg");
172#endif
173
174
175    // remove geo to lwo alias as the new Carbon Graphics GEO format
176    // also uses the .geo. It is still possible to load light wave .geo
177    // files via loading the lwo plugin explicitly and then doing a readNodeFile.
178    //addFileExtensionAlias("geo",  "lwo");
179    addFileExtensionAlias("lw",   "lwo");
180
181    addFileExtensionAlias("wrl",   "iv");
182   
183    // add alias for the text/freetype plugin.
184    addFileExtensionAlias("ttf",   "freetype");  // true type
185    addFileExtensionAlias("ttc",   "freetype");  // true type
186    addFileExtensionAlias("cid",   "freetype");  // Postscript CID-Fonts
187    addFileExtensionAlias("cff",   "freetype");  // OpenType
188    addFileExtensionAlias("cef",   "freetype");  // OpenType
189    addFileExtensionAlias("fon",   "freetype");  // Windows bitmap fonts
190    addFileExtensionAlias("fnt",   "freetype");    // Windows bitmap fonts
191   
192    // wont't add type1 and type2 until resolve extension collision with Peformer binary and ascii files.
193    // addFileExtensionAlias("pfb",   "freetype");  // type1 binary
194    // addFileExtensionAlias("pfa",   "freetype");  // type2 ascii
195
196
197    // portable bitmap, greyscale and colour/pixmap image formats
198    addFileExtensionAlias("pbm", "pnm");
199    addFileExtensionAlias("pgm", "pnm");
200    addFileExtensionAlias("ppm", "pnm");
201   
202}
203
204
205Registry::~Registry()
206{
207    // switch off the pager and its associated thread before we clean up
208    // rest of the Registry.
209    _databasePager = 0;
210
211    // clean up the SharedStateManager
212    _sharedStateManager = 0;
213   
214    // object cache clear needed here to prevent crash in unref() of
215    // the objects it contains when running the TXP plugin.
216    // Not sure why, but perhaps there is is something in a TXP plugin
217    // which is deleted the data before its ref count hits zero, perhaps
218    // even some issue with objects be allocated by a plugin that is
219    // mainted after that plugin is deleted...  Robert Osfield, Jan 2004.
220    _objectCache.clear();
221
222
223    // unload all the plugin before we finally destruct.
224    closeAllLibraries();
225}
226
227#ifndef WIN32
228static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[:path]..","Paths for locating datafiles");
229#else
230static osg::ApplicationUsageProxy Registry_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_FILE_PATH <path>[;path]..","Paths for locating datafiles");
231#endif
232
233void Registry::initDataFilePathList()
234{
235    //
236    // set up data file paths
237    //
238    char *ptr;
239    if( (ptr = getenv( "OSG_FILE_PATH" )) )
240    {
241        //notify(DEBUG_INFO) << "OSG_FILE_PATH("<<ptr<<")"<<std::endl;
242        setDataFilePathList(ptr);
243    }
244    else if( (ptr = getenv( "OSGFILEPATH" )) )
245    {
246        //notify(DEBUG_INFO) << "OSGFILEPATH("<<ptr<<")"<<std::endl;
247        setDataFilePathList(ptr);
248    }
249
250    //osg::notify(INFO)<<"Data FilePathList"<<std::endl;
251    //PrintFilePathList(osg::notify(INFO),getDataFilePathList());
252}
253
254#ifndef WIN32
255static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[:path]..","Paths for locating libraries/ plugins");
256#else
257static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_LIBRARY_PATH <path>[;path]..","Paths for locating libraries/ plugins");
258#endif
259
260void Registry::initLibraryFilePathList()
261{
262    //
263    // set up library paths
264    //
265    char* ptr;
266    if( (ptr = getenv( "OSG_LIBRARY_PATH")) )
267    {
268        //notify(DEBUG_INFO) << "OSG_LIBRARY_PATH("<<ptr<<")"<<std::endl;
269        setLibraryFilePathList(ptr);
270    }
271    else if( (ptr = getenv( "OSG_LD_LIBRARY_PATH")) )
272    {
273        //notify(DEBUG_INFO) << "OSG_LD_LIBRARY_PATH("<<ptr<<")"<<std::endl;
274        setLibraryFilePathList(ptr);
275    }
276
277#ifdef __sgi
278
279    convertStringPathIntoFilePathList("/usr/lib32/:/usr/local/lib32/",_libraryFilePath);
280
281    // bloody mess see rld(1) man page
282    #if (_MIPS_SIM == _MIPS_SIM_ABI32)
283
284
285    if( (ptr = getenv( "LD_LIBRARY_PATH" )))
286    {
287        convertStringPathIntoFilePathList(ptr,_libraryFilePath);
288    }
289
290    #elif (_MIPS_SIM == _MIPS_SIM_NABI32)
291
292    if( !(ptr = getenv( "LD_LIBRARYN32_PATH" )))
293        ptr = getenv( "LD_LIBRARY_PATH" );
294
295    if( ptr )
296    {
297        convertStringPathIntoFilePathList(ptr,_libraryFilePath);
298    }
299
300    #elif (_MIPS_SIM == _MIPS_SIM_ABI64)
301
302    if( !(ptr = getenv( "LD_LIBRARY64_PATH" )))
303        ptr = getenv( "LD_LIBRARY_PATH" );
304
305    if( ptr )
306    {
307        convertStringPathIntoFilePathList(ptr,_libraryFilePath);
308    }
309    #endif
310   
311#elif defined(__CYGWIN__)
312
313
314    if ((ptr = getenv( "PATH" )))
315    {
316        convertStringPathIntoFilePathList(ptr,_libraryFilePath);
317    }
318
319    convertStringPathIntoFilePathList("/usr/bin/:/usr/local/bin/",_libraryFilePath);
320   
321#elif defined(WIN32)
322
323
324
325    if ((ptr = getenv( "PATH" )))
326    {
327        convertStringPathIntoFilePathList(ptr,_libraryFilePath);
328    }
329
330    convertStringPathIntoFilePathList("C:/Windows/System/",_libraryFilePath);
331
332#elif defined(__APPLE__)
333
334    if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) )
335    {
336        convertStringPathIntoFilePathList(ptr, _libraryFilePath);
337    }
338
339#else   
340
341    if( (ptr = getenv( "LD_LIBRARY_PATH" )) )
342    {
343        convertStringPathIntoFilePathList(ptr,_libraryFilePath);
344    }
345
346    convertStringPathIntoFilePathList("/usr/lib/:/usr/local/lib/",_libraryFilePath);
347
348#endif
349
350    //osg::notify(INFO)<<"Library FilePathList"<<std::endl;
351    //PrintFilePathList(osg::notify(INFO),getLibraryFilePathList());
352
353}
354
355void Registry::readCommandLine(osg::ArgumentParser& arguments)
356{
357    // report the usage options.
358    if (arguments.getApplicationUsage())
359    {
360        arguments.getApplicationUsage()->addCommandLineOption("-l <library>","Load the plugin");
361        arguments.getApplicationUsage()->addCommandLineOption("-e <extension>","Load the plugin associated with handling files with specified extension");
362        arguments.getApplicationUsage()->addCommandLineOption("-O <option_string>","Provide an option string to reader/writers used to load databases");
363    }
364
365    std::string value;
366    while(arguments.read("-l",value))
367    {
368        loadLibrary(value);
369    }
370       
371    while(arguments.read("-e",value))
372    {
373        std::string libName = createLibraryNameForExtension(value);
374        loadLibrary(libName);
375    }
376
377    while(arguments.read("-O",value))
378    {
379        setOptions(new osgDB::ReaderWriter::Options(value));
380    }
381}
382
383void Registry::addDotOsgWrapper(DotOsgWrapper* wrapper)
384{
385    if (wrapper==0L) return;
386
387    //notify(INFO) << "osg::Registry::addDotOsgWrapper("<<wrapper->getName()<<")"<< std::endl;
388    const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
389   
390    for(DotOsgWrapper::Associates::const_iterator itr=assoc.begin();
391                                                  itr!=assoc.end();
392                                                  ++itr)
393    {
394        //notify(INFO) << "    ("<<*itr<<")"<< std::endl;
395    }
396
397    const std::string& name = wrapper->getName();
398    const osg::Object* proto = wrapper->getPrototype();
399
400    _objectWrapperMap[name] = wrapper;
401    if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[name] = wrapper;
402   
403    if (proto)
404    {
405        std::string libraryName = proto->libraryName();
406        std::string compositeName = libraryName + "::" + name;
407
408        _objectWrapperMap[compositeName] = wrapper;
409        if (wrapper->getReadWriteMode()==DotOsgWrapper::READ_AND_WRITE) _classNameWrapperMap[compositeName] = wrapper;
410
411        if (dynamic_cast<const Image*>(proto))
412        {
413            _imageWrapperMap[name] = wrapper;
414            _imageWrapperMap[compositeName] = wrapper;
415        }
416        if (dynamic_cast<const Drawable*>(proto))
417        {
418              _drawableWrapperMap[name] = wrapper;
419              _drawableWrapperMap[compositeName] = wrapper;
420        }
421        if (dynamic_cast<const StateAttribute*>(proto))
422        {
423            _stateAttrWrapperMap[name] = wrapper;
424            _stateAttrWrapperMap[compositeName] = wrapper;
425        }
426        if (dynamic_cast<const Node*>(proto))
427        {
428            _nodeWrapperMap[name] = wrapper;
429            _nodeWrapperMap[compositeName] = wrapper;
430        }
431
432
433    }
434}
435
436// need to change to delete all instances of wrapper, since we
437// now can have a wrapper entered twice with the addition of the
438// library::class composite name.
439void Registry::eraseWrapper(DotOsgWrapperMap& wrappermap,DotOsgWrapper* wrapper)
440{
441    typedef std::vector<DotOsgWrapperMap::iterator> EraseList;
442    EraseList eraseList;
443    for(DotOsgWrapperMap::iterator witr=wrappermap.begin();
444        witr!=wrappermap.end();
445        ++witr)
446    {
447        if (witr->second==wrapper) eraseList.push_back(witr);
448    }
449    for(EraseList::iterator eitr=eraseList.begin();
450        eitr!=eraseList.end();
451        ++eitr)
452    {
453        wrappermap.erase(*eitr);
454    }
455}
456
457void Registry::removeDotOsgWrapper(DotOsgWrapper* wrapper)
458{
459    if (wrapper==0L) return;
460
461    eraseWrapper(_objectWrapperMap,wrapper);
462    eraseWrapper(_classNameWrapperMap,wrapper);
463    eraseWrapper(_imageWrapperMap,wrapper);
464    eraseWrapper(_drawableWrapperMap,wrapper);
465    eraseWrapper(_stateAttrWrapperMap,wrapper);
466    eraseWrapper(_nodeWrapperMap,wrapper);
467}
468
469void Registry::addReaderWriter(ReaderWriter* rw)
470{
471    if (rw==0L) return;
472
473    // notify(INFO) << "osg::Registry::addReaderWriter("<<rw->className()<<")"<< std::endl;
474
475    _rwList.push_back(rw);
476
477}
478
479
480void Registry::removeReaderWriter(ReaderWriter* rw)
481{
482    if (rw==0L) return;
483
484//    notify(INFO) << "osg::Registry::removeReaderWriter();"<< std::endl;
485
486    ReaderWriterList::iterator rwitr = std::find(_rwList.begin(),_rwList.end(),rw);
487    if (rwitr!=_rwList.end())
488    {
489        _rwList.erase(rwitr);
490    }
491
492}
493
494
495void Registry::addFileExtensionAlias(const std::string mapExt, const std::string toExt)
496{
497    if (mapExt!=toExt) _extAliasMap[mapExt] = toExt;
498}
499
500std::string Registry::createLibraryNameForFile(const std::string& fileName)
501{
502    std::string ext = getLowerCaseFileExtension(fileName);
503    return createLibraryNameForExtension(ext);
504}
505
506
507std::string Registry::createLibraryNameForExtension(const std::string& ext)
508{
509
510    ExtensionAliasMap::iterator itr=_extAliasMap.find(ext);
511    if (itr!=_extAliasMap.end()) return createLibraryNameForExtension(itr->second);
512
513#if defined(WIN32)
514    // !! recheck evolving Cygwin DLL extension naming protocols !! NHV
515    #ifdef __CYGWIN__
516        return "cygosgdb_"+ext+".dll";
517    #elif defined(__MINGW32__)
518        return "libosgdb_"+ext+".dll";
519    #else
520        #ifdef _DEBUG
521            return "osgdb_"+ext+"d.dll";
522        #else
523            return "osgdb_"+ext+".dll";
524        #endif
525    #endif
526#elif macintosh
527    return "osgdb_"+ext;
528#elif defined(__hpux__)
529    // why don't we use PLUGIN_EXT from the makefiles here?
530    return "osgdb_"+ext+".sl";
531#else
532    return "osgdb_"+ext+".so";
533#endif
534
535}
536
537std::string Registry::createLibraryNameForNodeKit(const std::string& name)
538{
539#if defined(WIN32)
540    // !! recheck evolving Cygwin DLL extension naming protocols !! NHV
541    #ifdef __CYGWIN__ // [
542    return "cyg"+name+".dll";
543    #elif defined(__MINGW32__)
544        return "lib"+name+".dll";
545    #else
546        #ifdef _DEBUG
547            return name+"d.dll";
548        #else
549            return name+".dll";
550        #endif
551    #endif
552#elif macintosh
553    return name;
554#elif defined(__hpux__)
555    // why don't we use PLUGIN_EXT from the makefiles here?
556    return "lib"+name+".sl";
557#else
558    return "lib"+name+".so";
559#endif
560}
561
562bool Registry::loadLibrary(const std::string& fileName)
563{
564    DynamicLibrary* dl = getLibrary(fileName);
565    if (dl) return false;
566
567    _openingLibrary=true;
568
569    dl = DynamicLibrary::loadLibrary(fileName);
570    _openingLibrary=false;
571
572    if (dl)
573    {
574        _dlList.push_back(dl);
575        return true;
576    }
577    return false;
578}
579
580
581bool Registry::closeLibrary(const std::string& fileName)
582{
583    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
584    if (ditr!=_dlList.end())
585    {
586        _dlList.erase(ditr);
587        return true;
588    }
589    return false;
590}
591
592void Registry::closeAllLibraries()
593{
594    _dlList.clear();
595}
596
597Registry::DynamicLibraryList::iterator Registry::getLibraryItr(const std::string& fileName)
598{
599    DynamicLibraryList::iterator ditr = _dlList.begin();
600    for(;ditr!=_dlList.end();++ditr)
601    {
602        if ((*ditr)->getName()==fileName) return ditr;
603    }
604    return _dlList.end();
605}
606
607DynamicLibrary* Registry::getLibrary(const std::string& fileName)
608{
609    DynamicLibraryList::iterator ditr = getLibraryItr(fileName);
610    if (ditr!=_dlList.end()) return ditr->get();
611    else return NULL;
612}
613
614ReaderWriter* Registry::getReaderWriterForExtension(const std::string& ext)
615{
616    // record the existing reader writer.
617    std::set<ReaderWriter*> rwOriginal;
618
619    // first attemt one of the installed loaders
620    for(ReaderWriterList::iterator itr=_rwList.begin();
621        itr!=_rwList.end();
622        ++itr)
623    {
624        rwOriginal.insert(itr->get());
625        if((*itr)->acceptsExtension(ext)) return (*itr).get();
626    }
627
628    // now look for a plug-in to load the file.
629    std::string libraryName = createLibraryNameForExtension(ext);
630    notify(INFO) << "Now checking for plug-in "<<libraryName<< std::endl;
631    if (loadLibrary(libraryName))
632    {
633        for(ReaderWriterList::iterator itr=_rwList.begin();
634            itr!=_rwList.end();
635            ++itr)
636        {
637            if (rwOriginal.find(itr->get())==rwOriginal.end())
638          if((*itr)->acceptsExtension(ext)) return (*itr).get();
639        }
640    }
641
642    return NULL;
643
644}
645
646struct concrete_wrapper: basic_type_wrapper
647{
648    concrete_wrapper(const osg::Object *myobj) : myobj_(myobj) {}
649    bool matches(const osg::Object *proto) const
650    {
651        return myobj_->isSameKindAs(proto);
652    }
653    const osg::Object *myobj_;
654};
655
656osg::Object* Registry::readObjectOfType(const osg::Object& compObj,Input& fr)
657{
658    return readObjectOfType(concrete_wrapper(&compObj), fr);
659}
660
661osg::Object* Registry::readObjectOfType(const basic_type_wrapper &btw,Input& fr)
662{
663    const char *str = fr[0].getStr();
664    if (str==NULL) return NULL;
665
666    if (fr[0].matchWord("Use"))
667    {
668        if (fr[1].isString())
669        {
670            Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
671            if (obj && btw.matches(obj))
672            {
673                fr+=2;
674                return obj;
675            }
676        }
677        else return NULL;
678
679    }
680
681    std::string name = str;
682    DotOsgWrapperMap::iterator itr = _objectWrapperMap.find(name);
683    if (itr==_objectWrapperMap.end())
684    {
685        // not found so check if a library::class composite name.
686        std::string token = fr[0].getStr();
687        std::string::size_type posDoubleColon = token.rfind("::");
688        if (posDoubleColon != std::string::npos)
689        {
690            // we have a composite name so now strip off the library name
691            // are try to load it, and then retry the readObject to see
692            // if we can recongise the objects.
693       
694            std::string libraryName = std::string(token,0,posDoubleColon);
695
696            // first try the standard nodekit library.
697            std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
698            if (loadLibrary(nodeKitLibraryName)) return readObjectOfType(btw,fr);
699           
700            // otherwise try the osgdb_ plugin library.
701            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
702            if (loadLibrary(pluginLibraryName)) return readObjectOfType(btw,fr);
703        }
704    }
705    else if (fr[1].isOpenBracket())
706    {
707   
708        DotOsgWrapper* wrapper = itr->second.get();
709        const osg::Object* proto = wrapper->getPrototype();
710        if (proto==NULL)
711        {
712            osg::notify(osg::WARN)<<"Token "<<fr[0].getStr()<<" read, but has no prototype, cannot load."<< std::endl;
713            return NULL;
714        }
715       
716        if (!btw.matches(proto))
717        {
718            return NULL;
719        }
720
721        // record the number of nested brackets move the input iterator
722        // over the name { tokens.
723        int entry = fr[0].getNoNestedBrackets();
724        fr+=2;
725
726        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
727        osg::Object* obj = proto->cloneType();
728
729        while(!fr.eof() && fr[0].getNoNestedBrackets()>entry)
730        {
731            bool iteratorAdvanced = false;
732            if (fr[0].matchWord("UniqueID") && fr[1].isString())
733            {
734                fr.regisiterUniqueIDForObject(fr[1].getStr(),obj);
735                fr += 2;
736                iteratorAdvanced = true;
737            }
738
739            // read the local data by iterating through the associate
740            // list, mapping the associate names to DotOsgWrapper's which
741            // in turn have the appropriate functions.
742            for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
743                                                          aitr!=assoc.end();
744                                                          ++aitr)
745            {
746                DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
747                if (mitr==_objectWrapperMap.end())
748                {
749                    // not found so check if a library::class composite name.
750                    std::string token = *aitr;
751                    std::string::size_type posDoubleColon = token.rfind("::");
752                    if (posDoubleColon != std::string::npos)
753                    {
754
755                        // we have a composite name so now strip off the library name
756                        // are try to load it, and then retry the find to see
757                        // if we can recongise the objects.
758
759                        std::string libraryName = std::string(token,0,posDoubleColon);
760
761                        // first try the standard nodekit library.
762                        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
763                        if (loadLibrary(nodeKitLibraryName))
764                        {
765                            mitr = _objectWrapperMap.find(*aitr);
766                        }
767
768                        if (mitr==_objectWrapperMap.end())
769                        {
770                            // otherwise try the osgdb_ plugin library.
771                            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
772                            if (loadLibrary(pluginLibraryName))
773                            {
774                                mitr = _objectWrapperMap.find(*aitr);
775                            }
776                        }
777
778                    }
779                }
780
781                if (mitr!=_objectWrapperMap.end())
782                {
783                    // get the function to read the data...
784                    DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc();
785                    if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true;
786                }
787
788            }
789
790            if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock();
791        }
792        ++fr;                        // step over trailing '}'
793       
794        return obj;
795       
796    }
797    return 0L;
798}
799
800//
801// read object from input iterator.
802//
803osg::Object* Registry::readObject(DotOsgWrapperMap& dowMap,Input& fr)
804{
805    const char *str = fr[0].getStr();
806    if (str==NULL) return NULL;
807
808    std::string name = str;
809    DotOsgWrapperMap::iterator itr = dowMap.find(name);
810    if (itr==dowMap.end())
811    {
812        // not found so check if a library::class composite name.
813        std::string token = fr[0].getStr();
814        std::string::size_type posDoubleColon = token.rfind("::");
815        if (posDoubleColon != std::string::npos)
816        {
817            // we have a composite name so now strip off the library name
818            // are try to load it, and then retry the readObject to see
819            // if we can recongise the objects.
820       
821            std::string libraryName = std::string(token,0,posDoubleColon);
822
823            // first try the standard nodekit library.
824            std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
825            if (loadLibrary(nodeKitLibraryName)) return readObject(dowMap,fr);
826           
827            // otherwise try the osgdb_ plugin library.
828            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
829            if (loadLibrary(pluginLibraryName)) return readObject(dowMap,fr);
830        }
831    }
832    else if (fr[1].isOpenBracket())
833    {
834   
835        DotOsgWrapper* wrapper = itr->second.get();
836        const osg::Object* proto = wrapper->getPrototype();
837        if (proto==NULL)
838        {
839            osg::notify(osg::WARN)<<"Token "<<fr[0].getStr()<<" read, but has no prototype, cannot load."<< std::endl;
840            return NULL;
841        }
842
843        // record the number of nested brackets move the input iterator
844        // over the name { tokens.
845        int entry = fr[0].getNoNestedBrackets();
846        fr+=2;
847
848        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
849        osg::Object* obj = proto->cloneType();
850
851        while(!fr.eof() && fr[0].getNoNestedBrackets()>entry)
852        {
853            bool iteratorAdvanced = false;
854            if (fr[0].matchWord("UniqueID") && fr[1].isString())
855            {
856                fr.regisiterUniqueIDForObject(fr[1].getStr(),obj);
857                fr += 2;
858                iteratorAdvanced = true;
859            }
860
861            // read the local data by iterating through the associate
862            // list, mapping the associate names to DotOsgWrapper's which
863            // in turn have the appropriate functions.
864            for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
865                                                          aitr!=assoc.end();
866                                                          ++aitr)
867            {
868                DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
869                if (mitr==_objectWrapperMap.end())
870                {
871                    // not found so check if a library::class composite name.
872                    std::string token = *aitr;
873                    std::string::size_type posDoubleColon = token.rfind("::");
874                    if (posDoubleColon != std::string::npos)
875                    {
876
877                        // we have a composite name so now strip off the library name
878                        // are try to load it, and then retry the find to see
879                        // if we can recongise the objects.
880
881                        std::string libraryName = std::string(token,0,posDoubleColon);
882
883                        // first try the standard nodekit library.
884                        std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
885                        if (loadLibrary(nodeKitLibraryName))
886                        {
887                            mitr = _objectWrapperMap.find(*aitr);
888                        }
889
890                        if (mitr==_objectWrapperMap.end())
891                        {
892                            // otherwise try the osgdb_ plugin library.
893                            std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
894                            if (loadLibrary(pluginLibraryName))
895                            {
896                                mitr = _objectWrapperMap.find(*aitr);
897                            }
898                        }
899
900                    }
901                }
902
903                if (mitr!=_objectWrapperMap.end())
904                {
905                    // get the function to read the data...
906                    DotOsgWrapper::ReadFunc rf = mitr->second->getReadFunc();
907                    if (rf && (*rf)(*obj,fr)) iteratorAdvanced = true;
908                }
909
910            }
911
912            if (!iteratorAdvanced) fr.advanceOverCurrentFieldOrBlock();
913        }
914        ++fr;                        // step over trailing '}'
915       
916        return obj;
917       
918    }
919
920    return 0L;
921}
922
923//
924// read object from input iterator.
925//
926Object* Registry::readObject(Input& fr)
927{
928    if (fr[0].matchWord("Use"))
929    {
930        if (fr[1].isString())
931        {
932            Object* obj = fr.getObjectForUniqueID(fr[1].getStr());
933            if (obj) fr+=2;
934            return obj;
935        }
936        else return NULL;
937
938    }
939
940    return readObject(_objectWrapperMap,fr);
941}
942
943
944//
945// read image from input iterator.
946//
947Image* Registry::readImage(Input& fr)
948{
949    if (fr[0].matchWord("Use"))
950    {
951        if (fr[1].isString())
952        {
953            Image* image = dynamic_cast<Image*>(fr.getObjectForUniqueID(fr[1].getStr()));
954            if (image) fr+=2;
955            return image;
956        }
957        else return NULL;
958
959    }
960
961    osg::Object* obj = readObject(_imageWrapperMap,fr);
962    osg::Image* image = dynamic_cast<Image*>(obj);
963    if (image) return image;
964    else if (obj) obj->unref();
965   
966    return NULL;
967}
968
969
970//
971// read drawable from input iterator.
972//
973Drawable* Registry::readDrawable(Input& fr)
974{
975    if (fr[0].matchWord("Use"))
976    {
977        if (fr[1].isString())
978        {
979            Drawable* drawable = dynamic_cast<Drawable*>(fr.getObjectForUniqueID(fr[1].getStr()));
980            if (drawable) fr+=2;
981            return drawable;
982        }
983        else return NULL;
984
985    }
986
987    osg::Object* obj = readObject(_drawableWrapperMap,fr);
988    osg::Drawable* drawable = dynamic_cast<Drawable*>(obj);
989    if (drawable) return drawable;
990    else if (obj) obj->unref();
991   
992    return NULL;
993}
994
995//
996// read drawable from input iterator.
997//
998StateAttribute* Registry::readStateAttribute(Input& fr)
999{
1000
1001    if (fr[0].matchWord("Use"))
1002    {
1003        if (fr[1].isString())
1004        {
1005            StateAttribute* attribute = dynamic_cast<StateAttribute*>(fr.getObjectForUniqueID(fr[1].getStr()));
1006            if (attribute) fr+=2;
1007            return attribute;
1008        }
1009        else return NULL;
1010
1011    }
1012
1013    return dynamic_cast<StateAttribute*>(readObject(_stateAttrWrapperMap,fr));
1014}
1015
1016//
1017// read node from input iterator.
1018//
1019Node* Registry::readNode(Input& fr)
1020{
1021    if (fr[0].matchWord("Use"))
1022    {
1023        if (fr[1].isString())
1024        {
1025            Node* node = dynamic_cast<Node*>(fr.getObjectForUniqueID(fr[1].getStr()));
1026            if (node) fr+=2;
1027            return node;
1028        }
1029        else return NULL;
1030
1031    }
1032
1033    osg::Object* obj = readObject(_nodeWrapperMap,fr);
1034    osg::Node* node = dynamic_cast<Node*>(obj);
1035    if (node) return node;
1036    else if (obj) obj->unref();
1037   
1038    return NULL;
1039}
1040
1041//
1042// Write object to output
1043//
1044bool Registry::writeObject(const osg::Object& obj,Output& fw)
1045{
1046
1047    if (obj.referenceCount()>1)
1048    {
1049        std::string uniqueID;
1050        if (fw.getUniqueIDForObject(&obj,uniqueID))
1051        {
1052            fw.indent() << "Use " << uniqueID << std::endl;
1053            return true;
1054        }
1055    }
1056
1057    std::string classname = obj.className();
1058    std::string libraryName = obj.libraryName();
1059    std::string compositeName = libraryName + "::" + classname;
1060
1061    // try composite name first
1062    DotOsgWrapperMap::iterator itr = _classNameWrapperMap.find(compositeName);
1063
1064    // composite name not found, try simple class name
1065    if (itr == _classNameWrapperMap.end()) {
1066        itr = _classNameWrapperMap.find(classname);
1067    }
1068
1069    if (itr==_classNameWrapperMap.end())
1070    {
1071        // first try the standard nodekit library.
1072        std::string nodeKitLibraryName = createLibraryNameForNodeKit(obj.libraryName());
1073        if (loadLibrary(nodeKitLibraryName)) return writeObject(obj,fw);
1074
1075        // otherwise try the osgdb_ plugin library.
1076        std::string pluginLibraryName = createLibraryNameForExtension(obj.libraryName());
1077        if (loadLibrary(pluginLibraryName)) return writeObject(obj,fw);
1078    }
1079    else
1080    {
1081   
1082   
1083        DotOsgWrapper* wrapper = itr->second.get();
1084        const DotOsgWrapper::Associates& assoc = wrapper->getAssociates();
1085
1086        if (strcmp(obj.libraryName(),"osg")==0)
1087        {
1088            // member of the core osg, so no need to have composite library::class name.
1089            fw.indent() << wrapper->getName() << " {"<< std::endl;
1090            fw.moveIn();
1091        }
1092        else
1093        {
1094            // member of the node kit so must use composite library::class name.
1095            std::string::size_type posDoubleColon = wrapper->getName().find("::");
1096            if (posDoubleColon != std::string::npos)
1097            {
1098                fw.indent() << wrapper->getName() << " {"<< std::endl;
1099            }
1100            else
1101            {
1102                fw.indent() << obj.libraryName()<<"::"<< wrapper->getName() << " {"<< std::endl;
1103            }
1104
1105            fw.moveIn();
1106        }
1107
1108
1109        // write out the unique ID if required.
1110        if (obj.referenceCount()>1)
1111        {
1112            std::string uniqueID;
1113            fw.createUniqueIDForObject(&obj,uniqueID);
1114            fw.registerUniqueIDForObject(&obj,uniqueID);
1115            fw.indent() << "UniqueID " << uniqueID << std::endl;
1116        }
1117
1118        // read the local data by iterating through the associate
1119        // list, mapping the associate names to DotOsgWrapper's which
1120        // in turn have the appropriate functions.
1121        for(DotOsgWrapper::Associates::const_iterator aitr=assoc.begin();
1122                                                      aitr!=assoc.end();
1123                                                      ++aitr)
1124        {
1125            DotOsgWrapperMap::iterator mitr = _objectWrapperMap.find(*aitr);
1126            if (mitr==_objectWrapperMap.end())
1127            {
1128                // not found so check if a library::class composite name.
1129                std::string token = *aitr;
1130                std::string::size_type posDoubleColon = token.rfind("::");
1131                if (posDoubleColon != std::string::npos)
1132                {
1133
1134                    // we have a composite name so now strip off the library name
1135                    // are try to load it, and then retry the find to see
1136                    // if we can recongise the objects.
1137
1138                    std::string libraryName = std::string(token,0,posDoubleColon);
1139
1140                    // first try the standard nodekit library.
1141                    std::string nodeKitLibraryName = createLibraryNameForNodeKit(libraryName);
1142                    if (loadLibrary(nodeKitLibraryName))
1143                    {
1144                        mitr = _objectWrapperMap.find(*aitr);
1145                    }
1146
1147                    if (mitr==_objectWrapperMap.end())
1148                    {
1149                        // otherwise try the osgdb_ plugin library.
1150                        std::string pluginLibraryName = createLibraryNameForExtension(libraryName);
1151                        if (loadLibrary(pluginLibraryName))
1152                        {
1153                            mitr = _objectWrapperMap.find(*aitr);
1154                        }
1155                    }
1156
1157                }
1158            }
1159            if (mitr!=_objectWrapperMap.end())
1160            {
1161                // get the function to read the data...
1162                DotOsgWrapper::WriteFunc wf = mitr->second->getWriteFunc();
1163                if (wf) (*wf)(obj,fw);
1164            }
1165
1166        }
1167
1168        fw.moveOut();
1169        fw.indent() << "}"<< std::endl;
1170
1171        return true;
1172    }
1173   
1174    return false;
1175}
1176
1177//
1178// read object from specified file.
1179//
1180ReaderWriter::ReadResult Registry::readObject(const std::string& fileName)
1181{
1182    // record the errors reported by readerwriters.
1183    typedef std::vector<ReaderWriter::ReadResult> Results;
1184    Results results;
1185
1186    // first attempt to load the file from existing ReaderWriter's
1187    AvailableReaderWriterIterator itr(_rwList);
1188    for(;itr.valid();++itr)
1189    {
1190        ReaderWriter::ReadResult rr = itr->readObject(fileName,_options.get());
1191        if (rr.validObject()) return rr;
1192        else results.push_back(rr);
1193    }
1194
1195    if (!results.empty())
1196    {
1197        unsigned int num_FILE_NOT_HANDLED = 0;
1198        unsigned int num_FILE_NOT_FOUND = 0;
1199        unsigned int num_ERROR_IN_READING_FILE = 0;
1200
1201        for(Results::iterator ritr=results.begin();
1202            ritr!=results.end();
1203            ++ritr)
1204        {
1205            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1206            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1207            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1208        }
1209       
1210        if (num_FILE_NOT_HANDLED!=results.size())
1211        {
1212            // we've come across a file not found or error in reading file.
1213            if (num_ERROR_IN_READING_FILE)
1214            {
1215                osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<fileName<<"\""<<std::endl;
1216                return NULL;
1217            }
1218            else if (num_FILE_NOT_FOUND)
1219            {
1220                osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<fileName<<"\""<<std::endl;
1221                return NULL;
1222            }
1223        }
1224    }
1225
1226    // now look for a plug-in to load the file.
1227    std::string libraryName = createLibraryNameForFile(fileName);
1228    if (loadLibrary(libraryName))
1229    {
1230        for(;itr.valid();++itr)
1231        {
1232            ReaderWriter::ReadResult rr = itr->readObject(fileName,_options.get());
1233            if (rr.validObject()) return rr;
1234            else results.push_back(rr);
1235        }
1236    }
1237   
1238    if (results.empty())
1239    {
1240        return ReaderWriter::ReadResult("Warning: Could not find plugin to read objects from file \""+fileName+"\".");
1241    }
1242   
1243
1244    return results.front();
1245}
1246
1247ReaderWriter::ReadResult Registry::readObjectImplementation(const std::string& constFile,CacheHintOptions useObjectCache)
1248{
1249    std::string file(constFile);
1250
1251    if (useObjectCache & CACHE_OBJECTS)
1252    {
1253        // search for entry in the object cache.
1254        ObjectCache::iterator oitr=_objectCache.find(file);
1255        if (oitr!=_objectCache.end())
1256        {
1257            notify(INFO)<<"returning cached instanced of "<<file<<std::endl;
1258            osg::Object* object = oitr->second.first.get();
1259            if (object) return ReaderWriter::ReadResult(object, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
1260            else return ReaderWriter::ReadResult("Error file does not contain an osg::Object");
1261        }
1262
1263        PushAndPopDataPath tmpfile(getFilePath(file));
1264
1265        ReaderWriter::ReadResult rr = readObject(file);
1266        if (rr.validObject())
1267        {
1268            // update cache with new entry.
1269            notify(INFO)<<"Adding to cache object "<<file<<std::endl;
1270            addEntryToObjectCache(file,rr.getObject());
1271        }
1272       
1273        return rr;
1274
1275    }
1276    else
1277    {
1278   
1279        ObjectCache tmpObjectCache;
1280        tmpObjectCache.swap(_objectCache);
1281
1282        PushAndPopDataPath tmpfile(getFilePath(file));
1283
1284        ReaderWriter::ReadResult rr = readObject(file);
1285
1286        tmpObjectCache.swap(_objectCache);
1287
1288        return rr;
1289
1290    }
1291}
1292
1293ReaderWriter::WriteResult Registry::writeObjectImplementation(const Object& obj,const std::string& fileName)
1294{
1295    // record the errors reported by readerwriters.
1296    typedef std::vector<ReaderWriter::WriteResult> Results;
1297    Results results;
1298
1299    // first attempt to load the file from existing ReaderWriter's
1300    AvailableReaderWriterIterator itr(_rwList);
1301    for(;itr.valid();++itr)
1302    {
1303        ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,_options.get());
1304        if (rr.success()) return rr;
1305        else results.push_back(rr);
1306    }
1307
1308    // now look for a plug-in to save the file.
1309    std::string libraryName = createLibraryNameForFile(fileName);
1310    if (loadLibrary(libraryName))
1311    {
1312        for(;itr.valid();++itr)
1313        {
1314            ReaderWriter::WriteResult rr = itr->writeObject(obj,fileName,_options.get());
1315            if (rr.success()) return rr;
1316            else results.push_back(rr);
1317        }
1318    }
1319
1320    if (results.empty())
1321    {
1322        return ReaderWriter::WriteResult("Warning: Could not find plugin to write objects to file \""+fileName+"\".");
1323    }
1324
1325    return results.front();
1326}
1327
1328ReaderWriter::ReadResult Registry::readImage(const std::string& fileName)
1329{
1330    // record the errors reported by readerwriters.
1331    typedef std::vector<ReaderWriter::ReadResult> Results;
1332    Results results;
1333
1334    // first attempt to load the file from existing ReaderWriter's
1335    AvailableReaderWriterIterator itr(_rwList);
1336    for(;itr.valid();++itr)
1337    {
1338        ReaderWriter::ReadResult rr = itr->readImage(fileName,_options.get());
1339        if (rr.validImage())  return rr;
1340        else results.push_back(rr);
1341    }
1342
1343    if (!results.empty())
1344    {
1345        unsigned int num_FILE_NOT_HANDLED = 0;
1346        unsigned int num_FILE_NOT_FOUND = 0;
1347        unsigned int num_ERROR_IN_READING_FILE = 0;
1348
1349        for(Results::iterator ritr=results.begin();
1350            ritr!=results.end();
1351            ++ritr)
1352        {
1353            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1354            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1355            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1356        }
1357       
1358        if (num_FILE_NOT_HANDLED!=results.size())
1359        {
1360            // we've come across a file not found or error in reading file.
1361            if (num_ERROR_IN_READING_FILE)
1362            {
1363                osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<fileName<<"\""<<std::endl;
1364                return NULL;
1365            }
1366            else if (num_FILE_NOT_FOUND)
1367            {
1368                osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<fileName<<"\""<<std::endl;
1369                return NULL;
1370            }
1371        }
1372    }
1373
1374    // now look for a plug-in to load the file.
1375    std::string libraryName = createLibraryNameForFile(fileName);
1376    if (loadLibrary(libraryName))
1377    {
1378        for(;itr.valid();++itr)
1379        {
1380            ReaderWriter::ReadResult rr = itr->readImage(fileName,_options.get());
1381            if (rr.validImage()) return rr;
1382            else results.push_back(rr);
1383        }
1384    }
1385
1386    if (results.empty())
1387    {
1388        return ReaderWriter::ReadResult("Warning: Could not find plugin to read image from file \""+fileName+"\".");
1389    }
1390
1391    return results.front();
1392}
1393
1394
1395ReaderWriter::ReadResult Registry::readImageImplementation(const std::string& file,CacheHintOptions useObjectCache)
1396{
1397    if (useObjectCache & CACHE_IMAGES)
1398    {
1399        // search for entry in the object cache.
1400        ObjectCache::iterator oitr=_objectCache.find(file);
1401        if (oitr!=_objectCache.end())
1402        {
1403            notify(INFO)<< "returning cached instanced of "<<file<<std::endl;
1404            osg::Image* image = dynamic_cast<osg::Image*>(oitr->second.first.get());
1405            if (image) return ReaderWriter::ReadResult(image, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
1406            else return ReaderWriter::ReadResult("Error file not of type osg::Image");
1407        }
1408
1409        PushAndPopDataPath tmpfile(getFilePath(file));
1410
1411        ReaderWriter::ReadResult rr = readImage(file);
1412        if (rr.validImage())
1413        {
1414            // update cache with new entry.
1415            notify(INFO)<<"Adding to cache image "<<file<<std::endl;
1416            addEntryToObjectCache(file,rr.getObject());
1417        }
1418        else
1419            return ReaderWriter::ReadResult("Warning: file \""+file+"\" not found.");
1420       
1421        return rr;
1422
1423    }
1424    else
1425    {
1426   
1427        ObjectCache tmpObjectCache;
1428        tmpObjectCache.swap(_objectCache);
1429
1430        PushAndPopDataPath tmpfile(getFilePath(file));
1431
1432        ReaderWriter::ReadResult rr = readImage(file);
1433
1434        tmpObjectCache.swap(_objectCache);
1435
1436        return rr;
1437
1438    }
1439}
1440
1441
1442
1443ReaderWriter::WriteResult Registry::writeImageImplementation(const Image& image,const std::string& fileName)
1444{
1445    // record the errors reported by readerwriters.
1446    typedef std::vector<ReaderWriter::WriteResult> Results;
1447    Results results;
1448
1449    // first attempt to load the file from existing ReaderWriter's
1450    AvailableReaderWriterIterator itr(_rwList);
1451    for(;itr.valid();++itr)
1452    {
1453        ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,_options.get());
1454        if (rr.success()) return rr;
1455        else results.push_back(rr);
1456    }
1457
1458    // now look for a plug-in to save the file.
1459    std::string libraryName = createLibraryNameForFile(fileName);
1460    if (loadLibrary(libraryName))
1461    {
1462        for(;itr.valid();++itr)
1463        {
1464            ReaderWriter::WriteResult rr = itr->writeImage(image,fileName,_options.get());
1465            if (rr.success()) return rr;
1466            else results.push_back(rr);
1467        }
1468    }
1469
1470    if (results.empty())
1471    {
1472        return ReaderWriter::WriteResult("Warning: Could not find plugin to write image to file \""+fileName+"\".");
1473    }
1474   
1475    return results.front();
1476}
1477
1478ReaderWriter::ReadResult Registry::readHeightField(const std::string& fileName)
1479{
1480    // record the errors reported by readerwriters.
1481    typedef std::vector<ReaderWriter::ReadResult> Results;
1482    Results results;
1483
1484    // first attempt to load the file from existing ReaderWriter's
1485    AvailableReaderWriterIterator itr(_rwList);
1486    for(;itr.valid();++itr)
1487    {
1488        ReaderWriter::ReadResult rr = itr->readHeightField(fileName,_options.get());
1489        if (rr.validHeightField())  return rr;
1490        else results.push_back(rr);
1491    }
1492
1493    if (!results.empty())
1494    {
1495        unsigned int num_FILE_NOT_HANDLED = 0;
1496        unsigned int num_FILE_NOT_FOUND = 0;
1497        unsigned int num_ERROR_IN_READING_FILE = 0;
1498
1499        for(Results::iterator ritr=results.begin();
1500            ritr!=results.end();
1501            ++ritr)
1502        {
1503            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1504            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1505            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1506        }
1507       
1508        if (num_FILE_NOT_HANDLED!=results.size())
1509        {
1510            // we've come across a file not found or error in reading file.
1511            if (num_ERROR_IN_READING_FILE)
1512            {
1513                osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<fileName<<"\""<<std::endl;
1514                return NULL;
1515            }
1516            else if (num_FILE_NOT_FOUND)
1517            {
1518                osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<fileName<<"\""<<std::endl;
1519                return NULL;
1520            }
1521        }
1522    }
1523
1524    // now look for a plug-in to load the file.
1525    std::string libraryName = createLibraryNameForFile(fileName);
1526    if (loadLibrary(libraryName))
1527    {
1528        for(;itr.valid();++itr)
1529        {
1530            ReaderWriter::ReadResult rr = itr->readHeightField(fileName,_options.get());
1531            if (rr.validHeightField()) return rr;
1532            else  results.push_back(rr);
1533        }
1534    }
1535
1536    if (results.empty())
1537    {
1538        return ReaderWriter::ReadResult("Warning: Could not find plugin to read HeightField from file \""+fileName+"\".");
1539    }
1540
1541    return results.front();
1542}
1543
1544
1545ReaderWriter::ReadResult Registry::readHeightFieldImplementation(const std::string& file,CacheHintOptions useObjectCache)
1546{
1547    if (useObjectCache & CACHE_HEIGHTFIELDS)
1548    {
1549        // search for entry in the object cache.
1550        ObjectCache::iterator oitr=_objectCache.find(file);
1551        if (oitr!=_objectCache.end())
1552        {
1553            notify(INFO)<< "returning cached instanced of "<<file<<std::endl;
1554            osg::HeightField* heightField = dynamic_cast<osg::HeightField*>(oitr->second.first.get());
1555            if (heightField) return ReaderWriter::ReadResult(heightField, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
1556            else return ReaderWriter::ReadResult("Error file not of type osg::HeightField");
1557        }
1558
1559        PushAndPopDataPath tmpfile(getFilePath(file));
1560
1561        ReaderWriter::ReadResult rr = readHeightField(file);
1562        if (rr.validHeightField())
1563        {
1564            // update cache with new entry.
1565            notify(INFO)<<"Adding to cache HeightField "<<file<<std::endl;
1566            addEntryToObjectCache(file,rr.getObject());
1567        }
1568        else
1569            return ReaderWriter::ReadResult("Warning: file \""+file+"\" not found.");
1570       
1571        return rr;
1572
1573    }
1574    else
1575    {
1576   
1577        ObjectCache tmpObjectCache;
1578        tmpObjectCache.swap(_objectCache);
1579
1580        PushAndPopDataPath tmpfile(getFilePath(file));
1581
1582        ReaderWriter::ReadResult rr = readHeightField(file);
1583
1584        tmpObjectCache.swap(_objectCache);
1585
1586        return rr;
1587
1588    }
1589}
1590
1591
1592
1593ReaderWriter::WriteResult Registry::writeHeightFieldImplementation(const HeightField& HeightField,const std::string& fileName)
1594{
1595    // record the errors reported by readerwriters.
1596    typedef std::vector<ReaderWriter::WriteResult> Results;
1597    Results results;
1598
1599    // first attempt to load the file from existing ReaderWriter's
1600    AvailableReaderWriterIterator itr(_rwList);
1601    for(;itr.valid();++itr)
1602    {
1603        ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,_options.get());
1604        if (rr.success()) return rr;
1605        else results.push_back(rr);
1606    }
1607
1608    // now look for a plug-in to save the file.
1609    std::string libraryName = createLibraryNameForFile(fileName);
1610    if (loadLibrary(libraryName))
1611    {
1612        for(;itr.valid();++itr)
1613        {
1614            ReaderWriter::WriteResult rr = itr->writeHeightField(HeightField,fileName,_options.get());
1615            if (rr.success()) return rr;
1616            else results.push_back(rr);
1617        }
1618    }
1619
1620    if (results.empty())
1621    {
1622        return ReaderWriter::WriteResult("Warning: Could not find plugin to write HeightField to file \""+fileName+"\".");
1623    }
1624   
1625    return results.front();
1626}
1627
1628
1629
1630ReaderWriter::ReadResult Registry::readNode(const std::string& fileName)
1631{
1632    // record the errors reported by readerwriters.
1633    typedef std::vector<ReaderWriter::ReadResult> Results;
1634    Results results;
1635
1636    AvailableReaderWriterIterator itr(_rwList);
1637    for(;itr.valid();++itr)
1638    {
1639        ReaderWriter::ReadResult rr = itr->readNode(fileName,_options.get());
1640        if (rr.validNode())  return rr;
1641        else results.push_back(rr);
1642    }
1643
1644    if (!results.empty())
1645    {
1646        unsigned int num_FILE_NOT_HANDLED = 0;
1647        unsigned int num_FILE_NOT_FOUND = 0;
1648        unsigned int num_ERROR_IN_READING_FILE = 0;
1649
1650        for(Results::iterator ritr=results.begin();
1651            ritr!=results.end();
1652            ++ritr)
1653        {
1654            if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_HANDLED) ++num_FILE_NOT_HANDLED;
1655            else if (ritr->status()==ReaderWriter::ReadResult::FILE_NOT_FOUND) ++num_FILE_NOT_FOUND;
1656            else if (ritr->status()==ReaderWriter::ReadResult::ERROR_IN_READING_FILE) ++num_ERROR_IN_READING_FILE;
1657        }
1658       
1659        if (num_FILE_NOT_HANDLED!=results.size())
1660        {
1661            // we've come across a file not found or error in reading file.
1662            if (num_ERROR_IN_READING_FILE)
1663            {
1664                osg::notify(osg::NOTICE)<<"Warning: error reading file \""<<fileName<<"\""<<std::endl;
1665                return NULL;
1666            }
1667            else if (num_FILE_NOT_FOUND)
1668            {
1669                osg::notify(osg::NOTICE)<<"Warning: could not find file \""<<fileName<<"\""<<std::endl;
1670                return NULL;
1671            }
1672        }
1673    }
1674   
1675    // now look for a plug-in to load the file.
1676    std::string libraryName = createLibraryNameForFile(fileName);
1677    notify(INFO) << "Now checking for plug-in "<<libraryName<< std::endl;
1678    if (loadLibrary(libraryName))
1679    {
1680        for(;itr.valid();++itr)
1681        {
1682            ReaderWriter::ReadResult rr = itr->readNode(fileName,_options.get());
1683            if (rr.validNode()) return rr;
1684            else results.push_back(rr);
1685        }
1686    }
1687
1688
1689    // need to sort out.
1690    CacheHintOptions useObjectCache = CACHE_ALL;
1691
1692    if (_createNodeFromImage)
1693    {
1694        ReaderWriter::ReadResult rr = readImage(fileName,useObjectCache);
1695        if (rr.validImage()) return createGeodeForImage(rr.takeImage());
1696        //else results.push_back(rr);
1697    }
1698
1699    if (results.empty())
1700    {
1701        return ReaderWriter::ReadResult("Warning: Could not find plugin to read nodes from file \""+fileName+"\".");
1702    }
1703
1704    return results.front();
1705}
1706
1707ReaderWriter::ReadResult Registry::readNodeImplementation(const std::string& file,CacheHintOptions useObjectCache)
1708{
1709    if (useObjectCache & CACHE_NODES)
1710    {
1711        // search for entry in the object cache.
1712        ObjectCache::iterator oitr=_objectCache.find(file);
1713        if (oitr!=_objectCache.end())
1714        {
1715            notify(INFO)<< "returning cached instanced of "<<file<<std::endl;
1716            osg::Node* node = dynamic_cast<osg::Node*>(oitr->second.first.get());
1717            if (node) return ReaderWriter::ReadResult(node, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE);
1718            else return ReaderWriter::ReadResult("Error file not of type osg::Node");
1719        }
1720
1721        PushAndPopDataPath tmpfile(getFilePath(file));
1722
1723        ReaderWriter::ReadResult rr = readNode(file);
1724        if (rr.validNode())
1725        {
1726            // update cache with new entry.
1727            notify(INFO)<<"Adding to cache node "<<file<<std::endl;
1728            addEntryToObjectCache(file,rr.getObject());
1729        }
1730       
1731        return rr;
1732
1733    }
1734    else
1735    {
1736   
1737        ObjectCache tmpObjectCache;
1738        tmpObjectCache.swap(_objectCache);
1739
1740        PushAndPopDataPath tmpfile(getFilePath(file));
1741
1742        ReaderWriter::ReadResult rr = readNode(file);
1743
1744        tmpObjectCache.swap(_objectCache);
1745
1746        return rr;
1747
1748    }
1749}
1750
1751ReaderWriter::WriteResult Registry::writeNodeImplementation(const Node& node,const std::string& fileName)
1752{
1753    // record the errors reported by readerwriters.
1754    typedef std::vector<ReaderWriter::WriteResult> Results;
1755    Results results;
1756
1757    // first attempt to write the file from existing ReaderWriter's
1758    AvailableReaderWriterIterator itr(_rwList);
1759    for(;itr.valid();++itr)
1760    {
1761        ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,_options.get());
1762        if (rr.success()) return rr;
1763        else results.push_back(rr);
1764    }
1765
1766    // now look for a plug-in to save the file.
1767    std::string libraryName = createLibraryNameForFile(fileName);
1768    if (loadLibrary(libraryName))
1769    {
1770        for(;itr.valid();++itr)
1771        {
1772            ReaderWriter::WriteResult rr = itr->writeNode(node,fileName,_options.get());
1773            if (rr.success()) return rr;
1774            else results.push_back(rr);
1775        }
1776    }
1777
1778    if (results.empty())
1779    {
1780        return ReaderWriter::WriteResult("Warning: Could not find plugin to write nodes to file \""+fileName+"\".");
1781    }
1782
1783    return results.front();
1784}
1785
1786void Registry::convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath)
1787{
1788#if defined(WIN32) && !defined(__CYGWIN__)
1789    char delimitor = ';';
1790#else
1791    char delimitor = ':';
1792#endif
1793
1794    if (!paths.empty())
1795    {
1796        std::string::size_type start = 0;
1797        std::string::size_type end;
1798        while ((end = paths.find_first_of(delimitor,start))!=std::string::npos)
1799        {
1800            filepath.push_back(std::string(paths,start,end-start));
1801            start = end+1;
1802        }
1803
1804        filepath.push_back(std::string(paths,start,std::string::npos));
1805    }
1806 
1807}
1808
1809void Registry::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp)
1810{
1811     _objectCache[filename]=ObjectTimeStampPair(object,timestamp);
1812}
1813
1814void Registry::updateTimeStampOfObjectsInCacheWithExtenalReferences(double currentTime)
1815{
1816
1817    // look for objects with external references and update their time stamp.
1818    for(ObjectCache::iterator itr=_objectCache.begin();
1819        itr!=_objectCache.end();
1820        ++itr)
1821    {
1822        // if ref count is greater the 1 the object has an external reference.
1823        if (itr->second.first->referenceCount()>1)
1824        {
1825            // so update it time stamp.
1826            itr->second.second = currentTime;
1827        }
1828    }
1829}
1830
1831void Registry::removeExpiredObjectsInCache(double expiryTime)
1832{
1833    typedef std::vector<std::string> ObjectsToRemove;
1834    ObjectsToRemove objectsToRemove;
1835
1836    // first collect all the exprired entries in the ObjectToRemove list.
1837    for(ObjectCache::iterator oitr=_objectCache.begin();
1838        oitr!=_objectCache.end();
1839        ++oitr)
1840    {
1841        if (oitr->second.second<=expiryTime)
1842        {
1843            // record the filename of the entry to use as key for deleting
1844            // afterwards/
1845            objectsToRemove.push_back(oitr->first);
1846        }
1847    }
1848   
1849    // remove the entries from the _objectCaache.
1850    for(ObjectsToRemove::iterator ritr=objectsToRemove.begin();
1851        ritr!=objectsToRemove.end();
1852        ++ritr)
1853    {
1854        // std::cout<<"Removing from Registry object cache '"<<*ritr<<"'"<<std::endl;
1855        _objectCache.erase(*ritr);
1856    }
1857       
1858}
1859
1860void Registry::clearObjectCache()
1861{
1862    _objectCache.clear();
1863}
1864
1865DatabasePager* Registry::getOrCreateDatabasePager()
1866{
1867    if (!_databasePager) _databasePager = new DatabasePager;
1868   
1869    return _databasePager.get();
1870}
1871
1872SharedStateManager* Registry::getOrCreateSharedStateManager()
1873{
1874    if (!_sharedStateManager) _sharedStateManager = new SharedStateManager;
1875   
1876    return _sharedStateManager.get();
1877}
Note: See TracBrowser for help on using the browser.