<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File SharedPtr.hpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Scientific Computing and Imaging Institute,
// University of Utah (USA) and Department of Aeronautics, Imperial
// College London (UK).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description:
//
///////////////////////////////////////////////////////////////////////////////

#ifndef NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_PTR_HPP
#define NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_PTR_HPP

#include <boost/config.hpp>   // for broken compiler workarounds

#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/detail/shared_count.hpp>
#include <boost/detail/workaround.hpp>

#include <memory>               // for std::auto_ptr
#include <algorithm>            // for std::swap
#include <functional>           // for std::less
#include <typeinfo>             // for std::bad_cast
#include <iosfwd>               // for std::basic_ostream

#ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash
    #pragma warning(push)
    #pragma warning(disable:4284) // odd return type for operator->
#endif

namespace Nektar
{
    struct static_cast_tag {};
    struct const_cast_tag {};
    struct dynamic_cast_tag {};
    struct polymorphic_cast_tag {};

    template<class T>
    class ptr
    {
        private:
            typedef ptr<T> this_type;

        public:
            typedef T element_type;
            typedef T value_type;
            typedef T* pointer;
            typedef T& reference;
            typedef const T& const_reference;

            template<typename Y>
            friend class ptr;

            ptr() :
                px(0),
                pn()
            {
            }

            template<class Y>
            explicit ptr(Y* p ) :
                px(p),
                pn(p)
            {
            }

            template<class Y, class D>
            ptr(Y* p, const D& d) :
                px(p),
                pn(p, d)
            {
            }

            template<class Y>
            ptr(const ptr<Y>& r) :
                px(r.px),
                pn(r.pn)
            {
            }

            ptr(const ptr<T>& rhs) :
                px(rhs.px),
                pn(rhs.pn)
            {
            }

            template<class Y>
            ptr(const ptr<Y>& r, static_cast_tag) :
                px(static_cast<element_type*>(r.px)),
                pn(r.pn)
            {
            }

            template<class Y>
            ptr(const ptr<Y>& r, const_cast_tag) :
                px(const_cast<element_type*>(r.px)),
                pn(r.pn)
            {
            }

            template<class Y>
            ptr(const ptr<Y>& r, dynamic_cast_tag) :
                px(dynamic_cast<element_type *>(r.px)),
                pn(r.pn)
            {
                if(px == 0) // need to allocate new counter -- the cast failed
                {
                    pn = boost::detail::shared_count();
                }
            }

            template<class Y>
            ptr(const ptr<Y>& r, polymorphic_cast_tag) :
                px(dynamic_cast<element_type *>(r.px)),
                pn(r.pn)
            {
                if(px == 0)
                {
                    boost::throw_exception(std::bad_cast());
                }
            }

            template<class Y>
            const ptr<T>& operator=(const ptr<Y>& r)
            {
                px = r.px;
                pn = r.pn;
                return *this;
            }

            const ptr<T>& operator=(const ptr<T>& r)
            {
                px = r.px;
                pn = r.pn;
                return *this;
            }

            void reset()
            {
                this_type().swap(*this);
            }

            template<class Y>
            void reset(Y* p)
            {
                BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
                this_type(p).swap(*this);
            }

            template<class Y, class D>
            void reset(Y* p, const D& d)
            {
                this_type(p, d).swap(*this);
            }

            const_reference operator*() const
            {
                BOOST_ASSERT(px != 0);
                return *px;
            }

            const T* operator->() const
            {
                BOOST_ASSERT(px != 0);
                return px;
            }

            const T* get() const
            {
                return px;
            }

            reference operator*()
            {
                BOOST_ASSERT(this->GetPx() != 0);
                return *(this->GetPx());
            }

            T* operator->()
            {
                BOOST_ASSERT(this->GetPx() != 0);
                return this->GetPx();
            }

            T* get()
            {
                return this->GetPx();
            }

            operator bool() const
            {
                return px != 0;
            }

            // operator! is redundant, but some compilers need it
            bool operator!() const
            {
                return px == 0;
            }

            bool unique() const
            {
                return pn.unique();
            }

            long use_count() const
            {
                return pn.use_count();
            }

            void swap(ptr<T>& other)
            {
                std::swap(px, other.px);
                pn.swap(other.pn);
            }

            template<class Y> bool
            internal_less(const ptr<Y>& rhs) const
            {
                return pn < rhs.pn;
            }

        protected:
            T* GetPx() const { return px; }
            boost::detail::shared_count& GetPn() const { return pn; }

        private:
            T* px;
            boost::detail::shared_count pn;

    };

    template<class T, class U>
    inline bool operator==(const ptr<T>& a, const ptr<U>& b)
    {
        return a.get() == b.get();
    }

    template<class T, class U>
    inline bool operator!=(const ptr<T>& a, const ptr<U>& b)
    {
        return a.get() != b.get();
    }

    template<class T, class U>
    inline bool operator<(const ptr<T>& a, const ptr<U>& b)
    {
        return a.internal_less(b);
    }

    template<class T>
    inline void swap(const ptr<T>& a, const ptr<T>& b)
    {
        a.swap(b);
    }

    template<class T, class U>
    ptr<T> static_pointer_cast(const ptr<U>& r)
    {
        return ptr<T>(r, static_cast_tag());
    }

    template<class T, class U>
    ptr<T> const_pointer_cast(const ptr<U>& r)
    {
        return ptr<T>(r, const_cast_tag());
    }

    template<class T, class U>
    ptr<T> dynamic_pointer_cast(const ptr<U>& r)
    {
        return ptr<T>(r, dynamic_cast_tag());
    }

    template<class T>
    inline const T* get_pointer(const ptr<T>& p)
    {
        return p.get();
    }

}

#endif //NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_PTR_HPP
<commit_msg>*** empty log message ***<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File SharedPtr.hpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Scientific Computing and Imaging Institute,
// University of Utah (USA) and Department of Aeronautics, Imperial
// College London (UK).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description:
//
///////////////////////////////////////////////////////////////////////////////

#ifndef NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_PTR_HPP
#define NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_PTR_HPP

#include <boost/config.hpp>   // for broken compiler workarounds

#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/detail/shared_count.hpp>
#include <boost/detail/workaround.hpp>

#include <memory>               // for std::auto_ptr
#include <algorithm>            // for std::swap
#include <functional>           // for std::less
#include <typeinfo>             // for std::bad_cast
#include <iosfwd>               // for std::basic_ostream

#ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash
    #pragma warning(push)
    #pragma warning(disable:4284) // odd return type for operator->
#endif

namespace Nektar
{
    struct static_cast_tag {};
    struct const_cast_tag {};
    struct dynamic_cast_tag {};
    struct polymorphic_cast_tag {};

    template<class T>
    class ptr
    {
        private:
            typedef boost::shared_ptr<T> this_type;

        public:
            typedef T element_type;
            typedef T value_type;
            typedef T* pointer;
            typedef T& reference;
            typedef const T& const_reference;

            template<typename Y>
            friend class ptr;

            ptr() :
                px(0),
                pn()
            {
            }

            template<class Y>
            explicit ptr(Y* p ) :
                px(p),
                pn(p)
            {
            }

            template<class Y, class D>
            ptr(Y* p, const D& d) :
                px(p),
                pn(p, d)
            {
            }

            template<class Y>
            ptr(const boost::shared_ptr<Y>& r) :
                px(r.px),
                pn(r.pn)
            {
            }

            ptr(const boost::shared_ptr<T>& rhs) :
                px(rhs.px),
                pn(rhs.pn)
            {
            }

            template<class Y>
            ptr(const boost::shared_ptr<Y>& r, static_cast_tag) :
                px(static_cast<element_type*>(r.px)),
                pn(r.pn)
            {
            }

            template<class Y>
            ptr(const boost::shared_ptr<Y>& r, const_cast_tag) :
                px(const_cast<element_type*>(r.px)),
                pn(r.pn)
            {
            }

            template<class Y>
            ptr(const boost::shared_ptr<Y>& r, dynamic_cast_tag) :
                px(dynamic_cast<element_type *>(r.px)),
                pn(r.pn)
            {
                if(px == 0) // need to allocate new counter -- the cast failed
                {
                    pn = boost::detail::shared_count();
                }
            }

            template<class Y>
            ptr(const boost::shared_ptr<Y>& r, polymorphic_cast_tag) :
                px(dynamic_cast<element_type *>(r.px)),
                pn(r.pn)
            {
                if(px == 0)
                {
                    boost::throw_exception(std::bad_cast());
                }
            }

            template<class Y>
            const boost::shared_ptr<T>& operator=(const boost::shared_ptr<Y>& r)
            {
                px = r.px;
                pn = r.pn;
                return *this;
            }

            const boost::shared_ptr<T>& operator=(const boost::shared_ptr<T>& r)
            {
                px = r.px;
                pn = r.pn;
                return *this;
            }

            void reset()
            {
                this_type().swap(*this);
            }

            template<class Y>
            void reset(Y* p)
            {
                BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
                this_type(p).swap(*this);
            }

            template<class Y, class D>
            void reset(Y* p, const D& d)
            {
                this_type(p, d).swap(*this);
            }

            const_reference operator*() const
            {
                BOOST_ASSERT(px != 0);
                return *px;
            }

            const T* operator->() const
            {
                BOOST_ASSERT(px != 0);
                return px;
            }

            const T* get() const
            {
                return px;
            }

            reference operator*()
            {
                BOOST_ASSERT(this->GetPx() != 0);
                return *(this->GetPx());
            }

            T* operator->()
            {
                BOOST_ASSERT(this->GetPx() != 0);
                return this->GetPx();
            }

            T* get()
            {
                return this->GetPx();
            }

            operator bool() const
            {
                return px != 0;
            }

            // operator! is redundant, but some compilers need it
            bool operator!() const
            {
                return px == 0;
            }

            bool unique() const
            {
                return pn.unique();
            }

            long use_count() const
            {
                return pn.use_count();
            }

            void swap(boost::shared_ptr<T>& other)
            {
                std::swap(px, other.px);
                pn.swap(other.pn);
            }

            template<class Y> bool
            internal_less(const boost::shared_ptr<Y>& rhs) const
            {
                return pn < rhs.pn;
            }

        protected:
            T* GetPx() const { return px; }
            boost::detail::shared_count& GetPn() const { return pn; }

        private:
            T* px;
            boost::detail::shared_count pn;

    };

    template<class T, class U>
    inline bool operator==(const boost::shared_ptr<T>& a, const boost::shared_ptr<U>& b)
    {
        return a.get() == b.get();
    }

    template<class T, class U>
    inline bool operator!=(const boost::shared_ptr<T>& a, const boost::shared_ptr<U>& b)
    {
        return a.get() != b.get();
    }

    template<class T, class U>
    inline bool operator<(const boost::shared_ptr<T>& a, const boost::shared_ptr<U>& b)
    {
        return a.internal_less(b);
    }

    template<class T>
    inline void swap(const boost::shared_ptr<T>& a, const boost::shared_ptr<T>& b)
    {
        a.swap(b);
    }

    template<class T, class U>
    boost::shared_ptr<T> static_pointer_cast(const boost::shared_ptr<U>& r)
    {
        return boost::shared_ptr<T>(r, static_cast_tag());
    }

    template<class T, class U>
    boost::shared_ptr<T> const_pointer_cast(const boost::shared_ptr<U>& r)
    {
        return boost::shared_ptr<T>(r, const_cast_tag());
    }

    template<class T, class U>
    boost::shared_ptr<T> dynamic_pointer_cast(const boost::shared_ptr<U>& r)
    {
        return boost::shared_ptr<T>(r, dynamic_cast_tag());
    }

    template<class T>
    inline const T* get_pointer(const boost::shared_ptr<T>& p)
    {
        return p.get();
    }

}

#endif //NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_PTR_HPP
<|endoftext|>


<commit_before>#include <stdio.h>

#include <osg/StateSet>
#include <osg/State>
#include <osg/Notify>

#include <osg/AlphaFunc>
#include <osg/Material>
#include <osg/CullFace>
#include <osg/FrontFace>
#include <osg/PolygonMode>
#include <osg/Transparency>
#include <osg/Depth>

using namespace osg;

StateSet::StateSet()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();
}

StateSet::StateSet(const StateSet& rhs):Object()
{
    _modeList = rhs._modeList;
    _attributeList = rhs._attributeList;

    _renderingHint = rhs._renderingHint;

    _binMode = rhs._binMode;
    _binNum = rhs._binNum;
    _binName = rhs._binName;
}

StateSet::~StateSet()
{
    // note, all attached state attributes will be automatically
    // unreferenced by ref_ptr<> and therefore there is no need to
    // delete the memory manually.
}

int StateSet::compare(const StateSet& rhs,bool compareAttributeContents) const
{

    if (compareAttributeContents)
    {
        // now check to see how the attributes compare.
        AttributeList::const_iterator lhs_attr_itr = _attributeList.begin();
        AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin();
        while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end())
        {
            if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
            else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
            if      (*(lhs_attr_itr->second.first)<*(rhs_attr_itr->second.first)) return -1;
            else if (*(rhs_attr_itr->second.first)<*(lhs_attr_itr->second.first)) return 1;
            if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
            else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
            ++lhs_attr_itr;
            ++rhs_attr_itr;
        }
        if (lhs_attr_itr==_attributeList.end())
        {
            if (rhs_attr_itr!=rhs._attributeList.end()) return -1;
        }
        else if (rhs_attr_itr == rhs._attributeList.end()) return 1;
    }
    else // just compare pointers.
    {
        // now check to see how the attributes compare.
        AttributeList::const_iterator lhs_attr_itr = _attributeList.begin();
        AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin();
        while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end())
        {
            if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
            else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
            if      (lhs_attr_itr->second.first<rhs_attr_itr->second.first) return -1;
            else if (rhs_attr_itr->second.first<lhs_attr_itr->second.first) return 1;
            if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
            else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
            ++lhs_attr_itr;
            ++rhs_attr_itr;
        }
        if (lhs_attr_itr==_attributeList.end())
        {
            if (rhs_attr_itr!=rhs._attributeList.end()) return -1;
        }
        else if (rhs_attr_itr == rhs._attributeList.end()) return 1;
    }

    // we've got here so attributes must be equal...

    // check to see how the modes compare.

    ModeList::const_iterator lhs_mode_itr = _modeList.begin();
    ModeList::const_iterator rhs_mode_itr = rhs._modeList.begin();
    while (lhs_mode_itr!=_modeList.end() && rhs_mode_itr!=rhs._modeList.end())
    {
        if      (lhs_mode_itr->first<rhs_mode_itr->first) return -1;
        else if (rhs_mode_itr->first<lhs_mode_itr->first) return 1;
        if      (lhs_mode_itr->second<rhs_mode_itr->second) return -1;
        else if (rhs_mode_itr->second<lhs_mode_itr->second) return 1;
        ++lhs_mode_itr;
        ++rhs_mode_itr;
    }
    if (lhs_mode_itr==_modeList.end())
    {
        if (rhs_mode_itr!=rhs._modeList.end()) return -1;
    }
    else if (rhs_mode_itr == rhs._modeList.end()) return 1;

    return 0;
}

void StateSet::setGlobalDefaults()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();

    setAttributeAndModes(new AlphaFunc,StateAttribute::OFF);
    setAttributeAndModes(new Transparency,StateAttribute::OFF);

    Material *material       = new Material;
    material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
    setAttributeAndModes(material,StateAttribute::ON);
/*
    setMode(GL_LIGHTING,StateAttribute::OFF);
    setMode(GL_FOG,StateAttribute::OFF);
    setMode(GL_POINT_SMOOTH,StateAttribute::OFF);

    setMode(GL_TEXTURE_2D,StateAttribute::OFF);

    setMode(GL_TEXTURE_GEN_S,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_T,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_R,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_Q,StateAttribute::OFF);

    setAttributeAndModes(new AlphaFunc,StateAttribute::OFF);
    setAttributeAndModes(new CullFace,StateAttribute::ON);
    setAttributeAndModes(new FrontFace,StateAttribute::ON);

    Material *material       = new Material;
    material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
    setAttributeAndModes(material,StateAttribute::ON);

    setAttributeAndModes(new PolygonMode,StateAttribute::OFF);
    setAttributeAndModes(new Transparency,StateAttribute::OFF);
    setAttributeAndModes(new Depth,StateAttribute::ON);
*/
}

void StateSet::setAllToInherit()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();

    _modeList.clear();
    _attributeList.clear();
}

void StateSet::merge(const StateSet& rhs)
{
    // merge the modes of rhs into this,
    // this overrides rhs if OVERRIDE defined in this.
    for(ModeList::const_iterator rhs_mitr = rhs._modeList.begin();
        rhs_mitr != rhs._modeList.begin();
        ++rhs_mitr)
    {
        ModeList::iterator lhs_mitr = _modeList.find(rhs_mitr->first);
        if (lhs_mitr!=_modeList.end())
        {
            if (!(lhs_mitr->second & StateAttribute::OVERRIDE))
            {
                // override isn't on in rhs, so overrite it with incomming
                // value.
                lhs_mitr->second = rhs_mitr->second;
            }
        }
        else
        {
            // entry doesn't exist so insert it.
            _modeList.insert(*rhs_mitr);
        }
    }

    // merge the attributes of rhs into this,
    // this overrides rhs if OVERRIDE defined in this.
    for(AttributeList::const_iterator rhs_aitr = rhs._attributeList.begin();
        rhs_aitr != rhs._attributeList.begin();
        ++rhs_aitr)
    {
        AttributeList::iterator lhs_aitr = _attributeList.find(rhs_aitr->first);
        if (lhs_aitr!=_attributeList.end())
        {
            if (!(lhs_aitr->second.second & StateAttribute::OVERRIDE))
            {
                // override isn't on in rhs, so overrite it with incomming
                // value.
                lhs_aitr->second = rhs_aitr->second;
            }
        }
        else
        {
            // entry doesn't exist so insert it.
            _attributeList.insert(*rhs_aitr);
        }
    }
}

void StateSet::setMode(const StateAttribute::GLMode mode, const StateAttribute::GLModeValue value)
{
    if ((value&StateAttribute::INHERIT)) setModeToInherit(mode);
    else _modeList[mode] = value;
}

void StateSet::setModeToInherit(const StateAttribute::GLMode mode)
{
    ModeList::iterator itr = _modeList.find(mode);
    if (itr!=_modeList.end())
    {
        _modeList.erase(itr);
    }
}

const StateAttribute::GLModeValue StateSet::getMode(const StateAttribute::GLMode mode) const
{
    ModeList::const_iterator itr = _modeList.find(mode);
    if (itr!=_modeList.end())
    {
        return itr->second;
    }
    else
        return StateAttribute::INHERIT;
}

void StateSet::setAttribute(StateAttribute *attribute, const StateAttribute::OverrideValue value)
{
    if (attribute)
    {
        if ((value&StateAttribute::INHERIT)) setAttributeToInherit(attribute->getType());
        else _attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
    }
}

void StateSet::setAttributeAndModes(StateAttribute *attribute, const StateAttribute::GLModeValue value)
{
    if (attribute)
    {
        _attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
        attribute->setStateSetModes(*this,value);
    }
}

void StateSet::setAttributeToInherit(const StateAttribute::Type type)
{
    AttributeList::iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        itr->second.first->setStateSetModes(*this,StateAttribute::INHERIT);
        _attributeList.erase(itr);
    }
}

StateAttribute* StateSet::getAttribute(const StateAttribute::Type type)
{
    AttributeList::iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return itr->second.first.get();
    }
    else
        return NULL;
}

const StateAttribute* StateSet::getAttribute(const StateAttribute::Type type) const
{
    AttributeList::const_iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return itr->second.first.get();
    }
    else
        return NULL;
}

const StateSet::RefAttributePair* StateSet::getAttributePair(const StateAttribute::Type type) const
{
    AttributeList::const_iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return &(itr->second);
    }
    else
        return NULL;
}

void StateSet::compile(State& state) const
{
    for(AttributeList::const_iterator itr = _attributeList.begin();
        itr!=_attributeList.end();
        ++itr)
    {
        itr->second.first->compile(state);
    }
}

void StateSet::setRenderingHint(const int hint)
{
    _renderingHint = hint;
    // temporary hack to get new render bins working.
    if (_renderingHint==TRANSPARENT_BIN)
    {
        _binMode = USE_RENDERBIN_DETAILS;
        _binNum = 1;
        _binName = "DepthSortedBin";
//        _binName = "RenderBin";
    }
}

void StateSet::setRenderBinDetails(const int binNum,const std::string& binName,const RenderBinMode mode)
{
    _binMode = mode;
    _binNum = binNum;
    _binName = binName;
}

void StateSet::setRendingBinToInherit()
{
    _binMode = INHERIT_RENDERBIN_DETAILS;
    _binNum = 0;
    _binName = "";
}
<commit_msg>Fixed bug in osg::StateSet::merge(..) where the containers were being iterated from begin() to begin() rather than begin() to end().<commit_after>#include <stdio.h>

#include <osg/StateSet>
#include <osg/State>
#include <osg/Notify>

#include <osg/AlphaFunc>
#include <osg/Material>
#include <osg/CullFace>
#include <osg/FrontFace>
#include <osg/PolygonMode>
#include <osg/Transparency>
#include <osg/Depth>

using namespace osg;

StateSet::StateSet()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();
}

StateSet::StateSet(const StateSet& rhs):Object()
{
    _modeList = rhs._modeList;
    _attributeList = rhs._attributeList;

    _renderingHint = rhs._renderingHint;

    _binMode = rhs._binMode;
    _binNum = rhs._binNum;
    _binName = rhs._binName;
}

StateSet::~StateSet()
{
    // note, all attached state attributes will be automatically
    // unreferenced by ref_ptr<> and therefore there is no need to
    // delete the memory manually.
}

int StateSet::compare(const StateSet& rhs,bool compareAttributeContents) const
{

    if (compareAttributeContents)
    {
        // now check to see how the attributes compare.
        AttributeList::const_iterator lhs_attr_itr = _attributeList.begin();
        AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin();
        while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end())
        {
            if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
            else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
            if      (*(lhs_attr_itr->second.first)<*(rhs_attr_itr->second.first)) return -1;
            else if (*(rhs_attr_itr->second.first)<*(lhs_attr_itr->second.first)) return 1;
            if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
            else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
            ++lhs_attr_itr;
            ++rhs_attr_itr;
        }
        if (lhs_attr_itr==_attributeList.end())
        {
            if (rhs_attr_itr!=rhs._attributeList.end()) return -1;
        }
        else if (rhs_attr_itr == rhs._attributeList.end()) return 1;
    }
    else // just compare pointers.
    {
        // now check to see how the attributes compare.
        AttributeList::const_iterator lhs_attr_itr = _attributeList.begin();
        AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin();
        while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end())
        {
            if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
            else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
            if      (lhs_attr_itr->second.first<rhs_attr_itr->second.first) return -1;
            else if (rhs_attr_itr->second.first<lhs_attr_itr->second.first) return 1;
            if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
            else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
            ++lhs_attr_itr;
            ++rhs_attr_itr;
        }
        if (lhs_attr_itr==_attributeList.end())
        {
            if (rhs_attr_itr!=rhs._attributeList.end()) return -1;
        }
        else if (rhs_attr_itr == rhs._attributeList.end()) return 1;
    }

    // we've got here so attributes must be equal...

    // check to see how the modes compare.

    ModeList::const_iterator lhs_mode_itr = _modeList.begin();
    ModeList::const_iterator rhs_mode_itr = rhs._modeList.begin();
    while (lhs_mode_itr!=_modeList.end() && rhs_mode_itr!=rhs._modeList.end())
    {
        if      (lhs_mode_itr->first<rhs_mode_itr->first) return -1;
        else if (rhs_mode_itr->first<lhs_mode_itr->first) return 1;
        if      (lhs_mode_itr->second<rhs_mode_itr->second) return -1;
        else if (rhs_mode_itr->second<lhs_mode_itr->second) return 1;
        ++lhs_mode_itr;
        ++rhs_mode_itr;
    }
    if (lhs_mode_itr==_modeList.end())
    {
        if (rhs_mode_itr!=rhs._modeList.end()) return -1;
    }
    else if (rhs_mode_itr == rhs._modeList.end()) return 1;

    return 0;
}

void StateSet::setGlobalDefaults()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();

    setAttributeAndModes(new AlphaFunc,StateAttribute::OFF);
    setAttributeAndModes(new Transparency,StateAttribute::OFF);

    Material *material       = new Material;
    material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
    setAttributeAndModes(material,StateAttribute::ON);
/*
    setMode(GL_LIGHTING,StateAttribute::OFF);
    setMode(GL_FOG,StateAttribute::OFF);
    setMode(GL_POINT_SMOOTH,StateAttribute::OFF);

    setMode(GL_TEXTURE_2D,StateAttribute::OFF);

    setMode(GL_TEXTURE_GEN_S,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_T,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_R,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_Q,StateAttribute::OFF);

    setAttributeAndModes(new AlphaFunc,StateAttribute::OFF);
    setAttributeAndModes(new CullFace,StateAttribute::ON);
    setAttributeAndModes(new FrontFace,StateAttribute::ON);

    Material *material       = new Material;
    material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
    setAttributeAndModes(material,StateAttribute::ON);

    setAttributeAndModes(new PolygonMode,StateAttribute::OFF);
    setAttributeAndModes(new Transparency,StateAttribute::OFF);
    setAttributeAndModes(new Depth,StateAttribute::ON);
*/
}

void StateSet::setAllToInherit()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();

    _modeList.clear();
    _attributeList.clear();
}

void StateSet::merge(const StateSet& rhs)
{
    // merge the modes of rhs into this,
    // this overrides rhs if OVERRIDE defined in this.
    for(ModeList::const_iterator rhs_mitr = rhs._modeList.begin();
        rhs_mitr != rhs._modeList.end();
        ++rhs_mitr)
    {
        ModeList::iterator lhs_mitr = _modeList.find(rhs_mitr->first);
        if (lhs_mitr!=_modeList.end())
        {
            if (!(lhs_mitr->second & StateAttribute::OVERRIDE))
            {
                // override isn't on in rhs, so overrite it with incomming
                // value.
                lhs_mitr->second = rhs_mitr->second;
            }
        }
        else
        {
            // entry doesn't exist so insert it.
            _modeList.insert(*rhs_mitr);
        }
    }

    // merge the attributes of rhs into this,
    // this overrides rhs if OVERRIDE defined in this.
    for(AttributeList::const_iterator rhs_aitr = rhs._attributeList.begin();
        rhs_aitr != rhs._attributeList.end();
        ++rhs_aitr)
    {
        AttributeList::iterator lhs_aitr = _attributeList.find(rhs_aitr->first);
        if (lhs_aitr!=_attributeList.end())
        {
            if (!(lhs_aitr->second.second & StateAttribute::OVERRIDE))
            {
                // override isn't on in rhs, so overrite it with incomming
                // value.
                lhs_aitr->second = rhs_aitr->second;
            }
        }
        else
        {
            // entry doesn't exist so insert it.
            _attributeList.insert(*rhs_aitr);
        }
    }

    // need to merge rendering hints
    // but will need to think how best to do this first
    // RO, Nov. 2001.

}

void StateSet::setMode(const StateAttribute::GLMode mode, const StateAttribute::GLModeValue value)
{
    if ((value&StateAttribute::INHERIT)) setModeToInherit(mode);
    else _modeList[mode] = value;
}

void StateSet::setModeToInherit(const StateAttribute::GLMode mode)
{
    ModeList::iterator itr = _modeList.find(mode);
    if (itr!=_modeList.end())
    {
        _modeList.erase(itr);
    }
}

const StateAttribute::GLModeValue StateSet::getMode(const StateAttribute::GLMode mode) const
{
    ModeList::const_iterator itr = _modeList.find(mode);
    if (itr!=_modeList.end())
    {
        return itr->second;
    }
    else
        return StateAttribute::INHERIT;
}

void StateSet::setAttribute(StateAttribute *attribute, const StateAttribute::OverrideValue value)
{
    if (attribute)
    {
        if ((value&StateAttribute::INHERIT)) setAttributeToInherit(attribute->getType());
        else _attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
    }
}

void StateSet::setAttributeAndModes(StateAttribute *attribute, const StateAttribute::GLModeValue value)
{
    if (attribute)
    {
        _attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
        attribute->setStateSetModes(*this,value);
    }
}

void StateSet::setAttributeToInherit(const StateAttribute::Type type)
{
    AttributeList::iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        itr->second.first->setStateSetModes(*this,StateAttribute::INHERIT);
        _attributeList.erase(itr);
    }
}

StateAttribute* StateSet::getAttribute(const StateAttribute::Type type)
{
    AttributeList::iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return itr->second.first.get();
    }
    else
        return NULL;
}

const StateAttribute* StateSet::getAttribute(const StateAttribute::Type type) const
{
    AttributeList::const_iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return itr->second.first.get();
    }
    else
        return NULL;
}

const StateSet::RefAttributePair* StateSet::getAttributePair(const StateAttribute::Type type) const
{
    AttributeList::const_iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return &(itr->second);
    }
    else
        return NULL;
}

void StateSet::compile(State& state) const
{
    for(AttributeList::const_iterator itr = _attributeList.begin();
        itr!=_attributeList.end();
        ++itr)
    {
        itr->second.first->compile(state);
    }
}

void StateSet::setRenderingHint(const int hint)
{
    _renderingHint = hint;
    // temporary hack to get new render bins working.
    if (_renderingHint==TRANSPARENT_BIN)
    {
        _binMode = USE_RENDERBIN_DETAILS;
        _binNum = 1;
        _binName = "DepthSortedBin";
//        _binName = "RenderBin";
    }
}

void StateSet::setRenderBinDetails(const int binNum,const std::string& binName,const RenderBinMode mode)
{
    _binMode = mode;
    _binNum = binNum;
    _binName = binName;
}

void StateSet::setRendingBinToInherit()
{
    _binMode = INHERIT_RENDERBIN_DETAILS;
    _binNum = 0;
    _binName = "";
}
<|endoftext|>


<commit_before>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          http://www.mrpt.org/                          |
   |                                                                        |
   | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file     |
   | See: http://www.mrpt.org/Authors - All rights reserved.                |
   | Released under BSD License. See details in http://www.mrpt.org/License |
   +------------------------------------------------------------------------+ */

#include <mrpt/hwdrivers/CGPSInterface.h>
#include <gtest/gtest.h>

using namespace mrpt;
using namespace mrpt::hwdrivers;
using namespace mrpt::obs;
using namespace std;

// Example cmds:
// https://www.sparkfun.com/datasheets/GPS/NMEA%20Reference%20Manual-Rev2.1-Dec07.pdf

TEST(CGPSInterface, parse_NMEA_GGA)
{
	// Test with a correct frame:
	{
		const char* test_cmd =
			"$GPGGA,101830.00,3649.76162994,N,00224.53709052,W,2,08,1.1,9.3,M,"
			"47.4,M,5.0,0120*58";
		mrpt::obs::CObservationGPS obsGPS;
		const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
		EXPECT_TRUE(parse_ret) << "Failed parse of: " << test_cmd << endl;

		const gnss::Message_NMEA_GGA* msg =
			obsGPS.getMsgByClassPtr<gnss::Message_NMEA_GGA>();
		EXPECT_TRUE(msg != nullptr);
		if (!msg) return;
		EXPECT_NEAR(
			msg->fields.latitude_degrees, 36 + 49.76162994 / 60.0, 1e-10);
		EXPECT_NEAR(
			msg->fields.longitude_degrees, -(002 + 24.53709052 / 60.0), 1e-10);
		EXPECT_NEAR(msg->fields.altitude_meters, 9.3, 1e-10);
	}
	// Test with an empty frame:
	{
		const char* test_cmd = "$GPGGA,,,,,,0,,,,M,,M,,*6";
		mrpt::obs::CObservationGPS obsGPS;
		const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
		EXPECT_FALSE(parse_ret);
	}
}

TEST(CGPSInterface, parse_NMEA_RMC)
{
	const char* test_cmd =
		"$GPRMC,161229.487,A,3723.2475,N,12158.3416,W,0.13,309.62,120598, ,*10";
	mrpt::obs::CObservationGPS obsGPS;
	const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
	EXPECT_TRUE(parse_ret) << "Failed parse of: " << test_cmd << endl;

	const gnss::Message_NMEA_RMC* msg =
		obsGPS.getMsgByClassPtr<gnss::Message_NMEA_RMC>();

	EXPECT_TRUE(msg != nullptr);
	if (!msg) return;
	EXPECT_NEAR(msg->fields.latitude_degrees, 37 + 23.2475 / 60.0, 1e-10);
	EXPECT_NEAR(msg->fields.longitude_degrees, -(121 + 58.3416 / 60.0), 1e-10);
}

TEST(CGPSInterface, parse_NMEA_GLL)
{
	const char* test_cmd = "$GPGLL,3723.2475,N,12158.3416,W,161229.487,A,A*41";
	mrpt::obs::CObservationGPS obsGPS;
	const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
	EXPECT_TRUE(parse_ret) << "Failed parse of: " << test_cmd << endl;

	const gnss::Message_NMEA_GLL* msg =
		obsGPS.getMsgByClassPtr<gnss::Message_NMEA_GLL>();

	EXPECT_TRUE(msg != nullptr);
	if (!msg) return;
	EXPECT_NEAR(msg->fields.latitude_degrees, 37 + 23.2475 / 60.0, 1e-10);
	EXPECT_NEAR(msg->fields.longitude_degrees, -(121 + 58.3416 / 60.0), 1e-10);
}

TEST(CGPSInterface, parse_NMEA_VTG)
{
	const char* test_cmd = "$GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48";
	mrpt::obs::CObservationGPS obsGPS;
	const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
	EXPECT_TRUE(parse_ret) << "Failed parse of: " << test_cmd << endl;

	const gnss::Message_NMEA_VTG* msg =
		obsGPS.getMsgByClassPtr<gnss::Message_NMEA_VTG>();

	EXPECT_TRUE(msg != nullptr);
	if (!msg) return;
	EXPECT_NEAR(msg->fields.true_track, 54.7, 1e-6);
	EXPECT_NEAR(msg->fields.magnetic_track, 34.4, 1e-6);
	EXPECT_NEAR(msg->fields.ground_speed_knots, 5.5, 1e-6);
	EXPECT_NEAR(msg->fields.ground_speed_kmh, 10.2, 1e-6);
}

TEST(CGPSInterface, parse_NMEA_ZDA)
{
	const char* test_cmd = "$GPZDA,181813,14,10,2003,00,00*4F";
	mrpt::obs::CObservationGPS obsGPS;
	const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
	EXPECT_TRUE(parse_ret) << "Failed parse of: " << test_cmd << endl;

	const gnss::Message_NMEA_ZDA* msg =
		obsGPS.getMsgByClassPtr<gnss::Message_NMEA_ZDA>();

	EXPECT_TRUE(msg != nullptr);
	if (!msg) return;
	EXPECT_TRUE(msg->fields.date_day == 14);
	EXPECT_TRUE(msg->fields.date_month == 10);
	EXPECT_TRUE(msg->fields.date_year == 2003);
	EXPECT_TRUE(msg->fields.UTCTime.hour == 18);
	EXPECT_TRUE(msg->fields.UTCTime.minute == 18);
	EXPECT_TRUE(msg->fields.UTCTime.sec == 13.0);  // Replaced from EXPECT_EQ()
	// to avoid a "bus error" in
	// a gtest template under
	// armhf.
}
<commit_msg>more GPS unit tests<commit_after>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          http://www.mrpt.org/                          |
   |                                                                        |
   | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file     |
   | See: http://www.mrpt.org/Authors - All rights reserved.                |
   | Released under BSD License. See details in http://www.mrpt.org/License |
   +------------------------------------------------------------------------+ */

#include <mrpt/hwdrivers/CGPSInterface.h>
#include <mrpt/io/CMemoryStream.h>
#include <gtest/gtest.h>

using namespace mrpt;
using namespace mrpt::hwdrivers;
using namespace mrpt::obs;
using namespace std;

// Example cmds:
// https://www.sparkfun.com/datasheets/GPS/NMEA%20Reference%20Manual-Rev2.1-Dec07.pdf

TEST(CGPSInterface, parse_NMEA_GGA)
{
	// Test with a correct frame:
	{
		const char* test_cmd =
			"$GPGGA,101830.00,3649.76162994,N,00224.53709052,W,2,08,1.1,9.3,M,"
			"47.4,M,5.0,0120*58";
		mrpt::obs::CObservationGPS obsGPS;
		const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
		EXPECT_TRUE(parse_ret) << "Failed parse of: " << test_cmd << endl;

		const gnss::Message_NMEA_GGA* msg =
			obsGPS.getMsgByClassPtr<gnss::Message_NMEA_GGA>();
		EXPECT_TRUE(msg != nullptr);
		if (!msg) return;
		EXPECT_NEAR(
			msg->fields.latitude_degrees, 36 + 49.76162994 / 60.0, 1e-10);
		EXPECT_NEAR(
			msg->fields.longitude_degrees, -(002 + 24.53709052 / 60.0), 1e-10);
		EXPECT_NEAR(msg->fields.altitude_meters, 9.3, 1e-10);
	}
	// Test with an empty frame:
	{
		const char* test_cmd = "$GPGGA,,,,,,0,,,,M,,M,,*6";
		mrpt::obs::CObservationGPS obsGPS;
		const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
		EXPECT_FALSE(parse_ret);
	}
}

TEST(CGPSInterface, parse_NMEA_RMC)
{
	const char* test_cmd =
		"$GPRMC,161229.487,A,3723.2475,N,12158.3416,W,0.13,309.62,120598, ,*10";
	mrpt::obs::CObservationGPS obsGPS;
	const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
	EXPECT_TRUE(parse_ret) << "Failed parse of: " << test_cmd << endl;

	const gnss::Message_NMEA_RMC* msg =
		obsGPS.getMsgByClassPtr<gnss::Message_NMEA_RMC>();

	EXPECT_TRUE(msg != nullptr);
	if (!msg) return;
	EXPECT_NEAR(msg->fields.latitude_degrees, 37 + 23.2475 / 60.0, 1e-10);
	EXPECT_NEAR(msg->fields.longitude_degrees, -(121 + 58.3416 / 60.0), 1e-10);
}

TEST(CGPSInterface, parse_NMEA_GLL)
{
	const char* test_cmd = "$GPGLL,3723.2475,N,12158.3416,W,161229.487,A,A*41";
	mrpt::obs::CObservationGPS obsGPS;
	const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
	EXPECT_TRUE(parse_ret) << "Failed parse of: " << test_cmd << endl;

	const gnss::Message_NMEA_GLL* msg =
		obsGPS.getMsgByClassPtr<gnss::Message_NMEA_GLL>();

	EXPECT_TRUE(msg != nullptr);
	if (!msg) return;
	EXPECT_NEAR(msg->fields.latitude_degrees, 37 + 23.2475 / 60.0, 1e-10);
	EXPECT_NEAR(msg->fields.longitude_degrees, -(121 + 58.3416 / 60.0), 1e-10);
}

TEST(CGPSInterface, parse_NMEA_VTG)
{
	const char* test_cmd = "$GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48";
	mrpt::obs::CObservationGPS obsGPS;
	const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
	EXPECT_TRUE(parse_ret) << "Failed parse of: " << test_cmd << endl;

	const gnss::Message_NMEA_VTG* msg =
		obsGPS.getMsgByClassPtr<gnss::Message_NMEA_VTG>();

	EXPECT_TRUE(msg != nullptr);
	if (!msg) return;
	EXPECT_NEAR(msg->fields.true_track, 54.7, 1e-6);
	EXPECT_NEAR(msg->fields.magnetic_track, 34.4, 1e-6);
	EXPECT_NEAR(msg->fields.ground_speed_knots, 5.5, 1e-6);
	EXPECT_NEAR(msg->fields.ground_speed_kmh, 10.2, 1e-6);
}

TEST(CGPSInterface, parse_NMEA_ZDA)
{
	const char* test_cmd = "$GPZDA,181813,14,10,2003,00,00*4F";
	mrpt::obs::CObservationGPS obsGPS;
	const bool parse_ret = CGPSInterface::parse_NMEA(test_cmd, obsGPS);
	EXPECT_TRUE(parse_ret) << "Failed parse of: " << test_cmd << endl;

	const gnss::Message_NMEA_ZDA* msg =
		obsGPS.getMsgByClassPtr<gnss::Message_NMEA_ZDA>();

	EXPECT_TRUE(msg != nullptr);
	if (!msg) return;
	EXPECT_TRUE(msg->fields.date_day == 14);
	EXPECT_TRUE(msg->fields.date_month == 10);
	EXPECT_TRUE(msg->fields.date_year == 2003);
	EXPECT_TRUE(msg->fields.UTCTime.hour == 18);
	EXPECT_TRUE(msg->fields.UTCTime.minute == 18);
	EXPECT_TRUE(msg->fields.UTCTime.sec == 13.0);
	// Replaced from EXPECT_EQ() to avoid a "bus error" in  a gtest template
	// under armhf.
}

TEST(CGPSInterface, parse_NMEA_ZDA_stream)
{
	mrpt::io::CMemoryStream buf;
	{
		const std::string s("$GPZDA,181813,14,10,2003,00,00*4F\n");
		buf.Write(s.c_str(), s.size());
		buf.Seek(0);
	}

	CGPSInterface gps;
	gps.bindStream(&buf);

	gps.initialize();
	gps.doProcess();

	mrpt::hwdrivers::CGenericSensor::TListObservations obss;
	gps.getObservations(obss);

	EXPECT_EQ(obss.size(), 1U);

	auto obsGPS = mrpt::ptr_cast<CObservationGPS>::from(obss.begin()->second);

	const gnss::Message_NMEA_ZDA* msg =
		obsGPS->getMsgByClassPtr<gnss::Message_NMEA_ZDA>();

	EXPECT_TRUE(msg != nullptr);
	if (!msg) return;
	EXPECT_TRUE(msg->fields.date_day == 14);
	EXPECT_TRUE(msg->fields.date_month == 10);
	EXPECT_TRUE(msg->fields.date_year == 2003);
	EXPECT_TRUE(msg->fields.UTCTime.hour == 18);
	EXPECT_TRUE(msg->fields.UTCTime.minute == 18);
	EXPECT_TRUE(msg->fields.UTCTime.sec == 13.0);
	// Replaced from EXPECT_EQ() to avoid a "bus error" in  a gtest template
	// under armhf.
}

TEST(CGPSInterface, parse_NOVATEL6_stream)
{
	mrpt::io::CMemoryStream buf;
	{
		const unsigned char sample_novatel6_gps[] = {
			0xaa, 0x44, 0x12, 0x1c, 0x2a, 0x00, 0x00, 0xa0, 0x48, 0x00, 0x00,
			0x00, 0x5a, 0xb4, 0x59, 0x07, 0x10, 0x4a, 0xb7, 0x16, 0x00, 0x00,
			0x00, 0x00, 0xf6, 0xb1, 0x4a, 0x34, 0x00, 0x00, 0x00, 0x00, 0x38,
			0x00, 0x00, 0x00, 0x97, 0x2b, 0x45, 0xa9, 0xc8, 0x6a, 0x42, 0x40,
			0xfc, 0x54, 0x43, 0x6f, 0x11, 0x18, 0x03, 0xc0, 0x00, 0x00, 0x20,
			0x8f, 0xe8, 0x0e, 0x1c, 0x40, 0x66, 0x66, 0x48, 0x42, 0x3d, 0x00,
			0x00, 0x00, 0x1d, 0x9b, 0x96, 0x3c, 0x2c, 0xd5, 0x9c, 0x3c, 0xd1,
			0x39, 0xa8, 0x3c, 0x35, 0x35, 0x35, 0x00, 0x00, 0x00, 0x60, 0x41,
			0x00, 0x00, 0x00, 0x00, 0x0f, 0x0e, 0x0e, 0x0d, 0x00, 0x00, 0x00,
			0x33, 0x82, 0xba, 0x79, 0xe5, 0xaa, 0x44, 0x13, 0x58, 0xfc, 0x01,
			0x59, 0x07, 0x10, 0x4a, 0xb7, 0x16, 0x59, 0x07, 0x00, 0x00, 0x33,
			0x33, 0x33, 0x33, 0xdb, 0x42, 0x17, 0x41, 0xa7, 0xf0, 0xaf, 0xa5,
			0xc8, 0x6a, 0x42, 0x40, 0xa2, 0xad, 0xac, 0x28, 0x12, 0x18, 0x03,
			0xc0, 0x00, 0x00, 0x8a, 0x8b, 0x52, 0x8d, 0x4c, 0x40, 0x10, 0xe2,
			0xdb, 0x3c, 0x4b, 0xbd, 0x82, 0xbf, 0x52, 0x23, 0x1e, 0x50, 0x08,
			0xf1, 0x9b, 0xbf, 0xd4, 0xa6, 0xd1, 0x7c, 0xcd, 0x16, 0xc8, 0x3f,
			0x31, 0x27, 0xe1, 0x16, 0xa2, 0x6b, 0x10, 0x40, 0xc7, 0x1c, 0xc7,
			0x39, 0x6a, 0x9c, 0x00, 0x40, 0xa0, 0x3c, 0x9f, 0x79, 0xca, 0xdd,
			0x63, 0x40, 0x03, 0x00, 0x00, 0x00, 0x27, 0xbb, 0xff, 0xf8, 0xaa,
			0x44, 0x12, 0x1c, 0x2a, 0x00, 0x00, 0xa0, 0x48, 0x00, 0x00, 0x00,
			0x5a, 0xb4, 0x59, 0x07, 0x42, 0x4a, 0xb7, 0x16, 0x00, 0x00, 0x00,
			0x00, 0xf6, 0xb1, 0x4a, 0x34, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00,
			0x00, 0x00, 0xf0, 0x23, 0x3c, 0xa9, 0xc8, 0x6a, 0x42, 0x40, 0xdd,
			0x10, 0x6c, 0x71, 0x11, 0x18, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x03,
			0xa7, 0x18, 0x1c, 0x40, 0x66, 0x66, 0x48, 0x42, 0x3d, 0x00, 0x00,
			0x00, 0x32, 0x9b, 0x96, 0x3c, 0x82, 0xd4, 0x9c, 0x3c, 0x5d, 0x3a,
			0xa8, 0x3c, 0x35, 0x35, 0x35, 0x00, 0x00, 0x00, 0x60, 0x41, 0x00,
			0x00, 0x00, 0x00, 0x0f, 0x0e, 0x0e, 0x0d, 0x00, 0x00, 0x00, 0x33,
			0xcb, 0x95, 0xa0, 0x9b, 0xaa, 0x44, 0x13, 0x58, 0xfc, 0x01, 0x59,
			0x07, 0x42, 0x4a, 0xb7, 0x16, 0x59, 0x07, 0x00, 0x00, 0x67, 0x66,
			0x66, 0x66, 0xdb, 0x42, 0x17, 0x41, 0xe6, 0xae, 0xa1, 0xa5, 0xc8,
			0x6a, 0x42, 0x40, 0x26, 0x1e, 0x82, 0x2b, 0x12, 0x18, 0x03, 0xc0,
			0x00, 0x00, 0x62, 0xb6, 0x8b, 0x8e, 0x4c, 0x40, 0x10, 0x63, 0x42,
			0x19, 0x38, 0x19, 0x7a, 0xbf, 0x1e, 0xa9, 0x79, 0x02, 0x24, 0x6c,
			0x9d, 0xbf, 0x52, 0x13, 0x38, 0xa4, 0x35, 0x2c, 0xc8, 0x3f, 0xa9,
			0x3b, 0x21, 0x59, 0xe0, 0xa0, 0x10, 0x40, 0x51, 0xd1, 0x8c, 0x50,
			0x0b, 0xa0, 0x00, 0x40, 0x16, 0x40, 0x94, 0xbe, 0xc2, 0xdd, 0x63,
			0x40, 0x03, 0x00, 0x00, 0x00, 0x20, 0x4d, 0xe7, 0xa2, 0xaa, 0x44,
			0x12, 0x1c, 0x2a, 0x00, 0x00, 0xa0, 0x48, 0x00, 0x00, 0x00, 0x5a,
			0xb4, 0x59, 0x07, 0x74, 0x4a, 0xb7, 0x16, 0x00, 0x00, 0x00, 0x00,
			0xf6, 0xb1, 0x4a, 0x34, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00,
			0x00, 0xaa, 0x41, 0x32, 0xa9, 0xc8, 0x6a, 0x42, 0x40, 0xff, 0x59,
			0xa8, 0x73, 0x11, 0x18, 0x03, 0xc0, 0x00, 0x00, 0xa0, 0xd6, 0x6b,
			0x22, 0x1c, 0x40, 0x66, 0x66, 0x48, 0x42, 0x3d, 0x00, 0x00, 0x00,
			0x92, 0x9b, 0x96, 0x3c, 0x70, 0xd3, 0x9c, 0x3c, 0x06, 0x3b, 0xa8,
			0x3c, 0x35, 0x35, 0x35, 0x00};
		const unsigned int sample_novatel6_gps_len = 500;
		buf.Write(sample_novatel6_gps, sample_novatel6_gps_len);
		buf.Seek(0);
	}

	CGPSInterface gps;
	gps.bindStream(&buf);

	gps.initialize();
	gps.doProcess();

	mrpt::hwdrivers::CGenericSensor::TListObservations obss;
	gps.getObservations(obss);

	EXPECT_EQ(obss.size(), 4U);

	auto itObs = obss.begin();
	auto obsGPS1 = mrpt::ptr_cast<CObservationGPS>::from(itObs->second);
	++itObs;
	auto obsGPS2 = mrpt::ptr_cast<CObservationGPS>::from(itObs->second);

	EXPECT_TRUE(obsGPS1);
	EXPECT_TRUE(obsGPS2);

	const auto* msg1 =
		obsGPS1->getMsgByClassPtr<gnss::Message_NV_OEM6_BESTPOS>();
	EXPECT_TRUE(msg1 != nullptr);
	if (!msg1) return;
	EXPECT_TRUE(msg1->fields.num_sats_tracked == 15);

	const auto* msg2 =
		obsGPS2->getMsgByClassPtr<gnss::Message_NV_OEM6_INSPVAS>();
	EXPECT_TRUE(msg2 != nullptr);
	if (!msg2) return;
	EXPECT_NEAR(msg2->fields.roll, 4.10511, 1e-4);
}
<|endoftext|>


<commit_before>
#include "ofPixelUtils.h"
#include "ofPixels.h"

void ofPixelUtils::crop(ofPixels & pix, int x, int y, int _width, int _height){

	if (pix.bAllocated == true){

		int width = pix.width;
		int height = pix.height;
		int bytesPerPixel = pix.bytesPerPixel;

		unsigned char * newPixels = new unsigned char [width*height*bytesPerPixel];
		int newWidth = _width;
		int newHeight = _height;
		memset(newPixels, 0, width*height*pix.bytesPerPixel);

		// this prevents having to do a check for bounds in the for loop;
		int minX = MAX(x, 0);
		int maxX = MIN(x+_width, width);
		int minY = MAX(y, 0);
		int maxY = MIN(y+_height, height);

		// TODO: point math can help speed this up:
		for (int i = minX; i < maxX; i++){
			for (int j = minY; j < maxY; j++){

				int newPixel = (j-y) * newWidth + (i-x);
				int oldPixel = (j) * width + (i);

				for (int k = 0; k < bytesPerPixel; k++){
					newPixels[newPixel*bytesPerPixel + k] = pix.pixels[oldPixel*bytesPerPixel + k];
				}
			}
		}

		delete [] pix.pixels;
		pix.pixels = newPixels;
		pix.width = newWidth;
		pix.height = newHeight;
	}

}

void ofPixelUtils::rotate90(ofPixels & pix, int nClockwiseRotations){

}

void ofPixelUtils::mirror(ofPixels & pix, bool vertically, bool horizontal){

}<commit_msg>fixed a silly error in ofPixelUtils<commit_after>
#include "ofPixelUtils.h"
#include "ofPixels.h"

// TODO: more optimized non in place versions of these functions.

void ofPixelUtils::crop(ofPixels & pix, int x, int y, int _width, int _height){

	if (pix.bAllocated == true){

		int width = pix.width;
		int height = pix.height;
		int bytesPerPixel = pix.bytesPerPixel;

		int newWidth = _width;
		int newHeight = _height;
		unsigned char * newPixels = new unsigned char [newWidth*newHeight*bytesPerPixel];
		memset(newPixels, 0, newWidth*newHeight*pix.bytesPerPixel);

		// this prevents having to do a check for bounds in the for loop;
		int minX = MAX(x, 0);
		int maxX = MIN(x+_width, width);
		int minY = MAX(y, 0);
		int maxY = MIN(y+_height, height);

		// TODO: point math can help speed this up:
		for (int i = minX; i < maxX; i++){
			for (int j = minY; j < maxY; j++){

				int newPixel = (j-y) * newWidth + (i-x);
				int oldPixel = (j) * width + (i);

				for (int k = 0; k < bytesPerPixel; k++){
					newPixels[newPixel*bytesPerPixel + k] = pix.pixels[oldPixel*bytesPerPixel + k];
				}
			}
		}

		delete [] pix.pixels;
		pix.pixels = newPixels;
		pix.width = newWidth;
		pix.height = newHeight;
	}
}

void ofPixelUtils::rotate90(ofPixels & pix, int nClockwiseRotations){

}

void ofPixelUtils::mirror(ofPixels & pix, bool vertically, bool horizontal){

}

//
////--------------------------------------------------------------
//void setFromSubImage(ofImage &src, ofImage &dst, ofRectangle subRect) {
//	int oldw = src.width;
//	int oldh = src.height;
//	int w = subRect.width;
//	int h = subRect.height;
//	int x = (int)subRect.x;
//	int y = (int)subRect.y;
//	if (w > oldw) return;
//	if (h > oldh) return;
//	int nPix = w * h * 3;
//	unsigned char * tempPixels = new unsigned char[ nPix ];
//	memset(tempPixels, 0, nPix);
//	//if (dst.width != subRect.width || dst.height != subRect.height){
//	//		dst.clear();	// clean up if necessary?
//	//		dst.allocate(subRect.width, subRect.height, OF_IMAGE_COLOR);
//	//	}
//	unsigned char * srcPixel = src.getPixels() + (y * oldw + x) * 3;
//	for (int i = 0; i < h; i++){
//		memcpy(tempPixels + i*w*3, srcPixel + i*oldw*3, w*3);
//		//memset(tempPixels + i*w*3, 0, w*3);
//	}
//
//	dst.setFromPixels(tempPixels, w, h, OF_IMAGE_COLOR);
//	dst.update();
//	delete tempPixels;
//}
<|endoftext|>


<commit_before>/*
 * ModSecurity, http://www.modsecurity.org/
 * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
 *
 * You may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * If any of the files related to licensing are missing or if you have any
 * other questions related to licensing please contact Trustwave Holdings, Inc.
 * directly using the email address security@modsecurity.org.
 *
 */

#include "parser/driver.h"

#include "parser/seclang-parser.hh"
#include "audit_log/audit_log.h"

using modsecurity::audit_log::AuditLog;
using modsecurity::Rule;

namespace modsecurity {
namespace Parser {

Driver::Driver()
  : trace_scanning(false),
  trace_parsing(false) {
      audit_log = new audit_log::AuditLog();
      audit_log->refCountIncrease();
  }

Driver::~Driver() {
    if (audit_log != NULL) {
        audit_log->refCountDecreaseAndCheck();
    }
    delete loc.back();
}

int Driver::addSecMarker(std::string marker) {
    for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) {
        Rule *rule = new Rule(marker);
        rule->phase = i;
        rules[i].push_back(rule);
    }
    return 0;
}

int Driver::addSecAction(Rule *rule) {
    if (rule->phase > ModSecurity::Phases::NUMBER_OF_PHASES) {
        parserError << "Unknown phase: " << std::to_string(rule->phase);
        parserError << std::endl;
        return false;
    }

    rules[rule->phase].push_back(rule);

    return true;
}

int Driver::addSecRule(Rule *rule) {
    if (rule->phase > ModSecurity::Phases::NUMBER_OF_PHASES) {
        parserError << "Unknown phase: " << std::to_string(rule->phase);
        parserError << std::endl;
        return false;
    }

    if (lastRule && lastRule->chained && lastRule->chainedRule == NULL) {
        rule->phase = lastRule->phase;
        lastRule->chainedRule = rule;
        return true;
    }

    if (lastRule && lastRule->chained && lastRule->chainedRule != NULL) {
        Rule *a = lastRule->chainedRule;
        while (a->chained && a->chainedRule != NULL) {
            a = a->chainedRule;
        }
        if (a->chained && a->chainedRule == NULL) {
            a->chainedRule = rule;
            return true;
        }
    }

    /*
     * Checking if the rule has an ID and also checking if this ID is not used
     * by other rule
     */
    if (rule->rule_id == 0) {
        parserError << "Rules must have an ID. File: ";
        parserError << rule->m_fileName << " at line: ";
        parserError << std::to_string(rule->m_lineNumber) << std::endl;
        return false;
    }
    for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) {
        std::vector<Rule *> rules = this->rules[i];
        for (int j = 0; j < rules.size(); j++) {
            if (rules[j]->rule_id == rule->rule_id) {
                parserError << "Rule id: " << std::to_string(rule->rule_id) \
                    << " is duplicated" << std::endl;
                return false;
            }
        }
    }

    lastRule = rule;
    rules[rule->phase].push_back(rule);
    return true;
}

int Driver::parse(const std::string &f, const std::string &ref) {
    lastRule = NULL;
    loc.push_back(new yy::location());
    if (ref.empty()) {
        this->ref.push_back("<<reference missing or not informed>>");
    } else {
        this->ref.push_back(ref);
    }

    buffer = f;
    scan_begin();
    yy::seclang_parser parser(*this);
    parser.set_debug_level(trace_parsing);
    int res = parser.parse();
    scan_end();

    if (audit_log->init() == false) {
        parserError << "Problems while initializing the audit logs" \
            << std::endl;
        return false;
    }

    return res == 0;
}

int Driver::parseFile(const std::string &f) {
    std::ifstream t(f);
    std::string str;

    if (t.is_open() == false) {
        parserError << "Failed to open the file: " << f << std::endl;
        return false;
    }

    t.seekg(0, std::ios::end);
    str.reserve(t.tellg());
    t.seekg(0, std::ios::beg);

    str.assign((std::istreambuf_iterator<char>(t)),
        std::istreambuf_iterator<char>());

    return parse(str, f);
}

void Driver::error(const yy::location& l, const std::string& m) {
    error(l, m, "");
}

void Driver::error(const yy::location& l, const std::string& m,
    const std::string& c) {
    if (parserError.tellp() == 0) {
        parserError << "Rules error. ";
        if (ref.empty() == false) {
            parserError << "File: " << ref.back() << ". ";
        }
        parserError << "Line: " << l.end.line << ". ";
        parserError << "Column: " << l.end.column << ". ";
    }

    if (m.empty() == false) {
        parserError << "" << m << " ";
    }

    if (c.empty() == false) {
        parserError << c;
    }
}

}  // namespace Parser
}  // namespace modsecurity
<commit_msg>parser: Reporting the right column position in case of error<commit_after>/*
 * ModSecurity, http://www.modsecurity.org/
 * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
 *
 * You may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * If any of the files related to licensing are missing or if you have any
 * other questions related to licensing please contact Trustwave Holdings, Inc.
 * directly using the email address security@modsecurity.org.
 *
 */

#include "parser/driver.h"

#include "parser/seclang-parser.hh"
#include "audit_log/audit_log.h"

using modsecurity::audit_log::AuditLog;
using modsecurity::Rule;

namespace modsecurity {
namespace Parser {

Driver::Driver()
  : trace_scanning(false),
  trace_parsing(false) {
      audit_log = new audit_log::AuditLog();
      audit_log->refCountIncrease();
  }

Driver::~Driver() {
    if (audit_log != NULL) {
        audit_log->refCountDecreaseAndCheck();
    }
    delete loc.back();
}

int Driver::addSecMarker(std::string marker) {
    for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) {
        Rule *rule = new Rule(marker);
        rule->phase = i;
        rules[i].push_back(rule);
    }
    return 0;
}

int Driver::addSecAction(Rule *rule) {
    if (rule->phase > ModSecurity::Phases::NUMBER_OF_PHASES) {
        parserError << "Unknown phase: " << std::to_string(rule->phase);
        parserError << std::endl;
        return false;
    }

    rules[rule->phase].push_back(rule);

    return true;
}

int Driver::addSecRule(Rule *rule) {
    if (rule->phase > ModSecurity::Phases::NUMBER_OF_PHASES) {
        parserError << "Unknown phase: " << std::to_string(rule->phase);
        parserError << std::endl;
        return false;
    }

    if (lastRule && lastRule->chained && lastRule->chainedRule == NULL) {
        rule->phase = lastRule->phase;
        lastRule->chainedRule = rule;
        return true;
    }

    if (lastRule && lastRule->chained && lastRule->chainedRule != NULL) {
        Rule *a = lastRule->chainedRule;
        while (a->chained && a->chainedRule != NULL) {
            a = a->chainedRule;
        }
        if (a->chained && a->chainedRule == NULL) {
            a->chainedRule = rule;
            return true;
        }
    }

    /*
     * Checking if the rule has an ID and also checking if this ID is not used
     * by other rule
     */
    if (rule->rule_id == 0) {
        parserError << "Rules must have an ID. File: ";
        parserError << rule->m_fileName << " at line: ";
        parserError << std::to_string(rule->m_lineNumber) << std::endl;
        return false;
    }
    for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) {
        std::vector<Rule *> rules = this->rules[i];
        for (int j = 0; j < rules.size(); j++) {
            if (rules[j]->rule_id == rule->rule_id) {
                parserError << "Rule id: " << std::to_string(rule->rule_id) \
                    << " is duplicated" << std::endl;
                return false;
            }
        }
    }

    lastRule = rule;
    rules[rule->phase].push_back(rule);
    return true;
}

int Driver::parse(const std::string &f, const std::string &ref) {
    lastRule = NULL;
    loc.push_back(new yy::location());
    if (ref.empty()) {
        this->ref.push_back("<<reference missing or not informed>>");
    } else {
        this->ref.push_back(ref);
    }

    buffer = f;
    scan_begin();
    yy::seclang_parser parser(*this);
    parser.set_debug_level(trace_parsing);
    int res = parser.parse();
    scan_end();

    if (audit_log->init() == false) {
        parserError << "Problems while initializing the audit logs" \
            << std::endl;
        return false;
    }

    return res == 0;
}

int Driver::parseFile(const std::string &f) {
    std::ifstream t(f);
    std::string str;

    if (t.is_open() == false) {
        parserError << "Failed to open the file: " << f << std::endl;
        return false;
    }

    t.seekg(0, std::ios::end);
    str.reserve(t.tellg());
    t.seekg(0, std::ios::beg);

    str.assign((std::istreambuf_iterator<char>(t)),
        std::istreambuf_iterator<char>());

    return parse(str, f);
}

void Driver::error(const yy::location& l, const std::string& m) {
    error(l, m, "");
}

void Driver::error(const yy::location& l, const std::string& m,
    const std::string& c) {
    if (parserError.tellp() == 0) {
        parserError << "Rules error. ";
        if (ref.empty() == false) {
            parserError << "File: " << ref.back() << ". ";
        }
        parserError << "Line: " << l.end.line << ". ";
        parserError << "Column: " << l.end.column - 1 << ". ";
    }

    if (m.empty() == false) {
        parserError << "" << m << " ";
    }

    if (c.empty() == false) {
        parserError << c;
    }
}

}  // namespace Parser
}  // namespace modsecurity
<|endoftext|>


<commit_before>/* -*- mode: c++; indent-tabs-mode: nil -*- */
/*
  OraColumnValue.h

  Qore Programming Language

  Copyright (C) 2003 - 2010 David Nichols

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "oracle.h"

static DateTimeNode *convert_date_time(unsigned char *str) {
   int year;
   if ((str[0] < 100) || (str[1] < 100))
      year = 9999;
   else
      year = (str[0] - 100) * 100 + (str[1] - 100);

   //printd(5, "convert_date_time(): %d %d = %04d-%02d-%02d %02d:%02d:%02d\n", str[0], str[1], year, str[2], str[3], str[4] - 1, str[5] - 1, str[6] - 1);
   return new DateTimeNode(year, str[2], str[3], str[4] - 1, str[5] - 1, str[6] - 1);
}

void OraColumnValue::del(ExceptionSink *xsink) {
   switch (dtype) {
      case 0:
      case SQLT_INT:
      case SQLT_UIN:
      case SQLT_FLT:
#ifdef SQLT_BFLOAT
      case SQLT_BFLOAT:
#endif
#ifdef SQLT_BDOUBLE
      case SQLT_BDOUBLE:
#endif
#ifdef SQLT_IBFLOAT
      case SQLT_IBFLOAT:
#endif
#ifdef SQLT_IBDOUBLE
      case SQLT_IBDOUBLE:
#endif
      case SQLT_DAT:
         break;

      case SQLT_CLOB:
      case SQLT_BLOB:
      case SQLT_RDD:
         if (buf.ptr)
            OCIDescriptorFree(buf.ptr, OCI_DTYPE_LOB);
         break;

      case SQLT_RSET:
         if (buf.ptr)
            OCIHandleFree(buf.ptr, OCI_HTYPE_STMT);
         break;

      case SQLT_TIMESTAMP:
      case SQLT_TIMESTAMP_TZ:
      case SQLT_TIMESTAMP_LTZ:
      case SQLT_DATE:
         if (buf.odt) {
            //printd(5, "OraColumnValue::del() this=%p freeing TIMESTAMP descriptor %p\n", this, buf.odt);
            OCIDescriptorFree(buf.odt, OCI_DTYPE_TIMESTAMP);
         }
         break;

      case SQLT_INTERVAL_YM:
         if (buf.oi)
            OCIDescriptorFree(buf.odt, OCI_DTYPE_INTERVAL_YM);
         break;

      case SQLT_INTERVAL_DS:
         if (buf.oi)
            OCIDescriptorFree(buf.odt, OCI_DTYPE_INTERVAL_DS);
         break;

      case SQLT_BIN:
      case SQLT_LBI:
      case SQLT_LVB: {
         QoreOracleConnection *conn = stmt.getData();
         //printd(5, "freeing binary pointer for SQLT_LVB %p\n", buf.ptr);
         conn->rawFree((OCIRaw**)&buf.ptr, xsink);
         break;
      }

      case SQLT_NTY:
         freeObject();
         break;

      case SQLT_NUM:
      default:
         if (buf.ptr)
            free(buf.ptr);
         break;
   }
}

#define ORA_ROWID_LEN 25

AbstractQoreNode *OraColumnValue::getValue(ExceptionSink *xsink, bool horizontal, bool destructive) {
   // SQL NULL returned
   if (ind == -1)
      return null();

   switch (dtype) {
      case SQLT_INT:
      case SQLT_UIN:
	 return new QoreBigIntNode(buf.i8);

      case SQLT_FLT:
#ifdef SQLT_BFLOAT
      case SQLT_BFLOAT:
#endif
#ifdef SQLT_BDOUBLE
      case SQLT_BDOUBLE:
#endif
#ifdef SQLT_IBFLOAT
      case SQLT_IBFLOAT:
#endif
#ifdef SQLT_IBDOUBLE
      case SQLT_IBDOUBLE:
#endif
	 return new QoreFloatNode(buf.f8);

      case SQLT_DAT:
	 return convert_date_time(buf.date);

      case SQLT_TIMESTAMP:
      case SQLT_DATE:
         return stmt.getData()->getTimestamp(false, buf.odt, xsink);

      case SQLT_TIMESTAMP_TZ:
      case SQLT_TIMESTAMP_LTZ:
         return stmt.getData()->getTimestamp(true, buf.odt, xsink);

      case SQLT_INTERVAL_YM:
         return stmt.getData()->getIntervalYearMonth(buf.oi, xsink);

      case SQLT_INTERVAL_DS:
         return stmt.getData()->getIntervalDaySecond(buf.oi, xsink);

      case SQLT_BIN:
      case SQLT_LBI:
      case SQLT_LVB:
         //printd(5, "OraColumnValue::getValue() this=%p SQLT_LVB ptr=%p\n", this, buf.ptr);
         return stmt.getData()->getBinary((OCIRaw*)buf.ptr);

      case SQLT_CLOB:
         return stmt.getData()->readClob((OCILobLocator*)buf.ptr, stmt.getEncoding(), xsink);

      case SQLT_BLOB:
         return stmt.getData()->readBlob((OCILobLocator*)buf.ptr, xsink);

      case SQLT_RSET: {
         QoreOracleStatement tstmt(stmt.getDatasource(), (OCIStmt*)buf.takePtr());
         if (horizontal)
            return tstmt.fetchRows(xsink);
         return tstmt.fetchColumns(xsink);
      }

      case SQLT_NTY: {
         // Real (atomic) null handling is quite tricky here.
         // pp_ind and pp_struct are unknown C structs taken from
         // the OCI NTY object where we know only the pp_ind's first
         // member "_atomic". It holds info about NULL value of the
         // whole object. The rest content of those structs is ignored.
         // (It took ages to get those info from the docs :/)
         OCIInd *pp_ind = 0; // obtain NULL info
         void *pp_struct = 0; // used only for call. No usage for its value
         QoreOracleConnection *conn = stmt.getData();

         if (subdtype == SQLT_NTY_OBJECT) {
            OCI_ObjectGetStruct2(&conn->ocilib, buf.oraObj, (void**)&pp_struct, (void**)&pp_ind);
            if (*pp_ind == OCI_IND_NULL || *pp_ind == OCI_IND_BADNULL)
               return null();
            return objToQore(conn, buf.oraObj, stmt.getDatasource(), xsink);
         }
         else {
            assert(subdtype == SQLT_NTY_COLLECTION);
            OCI_CollGetStruct(&conn->ocilib, buf.oraColl, (void**)&pp_struct, (void**)&pp_ind);
            if (*pp_ind == OCI_IND_NULL || *pp_ind == OCI_IND_BADNULL)
               return null();
            return collToQore(conn, buf.oraColl, stmt.getDatasource(), xsink);
         }
         break;
      } // SQLT_NTY

#ifdef SQLT_RDD
      case SQLT_RDD: {
         SimpleRefHolder<QoreStringNode> str(new QoreStringNode(stmt.getEncoding()));
         str->reserve(ORA_ROWID_LEN);

         QoreOracleConnection *conn = stmt.getData();

         ub2 len = ORA_ROWID_LEN;
         if (conn->checkerr(OCIRowidToChar((OCIRowid *)buf.ptr, (OraText *)str->getBuffer(), &len, conn->errhp), "OraColumnValue::getValue() ROWID", xsink))
            return 0;

         str->terminate(len);
         return str.release();
      }
#endif

      // treat as string
      default:
         //printd(5, "OraColumnValue::getValue() type=%d\n", dtype);
         // must be string data
         remove_trailing_blanks((char *)buf.ptr);
         if (!destructive)
            return new QoreStringNode((const char *)buf.ptr, stmt.getEncoding());
         int len = strlen((char *)buf.ptr);
         QoreStringNode *str = new QoreStringNode((char *)buf.ptr, len, len + 1, stmt.getEncoding());
         buf.ptr = 0;
         return str;
   }

   assert(false);
   return 0;
}

void OraColumnValue::freeObject() {
   assert(dtype == SQLT_NTY);
   assert(subdtype == SQLT_NTY_OBJECT || subdtype == SQLT_NTY_COLLECTION);

   QoreOracleConnection *conn = stmt.getData();

   // printd(0, "deleting object (OraColumn) buf.oraObj: %p, buf.oraColl: %p\n", buf.oraObj, buf.oraColl);
   // objects are allocated in bind-methods and it has to be freed in any case
   if (subdtype == SQLT_NTY_OBJECT)
      OCI_ObjectFree2(&conn->ocilib, buf.oraObj);
   else
      OCI_CollFree2(&conn->ocilib, buf.oraColl);
}
<commit_msg>fixed rowid descriptor release<commit_after>/* -*- mode: c++; indent-tabs-mode: nil -*- */
/*
  OraColumnValue.h

  Qore Programming Language

  Copyright (C) 2003 - 2010 David Nichols

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "oracle.h"

static DateTimeNode *convert_date_time(unsigned char *str) {
   int year;
   if ((str[0] < 100) || (str[1] < 100))
      year = 9999;
   else
      year = (str[0] - 100) * 100 + (str[1] - 100);

   //printd(5, "convert_date_time(): %d %d = %04d-%02d-%02d %02d:%02d:%02d\n", str[0], str[1], year, str[2], str[3], str[4] - 1, str[5] - 1, str[6] - 1);
   return new DateTimeNode(year, str[2], str[3], str[4] - 1, str[5] - 1, str[6] - 1);
}

void OraColumnValue::del(ExceptionSink *xsink) {
   switch (dtype) {
      case 0:
      case SQLT_INT:
      case SQLT_UIN:
      case SQLT_FLT:
#ifdef SQLT_BFLOAT
      case SQLT_BFLOAT:
#endif
#ifdef SQLT_BDOUBLE
      case SQLT_BDOUBLE:
#endif
#ifdef SQLT_IBFLOAT
      case SQLT_IBFLOAT:
#endif
#ifdef SQLT_IBDOUBLE
      case SQLT_IBDOUBLE:
#endif
      case SQLT_DAT:
         break;

      case SQLT_CLOB:
      case SQLT_BLOB:
         if (buf.ptr)
            OCIDescriptorFree(buf.ptr, OCI_DTYPE_LOB);
         break;

      case SQLT_RDD:
         if (buf.ptr)
            OCIDescriptorFree(buf.ptr, OCI_DTYPE_ROWID);
         break;

      case SQLT_RSET:
         if (buf.ptr)
            OCIHandleFree(buf.ptr, OCI_HTYPE_STMT);
         break;

      case SQLT_TIMESTAMP:
      case SQLT_TIMESTAMP_TZ:
      case SQLT_TIMESTAMP_LTZ:
      case SQLT_DATE:
         if (buf.odt) {
            //printd(5, "OraColumnValue::del() this=%p freeing TIMESTAMP descriptor %p\n", this, buf.odt);
            OCIDescriptorFree(buf.odt, OCI_DTYPE_TIMESTAMP);
         }
         break;

      case SQLT_INTERVAL_YM:
         if (buf.oi)
            OCIDescriptorFree(buf.odt, OCI_DTYPE_INTERVAL_YM);
         break;

      case SQLT_INTERVAL_DS:
         if (buf.oi)
            OCIDescriptorFree(buf.odt, OCI_DTYPE_INTERVAL_DS);
         break;

      case SQLT_BIN:
      case SQLT_LBI:
      case SQLT_LVB: {
         QoreOracleConnection *conn = stmt.getData();
         //printd(5, "freeing binary pointer for SQLT_LVB %p\n", buf.ptr);
         conn->rawFree((OCIRaw**)&buf.ptr, xsink);
         break;
      }

      case SQLT_NTY:
         freeObject();
         break;

      case SQLT_NUM:
      default:
         if (buf.ptr)
            free(buf.ptr);
         break;
   }
}

#define ORA_ROWID_LEN 25

AbstractQoreNode *OraColumnValue::getValue(ExceptionSink *xsink, bool horizontal, bool destructive) {
   // SQL NULL returned
   if (ind == -1)
      return null();

   switch (dtype) {
      case SQLT_INT:
      case SQLT_UIN:
	 return new QoreBigIntNode(buf.i8);

      case SQLT_FLT:
#ifdef SQLT_BFLOAT
      case SQLT_BFLOAT:
#endif
#ifdef SQLT_BDOUBLE
      case SQLT_BDOUBLE:
#endif
#ifdef SQLT_IBFLOAT
      case SQLT_IBFLOAT:
#endif
#ifdef SQLT_IBDOUBLE
      case SQLT_IBDOUBLE:
#endif
	 return new QoreFloatNode(buf.f8);

      case SQLT_DAT:
	 return convert_date_time(buf.date);

      case SQLT_TIMESTAMP:
      case SQLT_DATE:
         return stmt.getData()->getTimestamp(false, buf.odt, xsink);

      case SQLT_TIMESTAMP_TZ:
      case SQLT_TIMESTAMP_LTZ:
         return stmt.getData()->getTimestamp(true, buf.odt, xsink);

      case SQLT_INTERVAL_YM:
         return stmt.getData()->getIntervalYearMonth(buf.oi, xsink);

      case SQLT_INTERVAL_DS:
         return stmt.getData()->getIntervalDaySecond(buf.oi, xsink);

      case SQLT_BIN:
      case SQLT_LBI:
      case SQLT_LVB:
         //printd(5, "OraColumnValue::getValue() this=%p SQLT_LVB ptr=%p\n", this, buf.ptr);
         return stmt.getData()->getBinary((OCIRaw*)buf.ptr);

      case SQLT_CLOB:
         return stmt.getData()->readClob((OCILobLocator*)buf.ptr, stmt.getEncoding(), xsink);

      case SQLT_BLOB:
         return stmt.getData()->readBlob((OCILobLocator*)buf.ptr, xsink);

      case SQLT_RSET: {
         QoreOracleStatement tstmt(stmt.getDatasource(), (OCIStmt*)buf.takePtr());
         if (horizontal)
            return tstmt.fetchRows(xsink);
         return tstmt.fetchColumns(xsink);
      }

      case SQLT_NTY: {
         // Real (atomic) null handling is quite tricky here.
         // pp_ind and pp_struct are unknown C structs taken from
         // the OCI NTY object where we know only the pp_ind's first
         // member "_atomic". It holds info about NULL value of the
         // whole object. The rest content of those structs is ignored.
         // (It took ages to get those info from the docs :/)
         OCIInd *pp_ind = 0; // obtain NULL info
         void *pp_struct = 0; // used only for call. No usage for its value
         QoreOracleConnection *conn = stmt.getData();

         if (subdtype == SQLT_NTY_OBJECT) {
            OCI_ObjectGetStruct2(&conn->ocilib, buf.oraObj, (void**)&pp_struct, (void**)&pp_ind);
            if (*pp_ind == OCI_IND_NULL || *pp_ind == OCI_IND_BADNULL)
               return null();
            return objToQore(conn, buf.oraObj, stmt.getDatasource(), xsink);
         }
         else {
            assert(subdtype == SQLT_NTY_COLLECTION);
            OCI_CollGetStruct(&conn->ocilib, buf.oraColl, (void**)&pp_struct, (void**)&pp_ind);
            if (*pp_ind == OCI_IND_NULL || *pp_ind == OCI_IND_BADNULL)
               return null();
            return collToQore(conn, buf.oraColl, stmt.getDatasource(), xsink);
         }
         break;
      } // SQLT_NTY

#ifdef SQLT_RDD
      case SQLT_RDD: {
         SimpleRefHolder<QoreStringNode> str(new QoreStringNode(stmt.getEncoding()));
         str->reserve(ORA_ROWID_LEN);

         QoreOracleConnection *conn = stmt.getData();

         ub2 len = ORA_ROWID_LEN;
         if (conn->checkerr(OCIRowidToChar((OCIRowid *)buf.ptr, (OraText *)str->getBuffer(), &len, conn->errhp), "OraColumnValue::getValue() ROWID", xsink))
            return 0;

         str->terminate(len);
         return str.release();
      }
#endif

      // treat as string
      default:
         //printd(5, "OraColumnValue::getValue() type=%d\n", dtype);
         // must be string data
         remove_trailing_blanks((char *)buf.ptr);
         if (!destructive)
            return new QoreStringNode((const char *)buf.ptr, stmt.getEncoding());
         int len = strlen((char *)buf.ptr);
         QoreStringNode *str = new QoreStringNode((char *)buf.ptr, len, len + 1, stmt.getEncoding());
         buf.ptr = 0;
         return str;
   }

   assert(false);
   return 0;
}

void OraColumnValue::freeObject() {
   assert(dtype == SQLT_NTY);
   assert(subdtype == SQLT_NTY_OBJECT || subdtype == SQLT_NTY_COLLECTION);

   QoreOracleConnection *conn = stmt.getData();

   // printd(0, "deleting object (OraColumn) buf.oraObj: %p, buf.oraColl: %p\n", buf.oraObj, buf.oraColl);
   // objects are allocated in bind-methods and it has to be freed in any case
   if (subdtype == SQLT_NTY_OBJECT)
      OCI_ObjectFree2(&conn->ocilib, buf.oraObj);
   else
      OCI_CollFree2(&conn->ocilib, buf.oraColl);
}
<|endoftext|>