<commit_before>#include <iostream>
#include <fstream>
#include <sstream>

#include <osg/Notify>

#include <osgDB/Input>
#include <osgDB/Registry>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgDB/FileUtils>
#include <osg/MatrixTransform>
#include <osg/Group>
#include <osg/Timer>
#include "sockinet.h"

 /*
  *  Semantics:
  *    Two methods for using the .net loader.
  *      1) Add a hostname prefix and a '.net' suffix on a model when passing
  *          to osgDB::readNodeFile()
  *          e.g:    osgDB::readNodeFile( "openscenegraph.org:cow.osg.net" );
  *
  *     2) Explicitely load the .net plugin and pass the plugin options including
  *           hostname=<hostname>
  *
  *    Method #1 takes precedence.  SO, if the hostname option is passed the
  *    plugin, but the name also contains a hostname prefix, the hostname
  *    prefix on the file name will override the option
  *
  *  Plugin options:
  *           hostname=<hostname>     - Specify the host where the data file is to
  *                                     be fetched from.
  *
  *           prefix=<prefix>         - Specify a server directory to prefix the
  *                                     file name with.
  *
  *           local_cache_dir=<dir>   - Specify a directory in which to cache files
  *                                     on the local machine once they've been fetched.
  *                                     This directory is also searched before fetching
  *                                     the file from the server when Read mode is
  *                                     enabled on the cache.
  *
  *           cache_mode=<mode>       - Set the mode for the local cache if local_cache
  *                                     was specified.  If local_cache was not specified
  *                                     this directive is ignored.  <mode> may
  *                                     be specified with ReadOnly, WriteOnly, or
  *                                     ReadWrite.  Behavior for the different modes is
  *                                     defined as:
  *
  *                                       ReadOnly   - When retrieving files, cache is
  *                                                    searched first, and if the file is
  *                                                    not present, it is fetched from the
  *                                                    server.  If it is fetched from the
  *                                                    server it is not stored in local cache
  *
  *                                       WriteOnly  - When retrieving files, cache is not
  *                                                    searched, file is always retrieved
  *                                                    from the server and always written to
  *                                                    cache.
  *
  *                                       ReadWrite  - (the default).  When retrieving files
  *                                                    cache is searched first, if file is
  *                                                    not present in cache, it is fetched from
  *                                                    the server.  If fetched, it is written
  *                                                    to cache.
  *
  */

class NetReader : public osgDB::ReaderWriter
{
    public:
        NetReader() {}

        virtual const char* className() { return "HTTP Protocol Model Reader"; }

        virtual bool acceptsExtension(const std::string& extension)
        {
            return osgDB::equalCaseInsensitive(extension,"net");
        }

        enum ObjectType
        {
            OBJECT,
            IMAGE,
            HEIGHTFIELD,
            NODE
        };

        virtual ReadResult readObject(const std::string& fileName, const Options* options)
        {
            return readFile(OBJECT,fileName,options);
        }

        virtual ReadResult readImage(const std::string& fileName, const Options *options)
        {
            return readFile(IMAGE,fileName,options);
        }

        virtual ReadResult readHeightField(const std::string& fileName, const Options *options)
        {
            return readFile(HEIGHTFIELD,fileName,options);
        }

        virtual ReadResult readNode(const std::string& fileName, const Options *options)
        {
            return readFile(NODE,fileName,options);
        }

        ReadResult readFile(ObjectType objectType, ReaderWriter* rw, std::istream& fin, const Options *options)
        {
            switch(objectType)
            {
            case(OBJECT): return rw->readObject(fin,options);
            case(IMAGE): return rw->readImage(fin,options);
            case(HEIGHTFIELD): return rw->readHeightField(fin,options);
            case(NODE): return rw->readNode(fin,options);
            default: break;
            }
        }

        virtual ReadResult readFile(ObjectType objectType, const std::string& inFileName, const Options *options)
        {
            osg::Timer_t start = osg::Timer::instance()->tick();

            osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: start load" << inFileName << std::endl;

            std::string hostname;
            std::string serverPrefix;
            std::string localCacheDir;
            int port = 80;

            enum CacheMode {
                Read      = 1,
                Write     = 2,
                ReadWrite = 3
            };

            CacheMode cacheMode = ReadWrite;

            if (options)
            {
                std::istringstream iss(options->getOptionString());
                std::string opt;
                while (iss >> opt)
                {
                    int index = opt.find( "=" );
                    if( opt.substr( 0, index ) == "hostname" ||
                        opt.substr( 0, index ) == "HOSTNAME" )
                    {
                        hostname = opt.substr( index+1 );
                    }
                    else if( opt.substr( 0, index ) == "port" ||
                             opt.substr( 0, index ) == "PORT" )
                    {
                        port = atoi( opt.substr(index+1).c_str() );
                    }
                    else if( opt.substr( 0, index ) == "server_prefix" ||
                             opt.substr( 0, index ) == "SERVER_PREFIX" ||
                             opt.substr( 0, index ) == "prefix" ||
                             opt.substr( 0, index ) == "PREFIX" )
                    {
                        serverPrefix = opt.substr(index+1);
                    }
                    else if( opt.substr( 0, index ) == "local_cache_dir" ||
                             opt.substr( 0, index ) == "LOCAL_CACHE_DIR" )
                    {
                        localCacheDir = opt.substr(index+1);
                    }
                    else if( opt.substr( 0, index ) == "cache_mode" ||
                             opt.substr( 0, index ) == "CACHE_MODE" )
                    {
                        if( opt.substr(index+1) == "ReadOnly" )
                            cacheMode = Read;
                        else if(  opt.substr(index+1) == "WriteOnly" )
                            cacheMode = Write;
                        else if(  opt.substr(index+1) == "ReadWrite" )
                            cacheMode = ReadWrite;
                        else
                            osg::notify(osg::WARN) <<
                                "NET plug-in warning:  cache_mode " << opt.substr(index+1) <<
                                " not understood.  Defaulting to ReadWrite." << std::endl;
                    }
                }
            }

            ReadResult readResult = ReadResult::FILE_NOT_HANDLED;

            /* * we accept all extensions
            std::string ext = osgDB::getFileExtension(inFileName);
            if (!acceptsExtension(ext))
                return ReadResult::FILE_NOT_HANDLED;
                */

            std::string fileName;
            int index = inFileName.find(":");
            // If we haven't been given a hostname as an option
            // and it hasn't been prefixed to the name, we fail
            if( index != -1 )
            {
                hostname = inFileName.substr( 0, index);
                // need to strip the inFileName of the hostname prefix
                fileName = inFileName.substr( index+1 );
            }
            else
            {
                if( hostname.empty() )
                    return ReadResult::FILE_NOT_HANDLED;
                else
                    fileName = inFileName;
            }

            // Let's also strip the possible .net extension
            if( osgDB::getFileExtension( fileName ) == "net" )
            {
                int rindex = fileName.rfind( "." );
                fileName = fileName.substr( 0, rindex );
            }

            if( !serverPrefix.empty() )
                fileName = serverPrefix + '/' + fileName;

            // Invoke the reader corresponding to the extension
            osgDB::ReaderWriter *reader =
                    osgDB::Registry::instance()->getReaderWriterForExtension( osgDB::getFileExtension(fileName));
            if( reader == 0L )
                return ReadResult::FILE_NOT_HANDLED;

            // Before we go to the network, lets see if it is in local cache, if cache
            // was specified and Read bit is set
            if( !localCacheDir.empty() && (cacheMode & Read) )
            {
                std::string cacheFile = localCacheDir + '/' + fileName;
                if( osgDB::fileExists( cacheFile ))
                {
                    std::ifstream  in(cacheFile.c_str());
                    readResult = readFile(objectType, reader, in, options );

                    in.close();
                    osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " fetched from local cache." << std::endl;
                    return readResult;
                }
            }

            // Fetch from the network
            iosockinet  sio (sockbuf::sock_stream);
            try {
                sio->connect( hostname.c_str(), port );
            }
            catch( sockerr e )
            {
                osg::notify(osg::WARN) << "osgPlugin .net reader: Unable to connect to host " << hostname << std::endl;
                return ReadResult::FILE_NOT_FOUND;
            }

            sio << "GET /" << fileName << " HTTP/1.1\n" << "Host:\n\n";
            sio.flush();

            char linebuff[256];
            do
            {
                sio.getline( linebuff, sizeof( linebuff ));

                std::istringstream iss(linebuff);
                std::string directive;
                iss >> directive;
                if( directive.substr(0,4) == "HTTP" )
                {
                    iss >> directive;
                    // Code 200.  We be ok.
                    if( directive == "200" )
                        ;
                    // Code 400 Bad Request
                    else if( directive == "400" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 400 - Bad Request" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 401 Bad Request
                    else if( directive == "401" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 401 - Unauthorized Access" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 403 Bad Request
                    else if( directive == "403" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 403 - Access Forbidden" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 404 File not found
                    else if( directive == "404" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 404 - File Not Found" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 405 Method not allowed
                    else if( directive == "405" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 405 - Method Not Allowed" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // There's more....
                }

            } while( linebuff[0] != '\r' );

            // code for setting up the database path so that any paged
            // databases can be automatically located.
            osg::ref_ptr<Options> local_opt = const_cast<Options*>(options);
            if (!local_opt) local_opt = new Options;

            if (local_opt.valid() && local_opt->getDatabasePath().empty())
            {
                local_opt->setDatabasePath(osgDB::getFilePath(inFileName));
            }

            if( reader != 0L )
                readResult = readFile(objectType, reader, sio, local_opt.get() );

            double ms = osg::Timer::instance()->delta_m(start,osg::Timer::instance()->tick());

            osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " fetched from server. in" << ms <<" ms"<< std::endl;

            if( !localCacheDir.empty() && cacheMode & Write )
            {
                std::string cacheFile = localCacheDir + '/' + fileName;
                if( osgDB::makeDirectoryForFile( cacheFile ) )
                {

                    switch(objectType)
                    {
                    case(OBJECT): osgDB::writeObjectFile( *(readResult.getObject()), cacheFile );
                    case(IMAGE): osgDB::writeImageFile( *(readResult.getImage()), cacheFile );
                    case(HEIGHTFIELD): osgDB::writeHeightFieldFile( *(readResult.getHeightField()), cacheFile );
                    case(NODE): osgDB::writeNodeFile( *(readResult.getNode()), cacheFile );;
                    default: break;
                    }

                    osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " stored to local cache." << std::endl;
                }
            }

            return readResult;
        }

};

osgDB::RegisterReaderWriterProxy<NetReader> g_netReader_Proxy;

<commit_msg>Small warning fix by Marco.<commit_after>#include <iostream>
#include <fstream>
#include <sstream>

#include <osg/Notify>

#include <osgDB/Input>
#include <osgDB/Registry>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgDB/FileUtils>
#include <osg/MatrixTransform>
#include <osg/Group>
#include <osg/Timer>
#include "sockinet.h"

 /*
  *  Semantics:
  *    Two methods for using the .net loader.
  *      1) Add a hostname prefix and a '.net' suffix on a model when passing
  *          to osgDB::readNodeFile()
  *          e.g:    osgDB::readNodeFile( "openscenegraph.org:cow.osg.net" );
  *
  *     2) Explicitely load the .net plugin and pass the plugin options including
  *           hostname=<hostname>
  *
  *    Method #1 takes precedence.  SO, if the hostname option is passed the
  *    plugin, but the name also contains a hostname prefix, the hostname
  *    prefix on the file name will override the option
  *
  *  Plugin options:
  *           hostname=<hostname>     - Specify the host where the data file is to
  *                                     be fetched from.
  *
  *           prefix=<prefix>         - Specify a server directory to prefix the
  *                                     file name with.
  *
  *           local_cache_dir=<dir>   - Specify a directory in which to cache files
  *                                     on the local machine once they've been fetched.
  *                                     This directory is also searched before fetching
  *                                     the file from the server when Read mode is
  *                                     enabled on the cache.
  *
  *           cache_mode=<mode>       - Set the mode for the local cache if local_cache
  *                                     was specified.  If local_cache was not specified
  *                                     this directive is ignored.  <mode> may
  *                                     be specified with ReadOnly, WriteOnly, or
  *                                     ReadWrite.  Behavior for the different modes is
  *                                     defined as:
  *
  *                                       ReadOnly   - When retrieving files, cache is
  *                                                    searched first, and if the file is
  *                                                    not present, it is fetched from the
  *                                                    server.  If it is fetched from the
  *                                                    server it is not stored in local cache
  *
  *                                       WriteOnly  - When retrieving files, cache is not
  *                                                    searched, file is always retrieved
  *                                                    from the server and always written to
  *                                                    cache.
  *
  *                                       ReadWrite  - (the default).  When retrieving files
  *                                                    cache is searched first, if file is
  *                                                    not present in cache, it is fetched from
  *                                                    the server.  If fetched, it is written
  *                                                    to cache.
  *
  */

class NetReader : public osgDB::ReaderWriter
{
    public:
        NetReader() {}

        virtual const char* className() { return "HTTP Protocol Model Reader"; }

        virtual bool acceptsExtension(const std::string& extension)
        {
            return osgDB::equalCaseInsensitive(extension,"net");
        }

        enum ObjectType
        {
            OBJECT,
            IMAGE,
            HEIGHTFIELD,
            NODE
        };

        virtual ReadResult readObject(const std::string& fileName, const Options* options)
        {
            return readFile(OBJECT,fileName,options);
        }

        virtual ReadResult readImage(const std::string& fileName, const Options *options)
        {
            return readFile(IMAGE,fileName,options);
        }

        virtual ReadResult readHeightField(const std::string& fileName, const Options *options)
        {
            return readFile(HEIGHTFIELD,fileName,options);
        }

        virtual ReadResult readNode(const std::string& fileName, const Options *options)
        {
            return readFile(NODE,fileName,options);
        }

        ReadResult readFile(ObjectType objectType, ReaderWriter* rw, std::istream& fin, const Options *options)
        {
            switch(objectType)
            {
            case(OBJECT): return rw->readObject(fin,options);
            case(IMAGE): return rw->readImage(fin,options);
            case(HEIGHTFIELD): return rw->readHeightField(fin,options);
            case(NODE): return rw->readNode(fin,options);
            default: break;
            }
			return ReadResult::FILE_NOT_HANDLED;
        }

        virtual ReadResult readFile(ObjectType objectType, const std::string& inFileName, const Options *options)
        {
            osg::Timer_t start = osg::Timer::instance()->tick();

            osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: start load" << inFileName << std::endl;

            std::string hostname;
            std::string serverPrefix;
            std::string localCacheDir;
            int port = 80;

            enum CacheMode {
                Read      = 1,
                Write     = 2,
                ReadWrite = 3
            };

            CacheMode cacheMode = ReadWrite;

            if (options)
            {
                std::istringstream iss(options->getOptionString());
                std::string opt;
                while (iss >> opt)
                {
                    int index = opt.find( "=" );
                    if( opt.substr( 0, index ) == "hostname" ||
                        opt.substr( 0, index ) == "HOSTNAME" )
                    {
                        hostname = opt.substr( index+1 );
                    }
                    else if( opt.substr( 0, index ) == "port" ||
                             opt.substr( 0, index ) == "PORT" )
                    {
                        port = atoi( opt.substr(index+1).c_str() );
                    }
                    else if( opt.substr( 0, index ) == "server_prefix" ||
                             opt.substr( 0, index ) == "SERVER_PREFIX" ||
                             opt.substr( 0, index ) == "prefix" ||
                             opt.substr( 0, index ) == "PREFIX" )
                    {
                        serverPrefix = opt.substr(index+1);
                    }
                    else if( opt.substr( 0, index ) == "local_cache_dir" ||
                             opt.substr( 0, index ) == "LOCAL_CACHE_DIR" )
                    {
                        localCacheDir = opt.substr(index+1);
                    }
                    else if( opt.substr( 0, index ) == "cache_mode" ||
                             opt.substr( 0, index ) == "CACHE_MODE" )
                    {
                        if( opt.substr(index+1) == "ReadOnly" )
                            cacheMode = Read;
                        else if(  opt.substr(index+1) == "WriteOnly" )
                            cacheMode = Write;
                        else if(  opt.substr(index+1) == "ReadWrite" )
                            cacheMode = ReadWrite;
                        else
                            osg::notify(osg::WARN) <<
                                "NET plug-in warning:  cache_mode " << opt.substr(index+1) <<
                                " not understood.  Defaulting to ReadWrite." << std::endl;
                    }
                }
            }

            ReadResult readResult = ReadResult::FILE_NOT_HANDLED;

            /* * we accept all extensions
            std::string ext = osgDB::getFileExtension(inFileName);
            if (!acceptsExtension(ext))
                return ReadResult::FILE_NOT_HANDLED;
                */

            std::string fileName;
            int index = inFileName.find(":");
            // If we haven't been given a hostname as an option
            // and it hasn't been prefixed to the name, we fail
            if( index != -1 )
            {
                hostname = inFileName.substr( 0, index);
                // need to strip the inFileName of the hostname prefix
                fileName = inFileName.substr( index+1 );
            }
            else
            {
                if( hostname.empty() )
                    return ReadResult::FILE_NOT_HANDLED;
                else
                    fileName = inFileName;
            }

            // Let's also strip the possible .net extension
            if( osgDB::getFileExtension( fileName ) == "net" )
            {
                int rindex = fileName.rfind( "." );
                fileName = fileName.substr( 0, rindex );
            }

            if( !serverPrefix.empty() )
                fileName = serverPrefix + '/' + fileName;

            // Invoke the reader corresponding to the extension
            osgDB::ReaderWriter *reader =
                    osgDB::Registry::instance()->getReaderWriterForExtension( osgDB::getFileExtension(fileName));
            if( reader == 0L )
                return ReadResult::FILE_NOT_HANDLED;

            // Before we go to the network, lets see if it is in local cache, if cache
            // was specified and Read bit is set
            if( !localCacheDir.empty() && (cacheMode & Read) )
            {
                std::string cacheFile = localCacheDir + '/' + fileName;
                if( osgDB::fileExists( cacheFile ))
                {
                    std::ifstream  in(cacheFile.c_str());
                    readResult = readFile(objectType, reader, in, options );

                    in.close();
                    osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " fetched from local cache." << std::endl;
                    return readResult;
                }
            }

            // Fetch from the network
            iosockinet  sio (sockbuf::sock_stream);
            try {
                sio->connect( hostname.c_str(), port );
            }
            catch( sockerr e )
            {
                osg::notify(osg::WARN) << "osgPlugin .net reader: Unable to connect to host " << hostname << std::endl;
                return ReadResult::FILE_NOT_FOUND;
            }

            sio << "GET /" << fileName << " HTTP/1.1\n" << "Host:\n\n";
            sio.flush();

            char linebuff[256];
            do
            {
                sio.getline( linebuff, sizeof( linebuff ));

                std::istringstream iss(linebuff);
                std::string directive;
                iss >> directive;
                if( directive.substr(0,4) == "HTTP" )
                {
                    iss >> directive;
                    // Code 200.  We be ok.
                    if( directive == "200" )
                        ;
                    // Code 400 Bad Request
                    else if( directive == "400" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 400 - Bad Request" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 401 Bad Request
                    else if( directive == "401" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 401 - Unauthorized Access" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 403 Bad Request
                    else if( directive == "403" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 403 - Access Forbidden" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 404 File not found
                    else if( directive == "404" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 404 - File Not Found" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 405 Method not allowed
                    else if( directive == "405" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 405 - Method Not Allowed" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // There's more....
                }

            } while( linebuff[0] != '\r' );

            // code for setting up the database path so that any paged
            // databases can be automatically located.
            osg::ref_ptr<Options> local_opt = const_cast<Options*>(options);
            if (!local_opt) local_opt = new Options;

            if (local_opt.valid() && local_opt->getDatabasePath().empty())
            {
                local_opt->setDatabasePath(osgDB::getFilePath(inFileName));
            }

            if( reader != 0L )
                readResult = readFile(objectType, reader, sio, local_opt.get() );

            double ms = osg::Timer::instance()->delta_m(start,osg::Timer::instance()->tick());

            osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " fetched from server. in" << ms <<" ms"<< std::endl;

            if( !localCacheDir.empty() && cacheMode & Write )
            {
                std::string cacheFile = localCacheDir + '/' + fileName;
                if( osgDB::makeDirectoryForFile( cacheFile ) )
                {

                    switch(objectType)
                    {
                    case(OBJECT): osgDB::writeObjectFile( *(readResult.getObject()), cacheFile );
                    case(IMAGE): osgDB::writeImageFile( *(readResult.getImage()), cacheFile );
                    case(HEIGHTFIELD): osgDB::writeHeightFieldFile( *(readResult.getHeightField()), cacheFile );
                    case(NODE): osgDB::writeNodeFile( *(readResult.getNode()), cacheFile );;
                    default: break;
                    }

                    osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " stored to local cache." << std::endl;
                }
            }

            return readResult;
        }

};

osgDB::RegisterReaderWriterProxy<NetReader> g_netReader_Proxy;

<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <sstream>

#include <osg/Notify>

#include <osgDB/Input>
#include <osgDB/Registry>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgDB/FileUtils>
#include <osg/MatrixTransform>
#include <osg/Group>
#include <osg/Timer>
#include "sockinet.h"

 /*
  *  Semantics:
  *    Two methods for using the .net loader.
  *      1) Add a hostname prefix and a '.net' suffix on a model when passing
  *          to osgDB::readNodeFile()
  *          e.g:    osgDB::readNodeFile( "openscenegraph.org:cow.osg.net" );
  *
  *     2) Explicitely load the .net plugin and pass the plugin options including
  *           hostname=<hostname>
  *
  *    Method #1 takes precedence.  SO, if the hostname option is passed the
  *    plugin, but the name also contains a hostname prefix, the hostname
  *    prefix on the file name will override the option
  *
  *  Plugin options:
  *           hostname=<hostname>     - Specify the host where the data file is to
  *                                     be fetched from.
  *
  *           prefix=<prefix>         - Specify a server directory to prefix the
  *                                     file name with.
  *
  *           local_cache_dir=<dir>   - Specify a directory in which to cache files
  *                                     on the local machine once they've been fetched.
  *                                     This directory is also searched before fetching
  *                                     the file from the server when Read mode is
  *                                     enabled on the cache.
  *
  *           cache_mode=<mode>       - Set the mode for the local cache if local_cache
  *                                     was specified.  If local_cache was not specified
  *                                     this directive is ignored.  <mode> may
  *                                     be specified with ReadOnly, WriteOnly, or
  *                                     ReadWrite.  Behavior for the different modes is
  *                                     defined as:
  *
  *                                       ReadOnly   - When retrieving files, cache is
  *                                                    searched first, and if the file is
  *                                                    not present, it is fetched from the
  *                                                    server.  If it is fetched from the
  *                                                    server it is not stored in local cache
  *
  *                                       WriteOnly  - When retrieving files, cache is not
  *                                                    searched, file is always retrieved
  *                                                    from the server and always written to
  *                                                    cache.
  *
  *                                       ReadWrite  - (the default).  When retrieving files
  *                                                    cache is searched first, if file is
  *                                                    not present in cache, it is fetched from
  *                                                    the server.  If fetched, it is written
  *                                                    to cache.
  *
  */

class NetReader : public osgDB::ReaderWriter
{
    public:
        NetReader() {}

        virtual const char* className() { return "HTTP Protocol Model Reader"; }

        virtual bool acceptsExtension(const std::string& extension)
        {
            return osgDB::equalCaseInsensitive(extension,"net");
        }

        enum ObjectType
        {
            OBJECT,
            IMAGE,
            HEIGHTFIELD,
            NODE
        };

        virtual ReadResult readObject(const std::string& fileName, const Options* options)
        {
            return readFile(OBJECT,fileName,options);
        }

        virtual ReadResult readImage(const std::string& fileName, const Options *options)
        {
            return readFile(IMAGE,fileName,options);
        }

        virtual ReadResult readHeightField(const std::string& fileName, const Options *options)
        {
            return readFile(HEIGHTFIELD,fileName,options);
        }

        virtual ReadResult readNode(const std::string& fileName, const Options *options)
        {
            return readFile(NODE,fileName,options);
        }

        ReadResult readFile(ObjectType objectType, ReaderWriter* rw, std::istream& fin, const Options *options)
        {
            switch(objectType)
            {
            case(OBJECT): return rw->readObject(fin,options);
            case(IMAGE): return rw->readImage(fin,options);
            case(HEIGHTFIELD): return rw->readHeightField(fin,options);
            case(NODE): return rw->readNode(fin,options);
            }
        }

        virtual ReadResult readFile(ObjectType objectType, const std::string& inFileName, const Options *options)
        {
            osg::Timer_t start = osg::Timer::instance()->tick();

            osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: start load" << inFileName << std::endl;

            std::string hostname;
            std::string serverPrefix;
            std::string localCacheDir;
            int port = 80;

            enum CacheMode {
                Read      = 1,
                Write     = 2,
                ReadWrite = 3
            };

            CacheMode cacheMode = ReadWrite;

            if (options)
            {
                std::istringstream iss(options->getOptionString());
                std::string opt;
                while (iss >> opt)
                {
                    int index = opt.find( "=" );
                    if( opt.substr( 0, index ) == "hostname" ||
                        opt.substr( 0, index ) == "HOSTNAME" )
                    {
                        hostname = opt.substr( index+1 );
                    }
                    else if( opt.substr( 0, index ) == "port" ||
                             opt.substr( 0, index ) == "PORT" )
                    {
                        port = atoi( opt.substr(index+1).c_str() );
                    }
                    else if( opt.substr( 0, index ) == "server_prefix" ||
                             opt.substr( 0, index ) == "SERVER_PREFIX" ||
                             opt.substr( 0, index ) == "prefix" ||
                             opt.substr( 0, index ) == "PREFIX" )
                    {
                        serverPrefix = opt.substr(index+1);
                    }
                    else if( opt.substr( 0, index ) == "local_cache_dir" ||
                             opt.substr( 0, index ) == "LOCAL_CACHE_DIR" )
                    {
                        localCacheDir = opt.substr(index+1);
                    }
                    else if( opt.substr( 0, index ) == "cache_mode" ||
                             opt.substr( 0, index ) == "CACHE_MODE" )
                    {
                        if( opt.substr(index+1) == "ReadOnly" )
                            cacheMode = Read;
                        else if(  opt.substr(index+1) == "WriteOnly" )
                            cacheMode = Write;
                        else if(  opt.substr(index+1) == "ReadWrite" )
                            cacheMode = ReadWrite;
                        else
                            osg::notify(osg::WARN) <<
                                "NET plug-in warning:  cache_mode " << opt.substr(index+1) <<
                                " not understood.  Defaulting to ReadWrite." << std::endl;
                    }
                }
            }

            ReadResult readResult = ReadResult::FILE_NOT_HANDLED;

            /* * we accept all extensions
            std::string ext = osgDB::getFileExtension(inFileName);
            if (!acceptsExtension(ext))
                return ReadResult::FILE_NOT_HANDLED;
                */

            std::string fileName;
            int index = inFileName.find(":");
            // If we haven't been given a hostname as an option
            // and it hasn't been prefixed to the name, we fail
            if( index != -1 )
            {
                hostname = inFileName.substr( 0, index);
                // need to strip the inFileName of the hostname prefix
                fileName = inFileName.substr( index+1 );
            }
            else
            {
                if( hostname.empty() )
                    return ReadResult::FILE_NOT_HANDLED;
                else
                    fileName = inFileName;
            }

            // Let's also strip the possible .net extension
            if( osgDB::getFileExtension( fileName ) == "net" )
            {
                int rindex = fileName.rfind( "." );
                fileName = fileName.substr( 0, rindex );
            }

            if( !serverPrefix.empty() )
                fileName = serverPrefix + '/' + fileName;

            // Invoke the reader corresponding to the extension
            osgDB::ReaderWriter *reader =
                    osgDB::Registry::instance()->getReaderWriterForExtension( osgDB::getFileExtension(fileName));
            if( reader == 0L )
                return ReadResult::FILE_NOT_HANDLED;

            // Before we go to the network, lets see if it is in local cache, if cache
            // was specified and Read bit is set
            if( !localCacheDir.empty() && (cacheMode & Read) )
            {
                std::string cacheFile = localCacheDir + '/' + fileName;
                if( osgDB::fileExists( cacheFile ))
                {
                    std::ifstream  in(cacheFile.c_str());
                    readResult = readFile(objectType, reader, in, options );

                    in.close();
                    osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " fetched from local cache." << std::endl;
                    return readResult;
                }
            }

            // Fetch from the network
            iosockinet  sio (sockbuf::sock_stream);
            try {
                sio->connect( hostname.c_str(), port );
            }
            catch( sockerr e )
            {
                osg::notify(osg::WARN) << "osgPlugin .net reader: Unable to connect to host " << hostname << std::endl;
                return ReadResult::FILE_NOT_FOUND;
            }

            sio << "GET /" << fileName << " HTTP/1.1\n" << "Host:\n\n";
            sio.flush();

            char linebuff[256];
            do
            {
                sio.getline( linebuff, sizeof( linebuff ));

                std::istringstream iss(linebuff);
                std::string directive;
                iss >> directive;
                if( directive.substr(0,4) == "HTTP" )
                {
                    iss >> directive;
                    // Code 200.  We be ok.
                    if( directive == "200" )
                        ;
                    // Code 400 Bad Request
                    else if( directive == "400" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 400 - Bad Request" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 401 Bad Request
                    else if( directive == "401" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 401 - Unauthorized Access" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 403 Bad Request
                    else if( directive == "403" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 403 - Access Forbidden" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 404 File not found
                    else if( directive == "404" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 404 - File Not Found" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 405 Method not allowed
                    else if( directive == "405" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 405 - Method Not Allowed" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // There's more....
                }

            } while( linebuff[0] != '\r' );

            // code for setting up the database path so that any paged
            // databases can be automatically located.
            osg::ref_ptr<Options> local_opt = const_cast<Options*>(options);
            if (!local_opt) local_opt = new Options;

            if (local_opt.valid() && local_opt->getDatabasePath().empty())
            {
                local_opt->setDatabasePath(osgDB::getFilePath(inFileName));
            }

            if( reader != 0L )
                readResult = readFile(objectType, reader, sio, local_opt.get() );

            double ms = osg::Timer::instance()->delta_m(start,osg::Timer::instance()->tick());

            osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " fetched from server. in" << ms <<" ms"<< std::endl;

            if( !localCacheDir.empty() && cacheMode & Write )
            {
                std::string cacheFile = localCacheDir + '/' + fileName;
                if( osgDB::makeDirectoryForFile( cacheFile ) )
                {

                    switch(objectType)
                    {
                    case(OBJECT): osgDB::writeObjectFile( *(readResult.getObject()), cacheFile );
                    case(IMAGE): osgDB::writeImageFile( *(readResult.getImage()), cacheFile );
                    case(HEIGHTFIELD): osgDB::writeHeightFieldFile( *(readResult.getHeightField()), cacheFile );
                    case(NODE): osgDB::writeNodeFile( *(readResult.getNode()), cacheFile );;
                    }

                    osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " stored to local cache." << std::endl;
                }
            }

            return readResult;
        }

};

osgDB::RegisterReaderWriterProxy<NetReader> g_netReader_Proxy;

<commit_msg>Added default: case for both switch() statements<commit_after>#include <iostream>
#include <fstream>
#include <sstream>

#include <osg/Notify>

#include <osgDB/Input>
#include <osgDB/Registry>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgDB/FileUtils>
#include <osg/MatrixTransform>
#include <osg/Group>
#include <osg/Timer>
#include "sockinet.h"

 /*
  *  Semantics:
  *    Two methods for using the .net loader.
  *      1) Add a hostname prefix and a '.net' suffix on a model when passing
  *          to osgDB::readNodeFile()
  *          e.g:    osgDB::readNodeFile( "openscenegraph.org:cow.osg.net" );
  *
  *     2) Explicitely load the .net plugin and pass the plugin options including
  *           hostname=<hostname>
  *
  *    Method #1 takes precedence.  SO, if the hostname option is passed the
  *    plugin, but the name also contains a hostname prefix, the hostname
  *    prefix on the file name will override the option
  *
  *  Plugin options:
  *           hostname=<hostname>     - Specify the host where the data file is to
  *                                     be fetched from.
  *
  *           prefix=<prefix>         - Specify a server directory to prefix the
  *                                     file name with.
  *
  *           local_cache_dir=<dir>   - Specify a directory in which to cache files
  *                                     on the local machine once they've been fetched.
  *                                     This directory is also searched before fetching
  *                                     the file from the server when Read mode is
  *                                     enabled on the cache.
  *
  *           cache_mode=<mode>       - Set the mode for the local cache if local_cache
  *                                     was specified.  If local_cache was not specified
  *                                     this directive is ignored.  <mode> may
  *                                     be specified with ReadOnly, WriteOnly, or
  *                                     ReadWrite.  Behavior for the different modes is
  *                                     defined as:
  *
  *                                       ReadOnly   - When retrieving files, cache is
  *                                                    searched first, and if the file is
  *                                                    not present, it is fetched from the
  *                                                    server.  If it is fetched from the
  *                                                    server it is not stored in local cache
  *
  *                                       WriteOnly  - When retrieving files, cache is not
  *                                                    searched, file is always retrieved
  *                                                    from the server and always written to
  *                                                    cache.
  *
  *                                       ReadWrite  - (the default).  When retrieving files
  *                                                    cache is searched first, if file is
  *                                                    not present in cache, it is fetched from
  *                                                    the server.  If fetched, it is written
  *                                                    to cache.
  *
  */

class NetReader : public osgDB::ReaderWriter
{
    public:
        NetReader() {}

        virtual const char* className() { return "HTTP Protocol Model Reader"; }

        virtual bool acceptsExtension(const std::string& extension)
        {
            return osgDB::equalCaseInsensitive(extension,"net");
        }

        enum ObjectType
        {
            OBJECT,
            IMAGE,
            HEIGHTFIELD,
            NODE
        };

        virtual ReadResult readObject(const std::string& fileName, const Options* options)
        {
            return readFile(OBJECT,fileName,options);
        }

        virtual ReadResult readImage(const std::string& fileName, const Options *options)
        {
            return readFile(IMAGE,fileName,options);
        }

        virtual ReadResult readHeightField(const std::string& fileName, const Options *options)
        {
            return readFile(HEIGHTFIELD,fileName,options);
        }

        virtual ReadResult readNode(const std::string& fileName, const Options *options)
        {
            return readFile(NODE,fileName,options);
        }

        ReadResult readFile(ObjectType objectType, ReaderWriter* rw, std::istream& fin, const Options *options)
        {
            switch(objectType)
            {
            case(OBJECT): return rw->readObject(fin,options);
            case(IMAGE): return rw->readImage(fin,options);
            case(HEIGHTFIELD): return rw->readHeightField(fin,options);
            case(NODE): return rw->readNode(fin,options);
            default: break;
            }
        }

        virtual ReadResult readFile(ObjectType objectType, const std::string& inFileName, const Options *options)
        {
            osg::Timer_t start = osg::Timer::instance()->tick();

            osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: start load" << inFileName << std::endl;

            std::string hostname;
            std::string serverPrefix;
            std::string localCacheDir;
            int port = 80;

            enum CacheMode {
                Read      = 1,
                Write     = 2,
                ReadWrite = 3
            };

            CacheMode cacheMode = ReadWrite;

            if (options)
            {
                std::istringstream iss(options->getOptionString());
                std::string opt;
                while (iss >> opt)
                {
                    int index = opt.find( "=" );
                    if( opt.substr( 0, index ) == "hostname" ||
                        opt.substr( 0, index ) == "HOSTNAME" )
                    {
                        hostname = opt.substr( index+1 );
                    }
                    else if( opt.substr( 0, index ) == "port" ||
                             opt.substr( 0, index ) == "PORT" )
                    {
                        port = atoi( opt.substr(index+1).c_str() );
                    }
                    else if( opt.substr( 0, index ) == "server_prefix" ||
                             opt.substr( 0, index ) == "SERVER_PREFIX" ||
                             opt.substr( 0, index ) == "prefix" ||
                             opt.substr( 0, index ) == "PREFIX" )
                    {
                        serverPrefix = opt.substr(index+1);
                    }
                    else if( opt.substr( 0, index ) == "local_cache_dir" ||
                             opt.substr( 0, index ) == "LOCAL_CACHE_DIR" )
                    {
                        localCacheDir = opt.substr(index+1);
                    }
                    else if( opt.substr( 0, index ) == "cache_mode" ||
                             opt.substr( 0, index ) == "CACHE_MODE" )
                    {
                        if( opt.substr(index+1) == "ReadOnly" )
                            cacheMode = Read;
                        else if(  opt.substr(index+1) == "WriteOnly" )
                            cacheMode = Write;
                        else if(  opt.substr(index+1) == "ReadWrite" )
                            cacheMode = ReadWrite;
                        else
                            osg::notify(osg::WARN) <<
                                "NET plug-in warning:  cache_mode " << opt.substr(index+1) <<
                                " not understood.  Defaulting to ReadWrite." << std::endl;
                    }
                }
            }

            ReadResult readResult = ReadResult::FILE_NOT_HANDLED;

            /* * we accept all extensions
            std::string ext = osgDB::getFileExtension(inFileName);
            if (!acceptsExtension(ext))
                return ReadResult::FILE_NOT_HANDLED;
                */

            std::string fileName;
            int index = inFileName.find(":");
            // If we haven't been given a hostname as an option
            // and it hasn't been prefixed to the name, we fail
            if( index != -1 )
            {
                hostname = inFileName.substr( 0, index);
                // need to strip the inFileName of the hostname prefix
                fileName = inFileName.substr( index+1 );
            }
            else
            {
                if( hostname.empty() )
                    return ReadResult::FILE_NOT_HANDLED;
                else
                    fileName = inFileName;
            }

            // Let's also strip the possible .net extension
            if( osgDB::getFileExtension( fileName ) == "net" )
            {
                int rindex = fileName.rfind( "." );
                fileName = fileName.substr( 0, rindex );
            }

            if( !serverPrefix.empty() )
                fileName = serverPrefix + '/' + fileName;

            // Invoke the reader corresponding to the extension
            osgDB::ReaderWriter *reader =
                    osgDB::Registry::instance()->getReaderWriterForExtension( osgDB::getFileExtension(fileName));
            if( reader == 0L )
                return ReadResult::FILE_NOT_HANDLED;

            // Before we go to the network, lets see if it is in local cache, if cache
            // was specified and Read bit is set
            if( !localCacheDir.empty() && (cacheMode & Read) )
            {
                std::string cacheFile = localCacheDir + '/' + fileName;
                if( osgDB::fileExists( cacheFile ))
                {
                    std::ifstream  in(cacheFile.c_str());
                    readResult = readFile(objectType, reader, in, options );

                    in.close();
                    osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " fetched from local cache." << std::endl;
                    return readResult;
                }
            }

            // Fetch from the network
            iosockinet  sio (sockbuf::sock_stream);
            try {
                sio->connect( hostname.c_str(), port );
            }
            catch( sockerr e )
            {
                osg::notify(osg::WARN) << "osgPlugin .net reader: Unable to connect to host " << hostname << std::endl;
                return ReadResult::FILE_NOT_FOUND;
            }

            sio << "GET /" << fileName << " HTTP/1.1\n" << "Host:\n\n";
            sio.flush();

            char linebuff[256];
            do
            {
                sio.getline( linebuff, sizeof( linebuff ));

                std::istringstream iss(linebuff);
                std::string directive;
                iss >> directive;
                if( directive.substr(0,4) == "HTTP" )
                {
                    iss >> directive;
                    // Code 200.  We be ok.
                    if( directive == "200" )
                        ;
                    // Code 400 Bad Request
                    else if( directive == "400" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 400 - Bad Request" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 401 Bad Request
                    else if( directive == "401" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 401 - Unauthorized Access" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 403 Bad Request
                    else if( directive == "403" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 403 - Access Forbidden" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 404 File not found
                    else if( directive == "404" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 404 - File Not Found" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // Code 405 Method not allowed
                    else if( directive == "405" )
                    {
                        osg::notify(osg::WARN) <<
                            "osgPlugin .net: http server response 405 - Method Not Allowed" << std::endl;
                        return ReadResult::FILE_NOT_FOUND;
                    }
                    // There's more....
                }

            } while( linebuff[0] != '\r' );

            // code for setting up the database path so that any paged
            // databases can be automatically located.
            osg::ref_ptr<Options> local_opt = const_cast<Options*>(options);
            if (!local_opt) local_opt = new Options;

            if (local_opt.valid() && local_opt->getDatabasePath().empty())
            {
                local_opt->setDatabasePath(osgDB::getFilePath(inFileName));
            }

            if( reader != 0L )
                readResult = readFile(objectType, reader, sio, local_opt.get() );

            double ms = osg::Timer::instance()->delta_m(start,osg::Timer::instance()->tick());

            osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " fetched from server. in" << ms <<" ms"<< std::endl;

            if( !localCacheDir.empty() && cacheMode & Write )
            {
                std::string cacheFile = localCacheDir + '/' + fileName;
                if( osgDB::makeDirectoryForFile( cacheFile ) )
                {

                    switch(objectType)
                    {
                    case(OBJECT): osgDB::writeObjectFile( *(readResult.getObject()), cacheFile );
                    case(IMAGE): osgDB::writeImageFile( *(readResult.getImage()), cacheFile );
                    case(HEIGHTFIELD): osgDB::writeHeightFieldFile( *(readResult.getHeightField()), cacheFile );
                    case(NODE): osgDB::writeNodeFile( *(readResult.getNode()), cacheFile );;
                    default: break;
                    }

                    osg::notify(osg::DEBUG_INFO) << "osgPlugin .net: " << fileName <<
                                         " stored to local cache." << std::endl;
                }
            }

            return readResult;
        }

};

osgDB::RegisterReaderWriterProxy<NetReader> g_netReader_Proxy;

<|endoftext|>


<commit_before>#include <sstream>

#include <osg/Image>
#include <osg/Group>
#include <osg/Notify>

#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/fstream>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>

using namespace osg;
using namespace osgDB;

// pull in symbols from individual .o's to enable the static build to work
USE_DOTOSGWRAPPER(AlphaFunc)
USE_DOTOSGWRAPPER(AnimationPath)
USE_DOTOSGWRAPPER(AutoTransform)
USE_DOTOSGWRAPPER(Billboard)
USE_DOTOSGWRAPPER(BlendColor)
USE_DOTOSGWRAPPER(BlendEquation)
USE_DOTOSGWRAPPER(BlendFunc)
USE_DOTOSGWRAPPER(Camera)
USE_DOTOSGWRAPPER(CameraView)
USE_DOTOSGWRAPPER(ClearNode)
USE_DOTOSGWRAPPER(ClipNode)
USE_DOTOSGWRAPPER(ClipPlane)
USE_DOTOSGWRAPPER(ClusterCullingCallback)
USE_DOTOSGWRAPPER(ColorMask)
USE_DOTOSGWRAPPER(ColorMatrix)
USE_DOTOSGWRAPPER(ConvexPlanarOccluder)
USE_DOTOSGWRAPPER(CoordinateSystemNode)
USE_DOTOSGWRAPPER(CullFace)
USE_DOTOSGWRAPPER(Depth)
USE_DOTOSGWRAPPER(Drawable)
USE_DOTOSGWRAPPER(EllipsoidModel)
USE_DOTOSGWRAPPER(Fog)
USE_DOTOSGWRAPPER(FragmentProgram)
USE_DOTOSGWRAPPER(FrontFace)
USE_DOTOSGWRAPPER(Geode)
USE_DOTOSGWRAPPER(Geometry)
USE_DOTOSGWRAPPER(Group)
USE_DOTOSGWRAPPER(Image)
USE_DOTOSGWRAPPER(ImageSequence)
USE_DOTOSGWRAPPER(Light)
USE_DOTOSGWRAPPER(LightModel)
USE_DOTOSGWRAPPER(LightSource)
USE_DOTOSGWRAPPER(LineStipple)
USE_DOTOSGWRAPPER(LineWidth)
USE_DOTOSGWRAPPER(LOD)
USE_DOTOSGWRAPPER(Material)
USE_DOTOSGWRAPPER(MatrixTransform)
USE_DOTOSGWRAPPER(NodeCallback)
USE_DOTOSGWRAPPER(Node)
USE_DOTOSGWRAPPER(Object)
USE_DOTOSGWRAPPER(OccluderNode)
USE_DOTOSGWRAPPER(OcclusionQueryNode)
USE_DOTOSGWRAPPER(PagedLOD)
USE_DOTOSGWRAPPER(Point)
USE_DOTOSGWRAPPER(PointSprite)
USE_DOTOSGWRAPPER(PolygonMode)
USE_DOTOSGWRAPPER(PolygonOffset)
USE_DOTOSGWRAPPER(PositionAttitudeTransform)
USE_DOTOSGWRAPPER(Program)
USE_DOTOSGWRAPPER(Projection)
USE_DOTOSGWRAPPER(ProxyNode)
USE_DOTOSGWRAPPER(Scissor)
USE_DOTOSGWRAPPER(Sequence)
USE_DOTOSGWRAPPER(ShadeModel)
USE_DOTOSGWRAPPER(Shader)
USE_DOTOSGWRAPPER(Sphere)
USE_DOTOSGWRAPPER(Cone)
USE_DOTOSGWRAPPER(Capsule)
USE_DOTOSGWRAPPER(Box)
USE_DOTOSGWRAPPER(HeightField)
USE_DOTOSGWRAPPER(CompositeShape)
USE_DOTOSGWRAPPER(Cylinder)
USE_DOTOSGWRAPPER(ShapeDrawable)
USE_DOTOSGWRAPPER(StateAttribute)
USE_DOTOSGWRAPPER(StateSet)
USE_DOTOSGWRAPPER(Stencil)
USE_DOTOSGWRAPPER(Switch)
USE_DOTOSGWRAPPER(TessellationHints)
USE_DOTOSGWRAPPER(TexEnvCombine)
USE_DOTOSGWRAPPER(TexEnv)
USE_DOTOSGWRAPPER(TexEnvFilter)
USE_DOTOSGWRAPPER(TexGen)
USE_DOTOSGWRAPPER(TexGenNode)
USE_DOTOSGWRAPPER(TexMat)
USE_DOTOSGWRAPPER(Texture1D)
USE_DOTOSGWRAPPER(Texture2D)
USE_DOTOSGWRAPPER(Texture3D)
USE_DOTOSGWRAPPER(Texture)
USE_DOTOSGWRAPPER(TextureCubeMap)
USE_DOTOSGWRAPPER(TextureRectangle)
USE_DOTOSGWRAPPER(Transform)
USE_DOTOSGWRAPPER(Uniform)
USE_DOTOSGWRAPPER(VertexProgram)
USE_DOTOSGWRAPPER(Viewport)

class OSGReaderWriter : public ReaderWriter
{
    public:

        OSGReaderWriter()
        {
            supportsExtension("osg","OpenSceneGraph Ascii file format");
            supportsExtension("osgs","Psuedo OpenSceneGraph file loaded, with file encoded in filename string");
            supportsOption("precision","Set the floating point precision when writing out files");
            supportsOption("OutputTextureFiles","Write out the texture images to file");
        }

        virtual const char* className() const { return "OSG Reader/Writer"; }

        virtual ReadResult readObject(const std::string& file, const Options* opt) const
        {
            std::string ext = osgDB::getLowerCaseFileExtension(file);

            if (equalCaseInsensitive(ext,"osgs"))
            {
                std::istringstream fin(osgDB::getNameLessExtension(file));
                if (fin) return readNode(fin,opt);
                return ReadResult::ERROR_IN_READING_FILE;
            }

            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file, opt );
            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

            // code for setting up the database path so that internally referenced file are searched for on relative paths.
            osg::ref_ptr<Options> local_opt = opt ? static_cast<Options*>(opt->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
            local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));

            osgDB::ifstream fin(fileName.c_str());
            if (fin)
            {
                return readObject(fin, local_opt.get());
            }
            return 0L;
        }

        virtual ReadResult readObject(std::istream& fin, const Options* options) const
        {
            fin.imbue(std::locale::classic());

            Input fr;
            fr.attach(&fin);
            fr.setOptions(options);

            typedef std::vector<osg::Object*> ObjectList;
            ObjectList objectList;

            // load all nodes in file, placing them in a group.
            while(!fr.eof())
            {
                Object *object = fr.readObject();
                if (object) objectList.push_back(object);
                else fr.advanceOverCurrentFieldOrBlock();
            }

            if  (objectList.empty())
            {
                return ReadResult("No data loaded");
            }
            else if (objectList.size()==1)
            {
                return objectList.front();
            }
            else
            {
                return objectList.front();
            }
        }

        virtual ReadResult readNode(const std::string& file, const Options* opt) const
        {
            std::string ext = osgDB::getLowerCaseFileExtension(file);

            if (equalCaseInsensitive(ext,"osgs"))
            {
                std::istringstream fin(osgDB::getNameLessExtension(file));
                if (fin) return readNode(fin,opt);
                return ReadResult::ERROR_IN_READING_FILE;
            }

            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file, opt );
            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

            // code for setting up the database path so that internally referenced file are searched for on relative paths.
            osg::ref_ptr<Options> local_opt = opt ? static_cast<Options*>(opt->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
            local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));

            osgDB::ifstream fin(fileName.c_str());
            if (fin)
            {
                return readNode(fin, local_opt.get());
            }
            return 0L;

        }

        virtual ReadResult readNode(std::istream& fin, const Options* options) const
        {
            fin.imbue(std::locale::classic());

            Input fr;
            fr.attach(&fin);
            fr.setOptions(options);

            typedef std::vector<osg::Node*> NodeList;
            NodeList nodeList;

            // load all nodes in file, placing them in a group.
            while(!fr.eof())
            {
                Node *node = fr.readNode();
                if (node) nodeList.push_back(node);
                else fr.advanceOverCurrentFieldOrBlock();
            }

            if  (nodeList.empty())
            {
                return ReadResult("No data loaded");
            }
            else if (nodeList.size()==1)
            {
                return nodeList.front();
            }
            else
            {
                Group* group = new Group;
                group->setName("import group");
                for(NodeList::iterator itr=nodeList.begin();
                    itr!=nodeList.end();
                    ++itr)
                {
                    group->addChild(*itr);
                }
                return group;
            }

        }

        void setPrecision(Output& fout, const osgDB::ReaderWriter::Options* options) const
        {
            if (options)
            {
                std::istringstream iss(options->getOptionString());
                std::string opt;
                while (iss >> opt)
                {
                    if(opt=="PRECISION" || opt=="precision")
                    {
                        int prec;
                        iss >> prec;
                        fout.precision(prec);
                    }
                    if (opt=="OutputTextureFiles")
                    {
                        fout.setOutputTextureFiles(true);
                    }
                }
            }
        }

        virtual WriteResult writeObject(const Object& obj, const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
        {
            std::string ext = osgDB::getLowerCaseFileExtension(fileName);
            if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;

            Output fout(fileName.c_str());
            if (fout)
            {
                fout.setOptions(options);

                setPrecision(fout,options);

                fout.imbue(std::locale::classic());

                fout.writeObject(obj);
                fout.close();
                return WriteResult::FILE_SAVED;
            }
            return WriteResult("Unable to open file for output");
        }

        virtual WriteResult writeObject(const Object& obj,std::ostream& fout, const osgDB::ReaderWriter::Options* options) const
        {

            if (fout)
            {
                Output foutput;
                foutput.setOptions(options);

                std::ios &fios = foutput;
                fios.rdbuf(fout.rdbuf());

                fout.imbue(std::locale::classic());

                setPrecision(foutput,options);

                foutput.writeObject(obj);
                return WriteResult::FILE_SAVED;
            }
            return WriteResult("Unable to write to output stream");
        }

        virtual WriteResult writeNode(const Node& node, const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
        {
            std::string ext = getFileExtension(fileName);
            if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;

            Output fout(fileName.c_str());
            if (fout)
            {
                fout.setOptions(options);

                fout.imbue(std::locale::classic());

                setPrecision(fout,options);

                fout.writeObject(node);
                fout.close();
                return WriteResult::FILE_SAVED;
            }
            return WriteResult("Unable to open file for output");
        }

        virtual WriteResult writeNode(const Node& node, std::ostream& fout, const osgDB::ReaderWriter::Options* options) const
        {

            if (fout)
            {
                Output foutput;
                foutput.setOptions(options);

                std::ios &fios = foutput;
                fios.rdbuf(fout.rdbuf());

                foutput.imbue(std::locale::classic());

                setPrecision(foutput,options);

                foutput.writeObject(node);
                return WriteResult::FILE_SAVED;
            }
            return WriteResult("Unable to write to output stream");
        }

};

// now register with Registry to instantiate the above
// reader/writer.
REGISTER_OSGPLUGIN(osg, OSGReaderWriter)
<commit_msg>From Bryan Thrall, "The .osg plugin doesn't seem to support an option to write shader files separately, so it always inlines them in the .osg file (as far as I can tell). This change adds that ability. "<commit_after>#include <sstream>

#include <osg/Image>
#include <osg/Group>
#include <osg/Notify>

#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/fstream>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>

using namespace osg;
using namespace osgDB;

// pull in symbols from individual .o's to enable the static build to work
USE_DOTOSGWRAPPER(AlphaFunc)
USE_DOTOSGWRAPPER(AnimationPath)
USE_DOTOSGWRAPPER(AutoTransform)
USE_DOTOSGWRAPPER(Billboard)
USE_DOTOSGWRAPPER(BlendColor)
USE_DOTOSGWRAPPER(BlendEquation)
USE_DOTOSGWRAPPER(BlendFunc)
USE_DOTOSGWRAPPER(Camera)
USE_DOTOSGWRAPPER(CameraView)
USE_DOTOSGWRAPPER(ClearNode)
USE_DOTOSGWRAPPER(ClipNode)
USE_DOTOSGWRAPPER(ClipPlane)
USE_DOTOSGWRAPPER(ClusterCullingCallback)
USE_DOTOSGWRAPPER(ColorMask)
USE_DOTOSGWRAPPER(ColorMatrix)
USE_DOTOSGWRAPPER(ConvexPlanarOccluder)
USE_DOTOSGWRAPPER(CoordinateSystemNode)
USE_DOTOSGWRAPPER(CullFace)
USE_DOTOSGWRAPPER(Depth)
USE_DOTOSGWRAPPER(Drawable)
USE_DOTOSGWRAPPER(EllipsoidModel)
USE_DOTOSGWRAPPER(Fog)
USE_DOTOSGWRAPPER(FragmentProgram)
USE_DOTOSGWRAPPER(FrontFace)
USE_DOTOSGWRAPPER(Geode)
USE_DOTOSGWRAPPER(Geometry)
USE_DOTOSGWRAPPER(Group)
USE_DOTOSGWRAPPER(Image)
USE_DOTOSGWRAPPER(ImageSequence)
USE_DOTOSGWRAPPER(Light)
USE_DOTOSGWRAPPER(LightModel)
USE_DOTOSGWRAPPER(LightSource)
USE_DOTOSGWRAPPER(LineStipple)
USE_DOTOSGWRAPPER(LineWidth)
USE_DOTOSGWRAPPER(LOD)
USE_DOTOSGWRAPPER(Material)
USE_DOTOSGWRAPPER(MatrixTransform)
USE_DOTOSGWRAPPER(NodeCallback)
USE_DOTOSGWRAPPER(Node)
USE_DOTOSGWRAPPER(Object)
USE_DOTOSGWRAPPER(OccluderNode)
USE_DOTOSGWRAPPER(OcclusionQueryNode)
USE_DOTOSGWRAPPER(PagedLOD)
USE_DOTOSGWRAPPER(Point)
USE_DOTOSGWRAPPER(PointSprite)
USE_DOTOSGWRAPPER(PolygonMode)
USE_DOTOSGWRAPPER(PolygonOffset)
USE_DOTOSGWRAPPER(PositionAttitudeTransform)
USE_DOTOSGWRAPPER(Program)
USE_DOTOSGWRAPPER(Projection)
USE_DOTOSGWRAPPER(ProxyNode)
USE_DOTOSGWRAPPER(Scissor)
USE_DOTOSGWRAPPER(Sequence)
USE_DOTOSGWRAPPER(ShadeModel)
USE_DOTOSGWRAPPER(Shader)
USE_DOTOSGWRAPPER(Sphere)
USE_DOTOSGWRAPPER(Cone)
USE_DOTOSGWRAPPER(Capsule)
USE_DOTOSGWRAPPER(Box)
USE_DOTOSGWRAPPER(HeightField)
USE_DOTOSGWRAPPER(CompositeShape)
USE_DOTOSGWRAPPER(Cylinder)
USE_DOTOSGWRAPPER(ShapeDrawable)
USE_DOTOSGWRAPPER(StateAttribute)
USE_DOTOSGWRAPPER(StateSet)
USE_DOTOSGWRAPPER(Stencil)
USE_DOTOSGWRAPPER(Switch)
USE_DOTOSGWRAPPER(TessellationHints)
USE_DOTOSGWRAPPER(TexEnvCombine)
USE_DOTOSGWRAPPER(TexEnv)
USE_DOTOSGWRAPPER(TexEnvFilter)
USE_DOTOSGWRAPPER(TexGen)
USE_DOTOSGWRAPPER(TexGenNode)
USE_DOTOSGWRAPPER(TexMat)
USE_DOTOSGWRAPPER(Texture1D)
USE_DOTOSGWRAPPER(Texture2D)
USE_DOTOSGWRAPPER(Texture3D)
USE_DOTOSGWRAPPER(Texture)
USE_DOTOSGWRAPPER(TextureCubeMap)
USE_DOTOSGWRAPPER(TextureRectangle)
USE_DOTOSGWRAPPER(Transform)
USE_DOTOSGWRAPPER(Uniform)
USE_DOTOSGWRAPPER(VertexProgram)
USE_DOTOSGWRAPPER(Viewport)

class OSGReaderWriter : public ReaderWriter
{
    public:

        OSGReaderWriter()
        {
            supportsExtension("osg","OpenSceneGraph Ascii file format");
            supportsExtension("osgs","Psuedo OpenSceneGraph file loaded, with file encoded in filename string");
            supportsOption("precision","Set the floating point precision when writing out files");
            supportsOption("OutputTextureFiles","Write out the texture images to file");
        }

        virtual const char* className() const { return "OSG Reader/Writer"; }

        virtual ReadResult readObject(const std::string& file, const Options* opt) const
        {
            std::string ext = osgDB::getLowerCaseFileExtension(file);

            if (equalCaseInsensitive(ext,"osgs"))
            {
                std::istringstream fin(osgDB::getNameLessExtension(file));
                if (fin) return readNode(fin,opt);
                return ReadResult::ERROR_IN_READING_FILE;
            }

            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file, opt );
            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

            // code for setting up the database path so that internally referenced file are searched for on relative paths.
            osg::ref_ptr<Options> local_opt = opt ? static_cast<Options*>(opt->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
            local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));

            osgDB::ifstream fin(fileName.c_str());
            if (fin)
            {
                return readObject(fin, local_opt.get());
            }
            return 0L;
        }

        virtual ReadResult readObject(std::istream& fin, const Options* options) const
        {
            fin.imbue(std::locale::classic());

            Input fr;
            fr.attach(&fin);
            fr.setOptions(options);

            typedef std::vector<osg::Object*> ObjectList;
            ObjectList objectList;

            // load all nodes in file, placing them in a group.
            while(!fr.eof())
            {
                Object *object = fr.readObject();
                if (object) objectList.push_back(object);
                else fr.advanceOverCurrentFieldOrBlock();
            }

            if  (objectList.empty())
            {
                return ReadResult("No data loaded");
            }
            else if (objectList.size()==1)
            {
                return objectList.front();
            }
            else
            {
                return objectList.front();
            }
        }

        virtual ReadResult readNode(const std::string& file, const Options* opt) const
        {
            std::string ext = osgDB::getLowerCaseFileExtension(file);

            if (equalCaseInsensitive(ext,"osgs"))
            {
                std::istringstream fin(osgDB::getNameLessExtension(file));
                if (fin) return readNode(fin,opt);
                return ReadResult::ERROR_IN_READING_FILE;
            }

            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file, opt );
            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;

            // code for setting up the database path so that internally referenced file are searched for on relative paths.
            osg::ref_ptr<Options> local_opt = opt ? static_cast<Options*>(opt->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
            local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));

            osgDB::ifstream fin(fileName.c_str());
            if (fin)
            {
                return readNode(fin, local_opt.get());
            }
            return 0L;

        }

        virtual ReadResult readNode(std::istream& fin, const Options* options) const
        {
            fin.imbue(std::locale::classic());

            Input fr;
            fr.attach(&fin);
            fr.setOptions(options);

            typedef std::vector<osg::Node*> NodeList;
            NodeList nodeList;

            // load all nodes in file, placing them in a group.
            while(!fr.eof())
            {
                Node *node = fr.readNode();
                if (node) nodeList.push_back(node);
                else fr.advanceOverCurrentFieldOrBlock();
            }

            if  (nodeList.empty())
            {
                return ReadResult("No data loaded");
            }
            else if (nodeList.size()==1)
            {
                return nodeList.front();
            }
            else
            {
                Group* group = new Group;
                group->setName("import group");
                for(NodeList::iterator itr=nodeList.begin();
                    itr!=nodeList.end();
                    ++itr)
                {
                    group->addChild(*itr);
                }
                return group;
            }

        }

        void setPrecision(Output& fout, const osgDB::ReaderWriter::Options* options) const
        {
            if (options)
            {
                std::istringstream iss(options->getOptionString());
                std::string opt;
                while (iss >> opt)
                {
                    if(opt=="PRECISION" || opt=="precision")
                    {
                        int prec;
                        iss >> prec;
                        fout.precision(prec);
                    }
                    if (opt=="OutputTextureFiles")
                    {
                        fout.setOutputTextureFiles(true);
                    }
                    if (opt=="OutputShaderFiles")
                    {
                        fout.setOutputShaderFiles(true);
                    }
                }
            }
        }

        virtual WriteResult writeObject(const Object& obj, const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
        {
            std::string ext = osgDB::getLowerCaseFileExtension(fileName);
            if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;

            Output fout(fileName.c_str());
            if (fout)
            {
                fout.setOptions(options);

                setPrecision(fout,options);

                fout.imbue(std::locale::classic());

                fout.writeObject(obj);
                fout.close();
                return WriteResult::FILE_SAVED;
            }
            return WriteResult("Unable to open file for output");
        }

        virtual WriteResult writeObject(const Object& obj,std::ostream& fout, const osgDB::ReaderWriter::Options* options) const
        {

            if (fout)
            {
                Output foutput;
                foutput.setOptions(options);

                std::ios &fios = foutput;
                fios.rdbuf(fout.rdbuf());

                fout.imbue(std::locale::classic());

                setPrecision(foutput,options);

                foutput.writeObject(obj);
                return WriteResult::FILE_SAVED;
            }
            return WriteResult("Unable to write to output stream");
        }

        virtual WriteResult writeNode(const Node& node, const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
        {
            std::string ext = getFileExtension(fileName);
            if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;

            Output fout(fileName.c_str());
            if (fout)
            {
                fout.setOptions(options);

                fout.imbue(std::locale::classic());

                setPrecision(fout,options);

                fout.writeObject(node);
                fout.close();
                return WriteResult::FILE_SAVED;
            }
            return WriteResult("Unable to open file for output");
        }

        virtual WriteResult writeNode(const Node& node, std::ostream& fout, const osgDB::ReaderWriter::Options* options) const
        {

            if (fout)
            {
                Output foutput;
                foutput.setOptions(options);

                std::ios &fios = foutput;
                fios.rdbuf(fout.rdbuf());

                foutput.imbue(std::locale::classic());

                setPrecision(foutput,options);

                foutput.writeObject(node);
                return WriteResult::FILE_SAVED;
            }
            return WriteResult("Unable to write to output stream");
        }

};

// now register with Registry to instantiate the above
// reader/writer.
REGISTER_OSGPLUGIN(osg, OSGReaderWriter)
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
//
// This source file is part of the YETI open source package under the
// BSD (2-clause) licence (see LICENCE file for details).
//
// (c) H Hathrell, R F L Evans 2014. All rights reserved.
//
//-----------------------------------------------------------------------------

// System headers
#include <iostream>

// Program headers
#include "material.hpp"
#include "object.hpp"
#include "yeti.hpp"

namespace yeti{

//-----------------------------------------------------------------------------
// Function to determine material properties as a function of position
//-----------------------------------------------------------------------------
material_t get_material_properties(double x,double y,double z){ //determine pAZ from inshape

   // declare temporary object to store result
   material_t result;

   // define negative starting order
   int maxorder = -1;

   // loop over all objects in list
   for (unsigned int i=0; i<objects::object_list.size(); i++){

      // Test if point x,y,z is within object
      bool test_inside = objects::object_list[i]->inshape(x,y,z);

      // Test if object has greater hierarchy
      bool test_hierarchy = objects::object_list[i]->order>maxorder;

      // check for both conditions true
      if (test_inside && test_hierarchy ){

         // update result with copy of object
         result.p = objects::object_list[i]->p;

         // update max order
         maxorder=objects::object_list[i]->order;

      }

   }

   // return final parameters
   return result;

}

}
<commit_msg>Bugfix: Corrected missing pointers to Z and A values in material properties function<commit_after>//-----------------------------------------------------------------------------
//
// This source file is part of the YETI open source package under the
// BSD (2-clause) licence (see LICENCE file for details).
//
// (c) H Hathrell, R F L Evans 2014. All rights reserved.
//
//-----------------------------------------------------------------------------

// System headers
#include <iostream>

// Program headers
#include "material.hpp"
#include "object.hpp"
#include "yeti.hpp"

namespace yeti{

//-----------------------------------------------------------------------------
// Function to determine material properties as a function of position
//-----------------------------------------------------------------------------
material_t get_material_properties(double x,double y,double z){ //determine pAZ from inshape

   // declare temporary object to store result
   material_t result;

   // define negative starting order
   int maxorder = -1;

   // loop over all objects in list
   for (unsigned int i=0; i<objects::object_list.size(); i++){

      // Test if point x,y,z is within object
      bool test_inside = objects::object_list[i]->inshape(x,y,z);

      // Test if object has greater hierarchy
      bool test_hierarchy = objects::object_list[i]->order>maxorder;

      // check for both conditions true
      if (test_inside && test_hierarchy ){

         // update result with copy of object
         result.p = objects::object_list[i]->p;
         result.Z = objects::object_list[i]->Z;
         result.A = objects::object_list[i]->A;

         // update max order
         maxorder=objects::object_list[i]->order;

      }

   }

   // return final parameters
   return result;

}

}
<|endoftext|>


<commit_before>#include <node_version.h>

#if NODE_VERSION_AT_LEAST(0, 11, 1) && !defined(_MSC_VER)
#include <sys/types.h>
#endif

#include <errno.h>

#include <napi.h>

#if defined(_MSC_VER)
#include <time.h>
#include <windows.h>

// Pick GetSystemTimePreciseAsFileTime or GetSystemTimeAsFileTime depending
// on which is available at runtime.
typedef VOID(WINAPI *WinGetSystemTime)(LPFILETIME);
static WinGetSystemTime getSystemTime = NULL;

struct timezone {
  int tz_minuteswest;
  int tz_dsttime;
};

int gettimeofday(struct timeval *tv, struct timezone *tz) {
  FILETIME ft;
  (*getSystemTime)(&ft);
  unsigned long long t = ft.dwHighDateTime;
  t <<= 32;
  t |= ft.dwLowDateTime;
  t /= 10;
  t -= 11644473600000000ULL;
  tv->tv_sec = (long)(t / 1000000UL);
  tv->tv_usec = (long)(t % 1000000UL);

  return 0;
}
#else
#include <sys/time.h>
#endif

Napi::Value Now(const Napi::CallbackInfo &info) {
  timeval t;
  int r = gettimeofday(&t, NULL);

  if (r < 0) {
    Napi::Error e = Napi::Error::New(info.Env(), "gettimeofday");
    e.Set("code", Napi::Number::New(info.Env(), errno));
    throw e;
  }

  return Napi::Number::New(info.Env(), ((t.tv_sec * 1000000.0) + t.tv_usec));
}

Napi::Value NowDouble(const Napi::CallbackInfo &info) {
  timeval t;
  int r = gettimeofday(&t, NULL);
  if (r < 0) {
    Napi::Error e = Napi::Error::New(info.Env(), "gettimeofday");
    e.Set("code", Napi::Number::New(info.Env(), errno));
    throw e;
  }

  return Napi::Number::New(info.Env(), t.tv_sec + (t.tv_usec * 0.000001));
}

Napi::Value NowStruct(const Napi::CallbackInfo &info) {
  timeval t;
  int r = gettimeofday(&t, NULL);

  if (r < 0) {
    Napi::Error e = Napi::Error::New(info.Env(), "gettimeofday");
    e.Set("code", Napi::Number::New(info.Env(), errno));
    throw e;
  }

  Napi::Array array = Napi::Array::New(info.Env(), 2);
  array.Set((uint32_t)0, (double)t.tv_sec);
  array.Set((uint32_t)1, (double)t.tv_usec);

  return array;
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
  exports.Set(Napi::String::New(env, "now"), Napi::Function::New(env, Now));
  exports.Set(Napi::String::New(env, "nowDouble"),
              Napi::Function::New(env, NowDouble));
  exports.Set(Napi::String::New(env, "nowStruct"),
              Napi::Function::New(env, NowStruct));
#if defined(_MSC_VER)
  getSystemTime = (WinGetSystemTime)GetProcAddress(
      GetModuleHandle(TEXT("kernel32.dll")), "GetSystemTimePreciseAsFileTime");
  if (getSystemTime == NULL) {
    getSystemTime = &GetSystemTimeAsFileTime;
  }
#endif
  return exports;
}

NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init);
<commit_msg>Add more robust ErrnoException<commit_after>#include <node_version.h>

#if NODE_VERSION_AT_LEAST(0, 11, 1) && !defined(_MSC_VER)
#include <sys/types.h>
#endif

#include <errno.h>

#include <napi.h>

#if defined(_MSC_VER)
#include <time.h>
#include <windows.h>

// Pick GetSystemTimePreciseAsFileTime or GetSystemTimeAsFileTime depending
// on which is available at runtime.
typedef VOID(WINAPI *WinGetSystemTime)(LPFILETIME);
static WinGetSystemTime getSystemTime = NULL;

struct timezone {
  int tz_minuteswest;
  int tz_dsttime;
};

int gettimeofday(struct timeval *tv, struct timezone *tz) {
  FILETIME ft;
  (*getSystemTime)(&ft);
  unsigned long long t = ft.dwHighDateTime;
  t <<= 32;
  t |= ft.dwLowDateTime;
  t /= 10;
  t -= 11644473600000000ULL;
  tv->tv_sec = (long)(t / 1000000UL);
  tv->tv_usec = (long)(t % 1000000UL);

  return 0;
}
#else
#include <sys/time.h>
#endif

// A very basic version of Node::ErrnoException since Napi doesn't expose it
Napi::Error ErrnoException(Napi::Env env, int errorno) {
  Napi::Error e = Napi::Error::New(env, strerror(errorno));
  e.Set("syscall", Napi::String::New(env, "gettimeofday"));
  e.Set("errno", Napi::Number::New(env, errno));
  // NOTE: in Node::ErrnoException this would be the string of the code
  // like "EFAULT", just simplify with the number here.
  e.Set("code", Napi::Number::New(env, errno));
  return e;
}

Napi::Value Now(const Napi::CallbackInfo &info) {
  timeval t;
  int r = gettimeofday(&t, NULL);

  if (r < 0) {
    throw ErrnoException(info.Env(), errno);
  }

  return Napi::Number::New(info.Env(), ((t.tv_sec * 1000000.0) + t.tv_usec));
}

Napi::Value NowDouble(const Napi::CallbackInfo &info) {
  timeval t;
  int r = gettimeofday(&t, NULL);
  if (r < 0) {
    throw ErrnoException(info.Env(), errno);
  }

  return Napi::Number::New(info.Env(), t.tv_sec + (t.tv_usec * 0.000001));
}

Napi::Value NowStruct(const Napi::CallbackInfo &info) {
  timeval t;
  int r = gettimeofday(&t, NULL);

  if (r < 0) {
    throw ErrnoException(info.Env(), errno);
  }

  Napi::Array array = Napi::Array::New(info.Env(), 2);
  array.Set((uint32_t)0, (double)t.tv_sec);
  array.Set((uint32_t)1, (double)t.tv_usec);

  return array;
}

Napi::Object Init(Napi::Env env, Napi::Object exports) {
  exports.Set(Napi::String::New(env, "now"), Napi::Function::New(env, Now));
  exports.Set(Napi::String::New(env, "nowDouble"),
              Napi::Function::New(env, NowDouble));
  exports.Set(Napi::String::New(env, "nowStruct"),
              Napi::Function::New(env, NowStruct));
#if defined(_MSC_VER)
  getSystemTime = (WinGetSystemTime)GetProcAddress(
      GetModuleHandle(TEXT("kernel32.dll")), "GetSystemTimePreciseAsFileTime");
  if (getSystemTime == NULL) {
    getSystemTime = &GetSystemTimeAsFileTime;
  }
#endif
  return exports;
}

NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init);
<|endoftext|>