<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgText/FadeText>
#include <osg/Notify>
#include <osg/io_utils>
#include <OpenThreads/Mutex>
#include <OpenThreads/ScopedLock>

using namespace osgText;

struct FadeTextData : public osg::Referenced
{
    FadeTextData(FadeText* fadeText=0):
        _fadeText(fadeText),
        _visible(true) {}

    bool operator < (const FadeTextData& rhs) const
    {
        return _fadeText < rhs._fadeText;
    }

    float getNearestZ() const
    {
        float nearestZ = _vertices[0].z();
        if (nearestZ > _vertices[1].z()) nearestZ = _vertices[1].z();
        if (nearestZ > _vertices[2].z()) nearestZ = _vertices[2].z();
        if (nearestZ > _vertices[3].z()) nearestZ = _vertices[3].z();
        return nearestZ;
    }

    FadeText*   _fadeText;
    osg::Vec3   _vertices[4];
    bool        _visible;
};

struct FadeTextPolytopeData : public FadeTextData, public osg::Polytope
{
    FadeTextPolytopeData(FadeTextData& fadeTextData):
        FadeTextData(fadeTextData)
    {
        _referenceVertexList.push_back(_vertices[0]);
        _referenceVertexList.push_back(_vertices[1]);
        _referenceVertexList.push_back(_vertices[2]);
        _referenceVertexList.push_back(_vertices[3]);
    }

    void buildPolytope()
    {
        osg::Vec3 edge01 = _vertices[1] - _vertices[0];
        osg::Vec3 edge12 = _vertices[2] - _vertices[1];
        osg::Vec3 edge23 = _vertices[3] - _vertices[2];
        osg::Vec3 edge30 = _vertices[0] - _vertices[3];
        osg::Vec3 normalFrontFace = edge01 ^ edge12;
    }

};

struct FadeTextUserData : public osg::Referenced
{
    FadeTextUserData():
        _frameNumber(0) {}

    typedef std::list<FadeTextData> FadeTextList;
    unsigned int _frameNumber;
    FadeTextList _fadeTextInView;
};

struct GlobalFadeText : public osg::Referenced
{
    typedef std::set< osg::ref_ptr<FadeTextUserData> > UserDataSet;
    typedef std::set<FadeText*> FadeTextSet;
    typedef std::multimap<float, osg::ref_ptr<FadeTextPolytopeData> > FadeTextPolytopeMap;
    typedef std::map<osg::View*, UserDataSet> ViewUserDataMap;
    typedef std::map<osg::View*, FadeTextSet > ViewFadeTextMap;

    GlobalFadeText():
        _frameNumber(0xffffffff)
    {
    }

    FadeTextUserData* createNewFadeTextUserData(osg::View* view)
    {
        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);

        FadeTextUserData* userData = new FadeTextUserData;

        if (!userData)
        {
            osg::notify(osg::NOTICE)<<"Memory error, unable to create FadeTextUserData."<<std::endl;
            return 0;
        }

        _viewMap[view].insert(userData);

        return userData;
    }

    void update(unsigned int frameNumber)
    {
        _frameNumber = frameNumber;

        for(GlobalFadeText::ViewUserDataMap::iterator vitr = _viewMap.begin();
            vitr != _viewMap.end();
            ++vitr)
        {

            osg::View* view = vitr->first;

            FadeTextSet& fadeTextSet = _viewFadeTextMap[view];
            fadeTextSet.clear();

            FadeTextPolytopeMap fadeTextPolytopeMap;

            for(GlobalFadeText::UserDataSet::iterator uitr = vitr->second.begin();
                uitr != vitr->second.end();
                ++uitr)
            {
                FadeTextUserData* userData = uitr->get();

                int frameDelta = frameNumber - userData->_frameNumber;
                if (frameDelta<=1)
                {
                    for(FadeTextUserData::FadeTextList::iterator fitr = userData->_fadeTextInView.begin();
                        fitr != userData->_fadeTextInView.end();
                        ++fitr)
                    {
                        FadeTextData& fadeTextData = *fitr;
                        if (fadeTextSet.count(fadeTextData._fadeText)==0)
                        {
                            fadeTextSet.insert(fadeTextData._fadeText);
                            fadeTextPolytopeMap.insert(FadeTextPolytopeMap::value_type(
                                fadeTextData.getNearestZ(), new FadeTextPolytopeData(fadeTextData)));
                        }
                    }
                }
            }

            // for each FadeTexPoltopeData
            //    create polytopes
            //    test against all FTPD's later in the list
            //       test all control points on FTPD against each plane of the current polytope
            //       if all control points removed or outside then disgard FTPD and make FT visible = false;

        }
    }

    inline void updateIfRequired(unsigned int frameNumber)
    {
        if (_frameNumber!=frameNumber) update(frameNumber);
    }

    unsigned int _frameNumber;
    OpenThreads::Mutex _mutex;
    ViewUserDataMap _viewMap;
    ViewFadeTextMap _viewFadeTextMap;
};

GlobalFadeText* getGlobalFadeText()
{
    static osg::ref_ptr<GlobalFadeText> s_globalFadeText = new GlobalFadeText;
    return s_globalFadeText.get();
}

struct FadeTextUpdateCallback : public osg::Drawable::UpdateCallback
{
    FadeTextData _ftd;

    virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)
    {
        osgText::FadeText* fadeText = dynamic_cast<osgText::FadeText*>(drawable);
        if (!fadeText) return;

        unsigned int frameNumber = nv->getFrameStamp()->getFrameNumber();

        GlobalFadeText* gft = getGlobalFadeText();
        gft->updateIfRequired(frameNumber);

        osgText::FadeText::ViewBlendColourMap& vbcm = fadeText->getViewBlendColourMap();

        _ftd._fadeText = fadeText;

        float fadeSpeed = 0.01f;

        GlobalFadeText::ViewFadeTextMap& vftm = gft->_viewFadeTextMap;
        for(GlobalFadeText::ViewFadeTextMap::iterator itr = vftm.begin();
            itr != vftm.end();
            ++itr)
        {
            osg::View* view = itr->first;
            GlobalFadeText::FadeTextSet& fadeTextSet = itr->second;
            bool visible = fadeTextSet.count(fadeText)!=0;

            osg::Vec4& tec = vbcm[view];
            tec[0] = 1.0f;
            tec[1] = 1.0f;
            tec[2] = 1.0f;
            if (visible)
            {
                if (tec[3]<1.0f)
                {
                    tec[3] += fadeSpeed;
                    if (tec[3]>1.0f) tec[3] = 1.0f;
                }

            }
            else
            {
                if (tec[3]>0.0f)
                {
                    tec[3] -= fadeSpeed;
                    if (tec[3]<0.0f) tec[3] = 0.0f;
                }
            }
        }

    }
};

FadeText::FadeText()
{
    init();
}

FadeText::FadeText(const Text& text,const osg::CopyOp& copyop):
    Text(text,copyop)
{
    init();
}

void FadeText::init()
{
    setUpdateCallback(new FadeTextUpdateCallback());
}

void FadeText::drawImplementation(osg::RenderInfo& renderInfo) const
{

    osg::State& state = *renderInfo.getState();

    ViewBlendColourMap::iterator itr = _viewBlendColourMap.find(renderInfo.getView());
    if (itr != _viewBlendColourMap.end())
    {
        Text::drawImplementation(*renderInfo.getState(), itr->second );
    }
    else
    {
        Text::drawImplementation(*renderInfo.getState(), osg::Vec4(1.0f,1.0f,1.0f,1.0f) );
    }

    // now pass on new details

    FadeTextUserData* userData = dynamic_cast<FadeTextUserData*>(renderInfo.getUserData());
    if (!userData)
    {
        if (renderInfo.getUserData())
        {
            osg::notify(osg::NOTICE)<<"Warning user data not of supported type."<<std::endl;
            return;
        }

        userData = getGlobalFadeText()->createNewFadeTextUserData(renderInfo.getView());

        if (!userData)
        {
            osg::notify(osg::NOTICE)<<"Memory error, unable to create FadeTextUserData."<<std::endl;
            return;
        }

        renderInfo.setUserData(userData);
    }

    unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber();
    if (frameNumber != userData->_frameNumber)
    {
        // new frame so must reset UserData structure.
        userData->_frameNumber = frameNumber;
        userData->_fadeTextInView.clear();
    }

    osgText::Text::AutoTransformCache& atc = _autoTransformCache[renderInfo.getContextID()];

    osg::Matrix lmv = atc._matrix;
    lmv.postMult(state.getModelViewMatrix());

    if (renderInfo.getView())
    {
        // move from camera into the view space.
        lmv.postMult(state.getInitialInverseViewMatrix());
        lmv.postMult(renderInfo.getView()->getViewMatrix());
        lmv.postMult(renderInfo.getView()->getProjectionMatrix());
    }

    FadeTextData ftd(const_cast<osgText::FadeText*>(this));
    ftd._vertices[0].set(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*lmv);
    ftd._vertices[1].set(osg::Vec3(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())*lmv);
    ftd._vertices[2].set(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMin())*lmv);
    ftd._vertices[3].set(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*lmv);

    userData->_fadeTextInView.push_back(ftd);

}
<commit_msg>Further work on fade text.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgText/FadeText>
#include <osg/Notify>
#include <osg/io_utils>
#include <OpenThreads/Mutex>
#include <OpenThreads/ScopedLock>

using namespace osgText;

struct FadeTextData : public osg::Referenced
{
    FadeTextData(FadeText* fadeText=0):
        _fadeText(fadeText),
        _visible(true) {}

    bool operator < (const FadeTextData& rhs) const
    {
        return _fadeText < rhs._fadeText;
    }

    float getNearestZ() const
    {
        float nearestZ = _vertices[0].z();
        if (nearestZ < _vertices[1].z()) nearestZ = _vertices[1].z();
        if (nearestZ < _vertices[2].z()) nearestZ = _vertices[2].z();
        if (nearestZ < _vertices[3].z()) nearestZ = _vertices[3].z();
        return nearestZ;
    }

    FadeText*   _fadeText;
    osg::Vec3   _vertices[4];
    bool        _visible;
};

struct FadeTextPolytopeData : public FadeTextData, public osg::Polytope
{
    FadeTextPolytopeData(FadeTextData& fadeTextData):
        FadeTextData(fadeTextData)
    {
        _referenceVertexList.push_back(_vertices[0]);
        _referenceVertexList.push_back(_vertices[1]);
        _referenceVertexList.push_back(_vertices[2]);
        _referenceVertexList.push_back(_vertices[3]);
    }

    void addEdgePlane(const osg::Vec3& corner, const osg::Vec3& edge)
    {
        osg::Vec3 normal( edge.y(), -edge.x(), 0.0f);
        normal.normalize();

        add(osg::Plane(normal, corner));
    }

    void buildPolytope()
    {
        osg::Vec3 edge01 = _vertices[1] - _vertices[0];
        osg::Vec3 edge12 = _vertices[2] - _vertices[1];
        osg::Vec3 edge23 = _vertices[3] - _vertices[2];
        osg::Vec3 edge30 = _vertices[0] - _vertices[3];

        osg::Vec3 normalFrontFace = edge01 ^ edge12;
        bool needToFlip = normalFrontFace.z()>0.0f;

        normalFrontFace.normalize();
        add(osg::Plane(normalFrontFace, _vertices[0]));

        addEdgePlane(_vertices[0], edge01);
        addEdgePlane(_vertices[1], edge12);
        addEdgePlane(_vertices[2], edge23);
        addEdgePlane(_vertices[3], edge30);

        osg::notify(osg::NOTICE)<<" normalFrontFace = "<<normalFrontFace<<std::endl;
        osg::notify(osg::NOTICE)<<" edge01 = "<<edge01<<std::endl;
        osg::notify(osg::NOTICE)<<" edge12 = "<<edge12<<std::endl;
        osg::notify(osg::NOTICE)<<" edge23 = "<<edge23<<std::endl;
        osg::notify(osg::NOTICE)<<" _vertices[0]= "<<_vertices[0]<<std::endl;
        osg::notify(osg::NOTICE)<<" _vertices[1]= "<<_vertices[1]<<std::endl;
        osg::notify(osg::NOTICE)<<" _vertices[2]= "<<_vertices[2]<<std::endl;
        osg::notify(osg::NOTICE)<<" _vertices[3]= "<<_vertices[3]<<std::endl;

        if (needToFlip) flip();

        osg::notify(osg::NOTICE)<<"   plane 0 "<< _planeList[0]<<std::endl;
        osg::notify(osg::NOTICE)<<"   plane 1 "<< _planeList[1]<<std::endl;
        osg::notify(osg::NOTICE)<<"   plane 2 "<< _planeList[2]<<std::endl;
        osg::notify(osg::NOTICE)<<"   plane 3 "<< _planeList[3]<<std::endl;
        osg::notify(osg::NOTICE)<<"   plane 4 "<< _planeList[4]<<std::endl;

    }

    inline bool contains(const std::vector<osg::Vec3>& vertices)
    {
        for(std::vector<osg::Vec3>::const_iterator itr = vertices.begin();
            itr != vertices.end();
            ++itr)
        {
           osg::notify(osg::NOTICE)<<"testing "<<*itr<<std::endl;
        }

        for(std::vector<osg::Vec3>::const_iterator itr = vertices.begin();
            itr != vertices.end();
            ++itr)
        {
            if (osg::Polytope::contains(*itr))
            {
                osg::notify(osg::NOTICE)<<"Does contain "<<*itr<<std::endl;
                return true;
            }
            else
            {
                osg::notify(osg::NOTICE)<<"Doesn't contain "<<*itr<<std::endl;
            }
        }
        return false;
    }

};

struct FadeTextUserData : public osg::Referenced
{
    FadeTextUserData():
        _frameNumber(0) {}

    typedef std::list<FadeTextData> FadeTextList;
    unsigned int _frameNumber;
    FadeTextList _fadeTextInView;
};

struct GlobalFadeText : public osg::Referenced
{
    typedef std::set< osg::ref_ptr<FadeTextUserData> > UserDataSet;
    typedef std::set<FadeText*> FadeTextSet;
    typedef std::multimap<float, osg::ref_ptr<FadeTextPolytopeData> > FadeTextPolytopeMap;
    typedef std::map<osg::View*, UserDataSet> ViewUserDataMap;
    typedef std::map<osg::View*, FadeTextSet > ViewFadeTextMap;

    GlobalFadeText():
        _frameNumber(0xffffffff)
    {
    }

    FadeTextUserData* createNewFadeTextUserData(osg::View* view)
    {
        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);

        FadeTextUserData* userData = new FadeTextUserData;

        if (!userData)
        {
            osg::notify(osg::NOTICE)<<"Memory error, unable to create FadeTextUserData."<<std::endl;
            return 0;
        }

        _viewMap[view].insert(userData);

        return userData;
    }

    void update(unsigned int frameNumber)
    {
        osg::notify(osg::NOTICE)<<std::endl<<"update**********************"<<std::endl;

        _frameNumber = frameNumber;

        for(GlobalFadeText::ViewUserDataMap::iterator vitr = _viewMap.begin();
            vitr != _viewMap.end();
            ++vitr)
        {

            osg::View* view = vitr->first;

            FadeTextSet& fadeTextSet = _viewFadeTextMap[view];
            fadeTextSet.clear();

            FadeTextPolytopeMap fadeTextPolytopeMap;

            for(GlobalFadeText::UserDataSet::iterator uitr = vitr->second.begin();
                uitr != vitr->second.end();
                ++uitr)
            {
                FadeTextUserData* userData = uitr->get();

                int frameDelta = frameNumber - userData->_frameNumber;
                if (frameDelta<=1)
                {
                    for(FadeTextUserData::FadeTextList::iterator fitr = userData->_fadeTextInView.begin();
                        fitr != userData->_fadeTextInView.end();
                        ++fitr)
                    {
                        FadeTextData& fadeTextData = *fitr;
                        if (fadeTextSet.count(fadeTextData._fadeText)==0)
                        {
                            fadeTextSet.insert(fadeTextData._fadeText);
                            fadeTextPolytopeMap.insert(FadeTextPolytopeMap::value_type(
                                -fadeTextData.getNearestZ(), new FadeTextPolytopeData(fadeTextData)));
                        }
                    }
                }
            }

            // for each FadeTexPoltopeData
            //    create polytopes
            //    test against all FTPD's later in the list
            //       test all control points on FTPD against each plane of the current polytope
            //       if all control points removed or outside then discard FTPD and make FT visible = false;

            FadeTextPolytopeMap::iterator outer_itr = fadeTextPolytopeMap.begin();
            while (outer_itr != fadeTextPolytopeMap.end())
            {
                FadeTextPolytopeMap::iterator inner_itr = outer_itr;
                ++inner_itr;

                if (inner_itr == fadeTextPolytopeMap.end()) break;

                FadeTextPolytopeData& outer_ftpm = *(outer_itr->second);
                outer_ftpm.buildPolytope();

                osg::notify(osg::NOTICE)<<"Outer z "<<outer_ftpm.getNearestZ()<<std::endl;

                while(inner_itr != fadeTextPolytopeMap.end())
                {
                    FadeTextPolytopeData& inner_ftpm = *(inner_itr->second);

                    osg::notify(osg::NOTICE)<<"Inner z "<<inner_ftpm.getNearestZ()<<std::endl;

                    if (outer_ftpm.contains(inner_ftpm.getReferenceVertexList()))
                    {
                        FadeTextPolytopeMap::iterator erase_itr = inner_itr;
                        // move to next ftpm
                        ++inner_itr;

                        fadeTextSet.erase(inner_ftpm._fadeText);

                        // need to remove inner_ftpm as its occluded.
                        fadeTextPolytopeMap.erase(erase_itr);

                    }
                    else
                    {
                        // move to next ftpm
                        ++inner_itr;
                    }
                }

                ++outer_itr;

            }

            osg::notify(osg::NOTICE)<<"fadeTextPolytopeMap.size() = "<<fadeTextPolytopeMap.size()<<std::endl;

        }
    }

    inline void updateIfRequired(unsigned int frameNumber)
    {
        if (_frameNumber!=frameNumber) update(frameNumber);
    }

    unsigned int _frameNumber;
    OpenThreads::Mutex _mutex;
    ViewUserDataMap _viewMap;
    ViewFadeTextMap _viewFadeTextMap;
};

GlobalFadeText* getGlobalFadeText()
{
    static osg::ref_ptr<GlobalFadeText> s_globalFadeText = new GlobalFadeText;
    return s_globalFadeText.get();
}

struct FadeTextUpdateCallback : public osg::Drawable::UpdateCallback
{
    FadeTextData _ftd;

    virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)
    {
        osgText::FadeText* fadeText = dynamic_cast<osgText::FadeText*>(drawable);
        if (!fadeText) return;

        unsigned int frameNumber = nv->getFrameStamp()->getFrameNumber();

        GlobalFadeText* gft = getGlobalFadeText();
        gft->updateIfRequired(frameNumber);

        osgText::FadeText::ViewBlendColourMap& vbcm = fadeText->getViewBlendColourMap();

        _ftd._fadeText = fadeText;

        float fadeSpeed = 0.01f;

        GlobalFadeText::ViewFadeTextMap& vftm = gft->_viewFadeTextMap;
        for(GlobalFadeText::ViewFadeTextMap::iterator itr = vftm.begin();
            itr != vftm.end();
            ++itr)
        {
            osg::View* view = itr->first;
            GlobalFadeText::FadeTextSet& fadeTextSet = itr->second;
            bool visible = fadeTextSet.count(fadeText)!=0;

            osg::Vec4& tec = vbcm[view];
            tec[0] = 1.0f;
            tec[1] = 1.0f;
            tec[2] = 1.0f;
            if (visible)
            {
                if (tec[3]<1.0f)
                {
                    tec[3] += fadeSpeed;
                    if (tec[3]>1.0f) tec[3] = 1.0f;
                }

            }
            else
            {
                if (tec[3]>0.0f)
                {
                    tec[3] -= fadeSpeed;
                    if (tec[3]<0.0f) tec[3] = 0.0f;
                }
            }
        }

    }
};

FadeText::FadeText()
{
    init();
}

FadeText::FadeText(const Text& text,const osg::CopyOp& copyop):
    Text(text,copyop)
{
    init();
}

void FadeText::init()
{
    setUpdateCallback(new FadeTextUpdateCallback());
}

void FadeText::drawImplementation(osg::RenderInfo& renderInfo) const
{

    osg::State& state = *renderInfo.getState();

    ViewBlendColourMap::iterator itr = _viewBlendColourMap.find(renderInfo.getView());
    if (itr != _viewBlendColourMap.end())
    {
        Text::drawImplementation(*renderInfo.getState(), itr->second );
    }
    else
    {
        Text::drawImplementation(*renderInfo.getState(), osg::Vec4(1.0f,1.0f,1.0f,1.0f) );
    }

    // now pass on new details

    FadeTextUserData* userData = dynamic_cast<FadeTextUserData*>(renderInfo.getUserData());
    if (!userData)
    {
        if (renderInfo.getUserData())
        {
            osg::notify(osg::NOTICE)<<"Warning user data not of supported type."<<std::endl;
            return;
        }

        userData = getGlobalFadeText()->createNewFadeTextUserData(renderInfo.getView());

        if (!userData)
        {
            osg::notify(osg::NOTICE)<<"Memory error, unable to create FadeTextUserData."<<std::endl;
            return;
        }

        renderInfo.setUserData(userData);
    }

    unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber();
    if (frameNumber != userData->_frameNumber)
    {
        // new frame so must reset UserData structure.
        userData->_frameNumber = frameNumber;
        userData->_fadeTextInView.clear();
    }

    osgText::Text::AutoTransformCache& atc = _autoTransformCache[renderInfo.getContextID()];

    osg::Matrix lmv = atc._matrix;
    lmv.postMult(state.getModelViewMatrix());

    if (renderInfo.getView())
    {
        // move from camera into the view space.
        lmv.postMult(state.getInitialInverseViewMatrix());
        lmv.postMult(renderInfo.getView()->getViewMatrix());
        lmv.postMult(renderInfo.getView()->getProjectionMatrix());

        osg::notify(osg::NOTICE)<<"renderInfo.getView()->getProjectionMatrix())="<<renderInfo.getView()->getProjectionMatrix()<<std::endl;
        osg::notify(osg::NOTICE)<<"lmv="<<lmv<<std::endl;
    }

    FadeTextData ftd(const_cast<osgText::FadeText*>(this));

    osg::notify(osg::NOTICE)<<"osg::Vec3d(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*lmv="<<osg::Vec3d(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*lmv<<std::endl;
    osg::notify(osg::NOTICE)<<"osg::Vec4d(_textBB.xMin(),_textBB.yMin(),_textBB.zMin(),1.0)*lmv="<<osg::Vec4d(_textBB.xMin(),_textBB.yMin(),_textBB.zMin(),1.0)*lmv<<std::endl;

    ftd._vertices[0].set(osg::Vec3d(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*lmv);
    ftd._vertices[1].set(osg::Vec3d(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())*lmv);
    ftd._vertices[2].set(osg::Vec3d(_textBB.xMax(),_textBB.yMax(),_textBB.zMin())*lmv);
    ftd._vertices[3].set(osg::Vec3d(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*lmv);

    userData->_fadeTextInView.push_back(ftd);

}
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com>

*/

// Copyright 2016 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// 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
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include <osvr/Util/Logger.h>

// Library/third-party includes
#include <spdlog/spdlog.h>

// Standard includes
#include <memory>           // for std::shared_ptr
#include <utility>          // for std::forward
#include <string>           // for std::string

namespace osvr {
namespace util {
namespace log {

Logger::Logger(const std::string& logger_name)
{
    logger_ = spdlog::get(logger_name);
}

Logger::Logger(spdlog::logger* logger) : logger_(logger)
{
    // do nothing
}

Logger::Logger(std::shared_ptr<spdlog::logger> logger) : logger_(logger)
{
    // do nothing
}

Logger::~Logger()
{
    // FIXME
}

/*
Logger::Logger(spdlog::logger* logger) : logger_(logger)
{
    // do nothing
}
*/

LogLevel Logger::getLogLevel() const
{
    return static_cast<LogLevel>(logger_->level());
}

void Logger::setLogLevel(LogLevel level)
{
    logger_->set_level(static_cast<spdlog::level::level_enum>(level));
}

void flush_on(LogLevel level)
{
    logger_->flush_on(static_cast<spdlog::level::level_enum>(level));
}

detail::LineLogger Logger::trace(const char* fmt)
{
    return logger_->trace(fmt);
}

detail::LineLogger Logger::debug(const char* fmt)
{
    return logger_->debug(fmt);
}

detail::LineLogger Logger::info(const char* fmt)
{
    return logger_->info(fmt);
}

detail::LineLogger Logger::notice(const char* fmt)
{
    return logger_->notice(fmt);
}

detail::LineLogger Logger::warn(const char* fmt)
{
    return logger_->warn(fmt);
}

detail::LineLogger Logger::error(const char* fmt)
{
    return logger_->error(fmt);
}

detail::LineLogger Logger::critical(const char* fmt)
{
    return logger_->critical(fmt);
}

detail::LineLogger Logger::alert(const char* fmt)
{
    return logger_->alert(fmt);
}

detail::LineLogger Logger::emerg(const char* fmt)
{
    return logger_->emerg(fmt);
}

// logger.info() << ".." call  style
detail::LineLogger Logger::trace()
{
    return logger_->trace();
}

detail::LineLogger Logger::debug()
{
    return logger_->debug();
}

detail::LineLogger Logger::info()
{
    return logger_->info();
}

detail::LineLogger Logger::notice()
{
    return logger_->notice();
}

detail::LineLogger Logger::warn()
{
    return logger_->warn();
}

detail::LineLogger Logger::error()
{
    return logger_->error();
}

detail::LineLogger Logger::critical()
{
    return logger_->critical();
}

detail::LineLogger Logger::alert()
{
    return logger_->alert();
}

detail::LineLogger Logger::emerg()
{
    return logger_->emerg();
}

// logger.log(log_level, msg) << ".." call style
detail::LineLogger Logger::log(LogLevel level, const char* msg)
{
    switch (level) {
    case LogLevel::trace:
        return trace(msg);
    case LogLevel::debug:
        return debug(msg);
    case LogLevel::info:
        return info(msg);
    case LogLevel::notice:
        return notice(msg);
    case LogLevel::warn:
        return warn(msg);
    case LogLevel::err:
        return error(msg);
    case LogLevel::critical:
        return critical(msg);
    case LogLevel::alert:
        return alert(msg);
    case LogLevel::emerg:
        return emerg(msg);
    }

    return info(msg);
}

// logger.log(log_level) << ".." call  style
detail::LineLogger Logger::log(LogLevel level)
{
    switch (level) {
    case LogLevel::trace:
        return trace();
    case LogLevel::debug:
        return debug();
    case LogLevel::info:
        return info();
    case LogLevel::notice:
        return notice();
    case LogLevel::warn:
        return warn();
    case LogLevel::err:
        return error();
    case LogLevel::critical:
        return critical();
    case LogLevel::alert:
        return alert();
    case LogLevel::emerg:
        return emerg();
    }

    return info();
}

void Logger::flush()
{
    logger_->flush();
}

} // end namespace log
} // end namespace util
} // end namespace osvr

<commit_msg>Fixed typo.<commit_after>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com>

*/

// Copyright 2016 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// 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
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include <osvr/Util/Logger.h>

// Library/third-party includes
#include <spdlog/spdlog.h>

// Standard includes
#include <memory>           // for std::shared_ptr
#include <utility>          // for std::forward
#include <string>           // for std::string

namespace osvr {
namespace util {
namespace log {

Logger::Logger(const std::string& logger_name)
{
    logger_ = spdlog::get(logger_name);
}

Logger::Logger(spdlog::logger* logger) : logger_(logger)
{
    // do nothing
}

Logger::Logger(std::shared_ptr<spdlog::logger> logger) : logger_(logger)
{
    // do nothing
}

Logger::~Logger()
{
    // FIXME
}

/*
Logger::Logger(spdlog::logger* logger) : logger_(logger)
{
    // do nothing
}
*/

LogLevel Logger::getLogLevel() const
{
    return static_cast<LogLevel>(logger_->level());
}

void Logger::setLogLevel(LogLevel level)
{
    logger_->set_level(static_cast<spdlog::level::level_enum>(level));
}

void Logger::flush_on(LogLevel level)
{
    logger_->flush_on(static_cast<spdlog::level::level_enum>(level));
}

detail::LineLogger Logger::trace(const char* fmt)
{
    return logger_->trace(fmt);
}

detail::LineLogger Logger::debug(const char* fmt)
{
    return logger_->debug(fmt);
}

detail::LineLogger Logger::info(const char* fmt)
{
    return logger_->info(fmt);
}

detail::LineLogger Logger::notice(const char* fmt)
{
    return logger_->notice(fmt);
}

detail::LineLogger Logger::warn(const char* fmt)
{
    return logger_->warn(fmt);
}

detail::LineLogger Logger::error(const char* fmt)
{
    return logger_->error(fmt);
}

detail::LineLogger Logger::critical(const char* fmt)
{
    return logger_->critical(fmt);
}

detail::LineLogger Logger::alert(const char* fmt)
{
    return logger_->alert(fmt);
}

detail::LineLogger Logger::emerg(const char* fmt)
{
    return logger_->emerg(fmt);
}

// logger.info() << ".." call  style
detail::LineLogger Logger::trace()
{
    return logger_->trace();
}

detail::LineLogger Logger::debug()
{
    return logger_->debug();
}

detail::LineLogger Logger::info()
{
    return logger_->info();
}

detail::LineLogger Logger::notice()
{
    return logger_->notice();
}

detail::LineLogger Logger::warn()
{
    return logger_->warn();
}

detail::LineLogger Logger::error()
{
    return logger_->error();
}

detail::LineLogger Logger::critical()
{
    return logger_->critical();
}

detail::LineLogger Logger::alert()
{
    return logger_->alert();
}

detail::LineLogger Logger::emerg()
{
    return logger_->emerg();
}

// logger.log(log_level, msg) << ".." call style
detail::LineLogger Logger::log(LogLevel level, const char* msg)
{
    switch (level) {
    case LogLevel::trace:
        return trace(msg);
    case LogLevel::debug:
        return debug(msg);
    case LogLevel::info:
        return info(msg);
    case LogLevel::notice:
        return notice(msg);
    case LogLevel::warn:
        return warn(msg);
    case LogLevel::err:
        return error(msg);
    case LogLevel::critical:
        return critical(msg);
    case LogLevel::alert:
        return alert(msg);
    case LogLevel::emerg:
        return emerg(msg);
    }

    return info(msg);
}

// logger.log(log_level) << ".." call  style
detail::LineLogger Logger::log(LogLevel level)
{
    switch (level) {
    case LogLevel::trace:
        return trace();
    case LogLevel::debug:
        return debug();
    case LogLevel::info:
        return info();
    case LogLevel::notice:
        return notice();
    case LogLevel::warn:
        return warn();
    case LogLevel::err:
        return error();
    case LogLevel::critical:
        return critical();
    case LogLevel::alert:
        return alert();
    case LogLevel::emerg:
        return emerg();
    }

    return info();
}

void Logger::flush()
{
    logger_->flush();
}

} // end namespace log
} // end namespace util
} // end namespace osvr

<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "ImageNode.h"

#include "SDLDisplayEngine.h"
#include "Player.h"
#include "NodeDefinition.h"

#include "../base/Logger.h"
#include "../base/ScopeTimer.h"
#include "../base/XMLHelper.h"
#include "../base/Exception.h"
#include "../base/ObjectCounter.h"

#include "../graphics/Filterfliprgb.h"

#include <iostream>
#include <sstream>

using namespace std;

namespace avg {

NodeDefinition ImageNode::createDefinition()
{
    return NodeDefinition("image", Node::buildNode<ImageNode>)
        .extendDefinition(RasterNode::createDefinition())
        .addArg(Arg<UTF8String>("href", "", false, offsetof(ImageNode, m_href)));
}

ImageNode::ImageNode(const ArgList& Args)
{
    m_pImage = ImagePtr(new Image(getSurface(), "", true));
    Args.setMembers(this);
    setHRef(m_href);
    ObjectCounter::get()->incRef(&typeid(*this));
}

ImageNode::~ImageNode()
{
    ObjectCounter::get()->decRef(&typeid(*this));
}

void ImageNode::setRenderingEngines(DisplayEngine * pDisplayEngine,
        AudioEngine * pAudioEngine)
{
    RasterNode::setRenderingEngines(pDisplayEngine, pAudioEngine);
    m_pImage->moveToGPU(dynamic_cast<SDLDisplayEngine*>(pDisplayEngine));
}

void ImageNode::connect()
{
    RasterNode::connect();
    checkReload();
}

void ImageNode::disconnect(bool bKill)
{
    if (bKill) {
        m_pImage = ImagePtr(new Image(getSurface(), "", true));
    } else {
        m_pImage->moveToCPU();
    }
    RasterNode::disconnect(bKill);
}

const UTF8String& ImageNode::getHRef() const
{
    return m_href;
}

void ImageNode::setHRef(const UTF8String& href)
{
    m_href = href;
    checkReload();
}

void ImageNode::setBitmap(const Bitmap * pBmp)
{
    m_pImage->setBitmap(pBmp);
    m_href = "";
    IntPoint Size = getMediaSize();
    setViewport(-32767, -32767, -32767, -32767);
}

static ProfilingZone RenderProfilingZone("ImageNode::render");

void ImageNode::render(const DRect& Rect)
{
    ScopeTimer Timer(RenderProfilingZone);
    if (m_pImage->getState() == Image::GPU) {
        m_pImage->getTiledSurface()->blt32(getSize(), getEffectiveOpacity(),
                getBlendMode());
    }
}

IntPoint ImageNode::getMediaSize()
{
    return m_pImage->getSize();
}

void ImageNode::checkReload()
{
    Node::checkReload(m_href, m_pImage);
    IntPoint Size = getMediaSize();
    setViewport(-32767, -32767, -32767, -32767);
    RasterNode::checkReload();
}

Bitmap * ImageNode::getBitmap()
{
    return m_pImage->getBitmap();
}

}
<commit_msg>Make sure Node is in a sane state after unlink(True).<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "ImageNode.h"

#include "SDLDisplayEngine.h"
#include "Player.h"
#include "NodeDefinition.h"

#include "../base/Logger.h"
#include "../base/ScopeTimer.h"
#include "../base/XMLHelper.h"
#include "../base/Exception.h"
#include "../base/ObjectCounter.h"

#include "../graphics/Filterfliprgb.h"

#include <iostream>
#include <sstream>

using namespace std;

namespace avg {

NodeDefinition ImageNode::createDefinition()
{
    return NodeDefinition("image", Node::buildNode<ImageNode>)
        .extendDefinition(RasterNode::createDefinition())
        .addArg(Arg<UTF8String>("href", "", false, offsetof(ImageNode, m_href)));
}

ImageNode::ImageNode(const ArgList& Args)
{
    m_pImage = ImagePtr(new Image(getSurface(), "", true));
    Args.setMembers(this);
    setHRef(m_href);
    ObjectCounter::get()->incRef(&typeid(*this));
}

ImageNode::~ImageNode()
{
    ObjectCounter::get()->decRef(&typeid(*this));
}

void ImageNode::setRenderingEngines(DisplayEngine * pDisplayEngine,
        AudioEngine * pAudioEngine)
{
    RasterNode::setRenderingEngines(pDisplayEngine, pAudioEngine);
    m_pImage->moveToGPU(dynamic_cast<SDLDisplayEngine*>(pDisplayEngine));
}

void ImageNode::connect()
{
    RasterNode::connect();
    checkReload();
}

void ImageNode::disconnect(bool bKill)
{
    if (bKill) {
        m_pImage = ImagePtr(new Image(getSurface(), "", true));
        m_href = "";
    } else {
        m_pImage->moveToCPU();
    }
    RasterNode::disconnect(bKill);
}

const UTF8String& ImageNode::getHRef() const
{
    return m_href;
}

void ImageNode::setHRef(const UTF8String& href)
{
    m_href = href;
    checkReload();
}

void ImageNode::setBitmap(const Bitmap * pBmp)
{
    m_pImage->setBitmap(pBmp);
    m_href = "";
    IntPoint Size = getMediaSize();
    setViewport(-32767, -32767, -32767, -32767);
}

static ProfilingZone RenderProfilingZone("ImageNode::render");

void ImageNode::render(const DRect& Rect)
{
    ScopeTimer Timer(RenderProfilingZone);
    if (m_pImage->getState() == Image::GPU) {
        m_pImage->getTiledSurface()->blt32(getSize(), getEffectiveOpacity(),
                getBlendMode());
    }
}

IntPoint ImageNode::getMediaSize()
{
    return m_pImage->getSize();
}

void ImageNode::checkReload()
{
    Node::checkReload(m_href, m_pImage);
    IntPoint Size = getMediaSize();
    setViewport(-32767, -32767, -32767, -32767);
    RasterNode::checkReload();
}

Bitmap * ImageNode::getBitmap()
{
    return m_pImage->getBitmap();
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// logging.cc: Breakpad logging
//
// See logging.h for documentation.
//
// Author: Mark Mentovai

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

#include "processor/logging.h"
#include "processor/pathname_stripper.h"

namespace google_breakpad {

#ifdef _WIN32
#define snprintf _snprintf
#endif

LogStream::LogStream(std::ostream &stream, Severity severity,
                     const char *file, int line)
    : stream_(stream) {
  time_t clock;
  time(&clock);
  struct tm tm_struct;
#ifdef _WIN32
  localtime_s(&tm_struct, &clock);
#else
  localtime_r(&clock, &tm_struct);
#endif
  char time_string[20];
  strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", &tm_struct);

  const char *severity_string = "UNKNOWN_SEVERITY";
  switch (severity) {
    case SEVERITY_INFO:
      severity_string = "INFO";
      break;
    case SEVERITY_ERROR:
      severity_string = "ERROR";
      break;
  }

  stream_ << time_string << ": " << PathnameStripper::File(file) << ":" <<
             line << ": " << severity_string << ": ";
}

LogStream::~LogStream() {
  stream_ << std::endl;
}

std::string HexString(u_int32_t number) {
  char buffer[11];
  snprintf(buffer, sizeof(buffer), "0x%x", number);
  return std::string(buffer);
}

std::string HexString(u_int64_t number) {
  char buffer[19];
  snprintf(buffer, sizeof(buffer), "0x%" PRIx64, number);
  return std::string(buffer);
}

std::string HexString(int number) {
  char buffer[19];
  snprintf(buffer, sizeof(buffer), "0x%x", number);
  return std::string(buffer);
}

int ErrnoString(std::string *error_string) {
  assert(error_string);

  // strerror isn't necessarily thread-safe.  strerror_r would be preferrable,
  // but GNU libc uses a nonstandard strerror_r by default, which returns a
  // char* (rather than an int success indicator) and doesn't necessarily
  // use the supplied buffer.
  error_string->assign(strerror(errno));
  return errno;
}

}  // namespace google_breakpad
<commit_msg>Fix review comment that I missed.<commit_after>// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// logging.cc: Breakpad logging
//
// See logging.h for documentation.
//
// Author: Mark Mentovai

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

#include "processor/logging.h"
#include "processor/pathname_stripper.h"

#ifdef _WIN32
#define snprintf _snprintf
#endif

namespace google_breakpad {

LogStream::LogStream(std::ostream &stream, Severity severity,
                     const char *file, int line)
    : stream_(stream) {
  time_t clock;
  time(&clock);
  struct tm tm_struct;
#ifdef _WIN32
  localtime_s(&tm_struct, &clock);
#else
  localtime_r(&clock, &tm_struct);
#endif
  char time_string[20];
  strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", &tm_struct);

  const char *severity_string = "UNKNOWN_SEVERITY";
  switch (severity) {
    case SEVERITY_INFO:
      severity_string = "INFO";
      break;
    case SEVERITY_ERROR:
      severity_string = "ERROR";
      break;
  }

  stream_ << time_string << ": " << PathnameStripper::File(file) << ":" <<
             line << ": " << severity_string << ": ";
}

LogStream::~LogStream() {
  stream_ << std::endl;
}

std::string HexString(u_int32_t number) {
  char buffer[11];
  snprintf(buffer, sizeof(buffer), "0x%x", number);
  return std::string(buffer);
}

std::string HexString(u_int64_t number) {
  char buffer[19];
  snprintf(buffer, sizeof(buffer), "0x%" PRIx64, number);
  return std::string(buffer);
}

std::string HexString(int number) {
  char buffer[19];
  snprintf(buffer, sizeof(buffer), "0x%x", number);
  return std::string(buffer);
}

int ErrnoString(std::string *error_string) {
  assert(error_string);

  // strerror isn't necessarily thread-safe.  strerror_r would be preferrable,
  // but GNU libc uses a nonstandard strerror_r by default, which returns a
  // char* (rather than an int success indicator) and doesn't necessarily
  // use the supplied buffer.
  error_string->assign(strerror(errno));
  return errno;
}

}  // namespace google_breakpad
<|endoftext|>


<commit_before>/** Copyright 2008, 2009, 2010, 2011, 2012 Roland Olbricht
*
* This file is part of Overpass_API.
*
* Overpass_API is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Overpass_API 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "../expat/expat_justparse_interface.h"

#include <iostream>

using namespace std;

char hex_digit(char c)
{
  if (c <= 57)
  {
    if (c >= 48)
      return c - 48;
    return 16;
  }
  if (c <= 70)
  {
    if (c >= 65)
      return c - 55;
    return 16;
  }
  if (c <= 102)
  {
    if (c >= 97)
      return c - 87;
    return 16;
  }
  return 16;
}

string decode_cgi_to_plain(const string& raw)
{
  string result;
  string::size_type pos(0);

  while (pos < raw.size())
  {
    if (raw[pos] == '%')
    {
      if (pos >= raw.size()+2)
	return (result + raw.substr(0, pos));
      char a(hex_digit(raw[pos+1])), b(hex_digit(raw[pos+2]));
      if ((a < 16) && (b < 16))
      {
	result += (char)(a*16 + b);
	pos += 3;
      }
      else
	result += raw[pos++];
    }
    else if (raw[pos] == '+')
    {
      result += ' ';
      ++pos;
    }
    else if (raw[pos] == '&')
      pos = raw.size();
    else
      result += raw[pos++];
  }

  return result;
}

int main(int argc, char *argv[])
{
  char c;
  string buf;
  while (!cin.eof())
  {
    cin.get(c);
    buf += c;
  }

  cout<<decode_cgi_to_plain(buf);

  return 0;
}
<commit_msg>Removed unnecessary dependency.<commit_after>/** Copyright 2008, 2009, 2010, 2011, 2012 Roland Olbricht
*
* This file is part of Overpass_API.
*
* Overpass_API is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Overpass_API 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>

using namespace std;

char hex_digit(char c)
{
  if (c <= 57)
  {
    if (c >= 48)
      return c - 48;
    return 16;
  }
  if (c <= 70)
  {
    if (c >= 65)
      return c - 55;
    return 16;
  }
  if (c <= 102)
  {
    if (c >= 97)
      return c - 87;
    return 16;
  }
  return 16;
}

string decode_cgi_to_plain(const string& raw)
{
  string result;
  string::size_type pos(0);

  while (pos < raw.size())
  {
    if (raw[pos] == '%')
    {
      if (pos >= raw.size()+2)
	return (result + raw.substr(0, pos));
      char a(hex_digit(raw[pos+1])), b(hex_digit(raw[pos+2]));
      if ((a < 16) && (b < 16))
      {
	result += (char)(a*16 + b);
	pos += 3;
      }
      else
	result += raw[pos++];
    }
    else if (raw[pos] == '+')
    {
      result += ' ';
      ++pos;
    }
    else if (raw[pos] == '&')
      pos = raw.size();
    else
      result += raw[pos++];
  }

  return result;
}

int main(int argc, char *argv[])
{
  char c;
  string buf;
  while (!cin.eof())
  {
    cin.get(c);
    buf += c;
  }

  cout<<decode_cgi_to_plain(buf);

  return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "platformstyle.h"

#include "guiconstants.h"

#include <QApplication>
#include <QColor>
#include <QIcon>
#include <QImage>
#include <QPalette>
#include <QPixmap>

static const struct {
    const char *platformId;
    /** Show images on push buttons */
    const bool imagesOnButtons;
    /** Colorize single-color icons */
    const bool colorizeIcons;
    /** Extra padding/spacing in transactionview */
    const bool useExtraSpacing;
} platform_styles[] = {
    {"macosx", false, false, true},
    {"windows", true, false, false},
    /* Other: linux, unix, ... */
    {"other", true, true, false}
};
static const unsigned platform_styles_count = sizeof(platform_styles)/sizeof(*platform_styles);

namespace {
/* Local functions for colorizing single-color images */

void MakeSingleColorImage(QImage& img, const QColor& colorbase)
{
    img = img.convertToFormat(QImage::Format_ARGB32);
    for (int x = img.width(); x--; )
    {
        for (int y = img.height(); y--; )
        {
            const QRgb rgb = img.pixel(x, y);
            img.setPixel(x, y, qRgba(colorbase.red(), colorbase.green(), colorbase.blue(), qAlpha(rgb)));
        }
    }
}

QIcon ColorizeIcon(const QIcon& ico, const QColor& colorbase)
{
    QIcon new_ico;
    QSize sz;
    Q_FOREACH(sz, ico.availableSizes())
    {
        QImage img(ico.pixmap(sz).toImage());
        MakeSingleColorImage(img, colorbase);
        new_ico.addPixmap(QPixmap::fromImage(img));
    }
    return new_ico;
}

QImage ColorizeImage(const QString& filename, const QColor& colorbase)
{
    QImage img(filename);
    MakeSingleColorImage(img, colorbase);
    return img;
}

QIcon ColorizeIcon(const QString& filename, const QColor& colorbase)
{
    return QIcon(QPixmap::fromImage(ColorizeImage(filename, QColor("#77A83F"))));
}

}

PlatformStyle::PlatformStyle(const QString &name, bool imagesOnButtons, bool colorizeIcons, bool useExtraSpacing):
    name(name),
    imagesOnButtons(imagesOnButtons),
    colorizeIcons(colorizeIcons),
    useExtraSpacing(useExtraSpacing),
    singleColor(0,0,0),
    textColor(0,0,0)
{
    // Determine icon highlighting color
    if (colorizeIcons) {
        const QColor colorHighlightBg(QApplication::palette().color(QPalette::Highlight));
        const QColor colorHighlightFg(QApplication::palette().color(QPalette::HighlightedText));
        const QColor colorText(QApplication::palette().color(QPalette::WindowText));
        const int colorTextLightness = colorText.lightness();
        QColor colorbase;
        if (abs(colorHighlightBg.lightness() - colorTextLightness) < abs(colorHighlightFg.lightness() - colorTextLightness))
            colorbase = colorHighlightBg;
        else
            colorbase = colorHighlightFg;
        singleColor = colorbase;
    }
    // Determine text color
    textColor = QColor(QApplication::palette().color(QPalette::WindowText));
}

QImage PlatformStyle::SingleColorImage(const QString& filename) const
{
    if (!colorizeIcons)
        return QImage(filename);
    return ColorizeImage(filename, SingleColor());
}

QIcon PlatformStyle::SingleColorIcon(const QString& filename) const
{
    if (!colorizeIcons)
        return QIcon(filename);
    return ColorizeIcon(filename, SingleColor());
}

QIcon PlatformStyle::SingleColorIcon(const QIcon& icon) const
{
    if (!colorizeIcons)
        return icon;
    return ColorizeIcon(icon, SingleColor());
}

QIcon PlatformStyle::TextColorIcon(const QString& filename) const
{
    return ColorizeIcon(filename, TextColor());
}

QIcon PlatformStyle::TextColorIcon(const QIcon& icon) const
{
    return ColorizeIcon(icon, TextColor());
}

const PlatformStyle *PlatformStyle::instantiate(const QString &platformId)
{
    for (unsigned x=0; x<platform_styles_count; ++x)
    {
        if (platformId == platform_styles[x].platformId)
        {
            return new PlatformStyle(
                    platform_styles[x].platformId,
                    platform_styles[x].imagesOnButtons,
                    platform_styles[x].colorizeIcons,
                    platform_styles[x].useExtraSpacing);
        }
    }
    return 0;
}

<commit_msg>Express QColor in rgba<commit_after>// Copyright (c) 2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "platformstyle.h"

#include "guiconstants.h"

#include <QApplication>
#include <QColor>
#include <QIcon>
#include <QImage>
#include <QPalette>
#include <QPixmap>

static const struct {
    const char *platformId;
    /** Show images on push buttons */
    const bool imagesOnButtons;
    /** Colorize single-color icons */
    const bool colorizeIcons;
    /** Extra padding/spacing in transactionview */
    const bool useExtraSpacing;
} platform_styles[] = {
    {"macosx", false, false, true},
    {"windows", true, false, false},
    /* Other: linux, unix, ... */
    {"other", true, true, false}
};
static const unsigned platform_styles_count = sizeof(platform_styles)/sizeof(*platform_styles);

namespace {
/* Local functions for colorizing single-color images */

void MakeSingleColorImage(QImage& img, const QColor& colorbase)
{
    img = img.convertToFormat(QImage::Format_ARGB32);
    for (int x = img.width(); x--; )
    {
        for (int y = img.height(); y--; )
        {
            const QRgb rgb = img.pixel(x, y);
            img.setPixel(x, y, qRgba(colorbase.red(), colorbase.green(), colorbase.blue(), qAlpha(rgb)));
        }
    }
}

QIcon ColorizeIcon(const QIcon& ico, const QColor& colorbase)
{
    QIcon new_ico;
    QSize sz;
    Q_FOREACH(sz, ico.availableSizes())
    {
        QImage img(ico.pixmap(sz).toImage());
        MakeSingleColorImage(img, colorbase);
        new_ico.addPixmap(QPixmap::fromImage(img));
    }
    return new_ico;
}

QImage ColorizeImage(const QString& filename, const QColor& colorbase)
{
    QImage img(filename);
    MakeSingleColorImage(img, colorbase);
    return img;
}

QIcon ColorizeIcon(const QString& filename, const QColor& colorbase)
{
    return QIcon(QPixmap::fromImage(ColorizeImage(filename, QColor(119,168,63,1))));
}

}

PlatformStyle::PlatformStyle(const QString &name, bool imagesOnButtons, bool colorizeIcons, bool useExtraSpacing):
    name(name),
    imagesOnButtons(imagesOnButtons),
    colorizeIcons(colorizeIcons),
    useExtraSpacing(useExtraSpacing),
    singleColor(0,0,0),
    textColor(0,0,0)
{
    // Determine icon highlighting color
    if (colorizeIcons) {
        const QColor colorHighlightBg(QApplication::palette().color(QPalette::Highlight));
        const QColor colorHighlightFg(QApplication::palette().color(QPalette::HighlightedText));
        const QColor colorText(QApplication::palette().color(QPalette::WindowText));
        const int colorTextLightness = colorText.lightness();
        QColor colorbase;
        if (abs(colorHighlightBg.lightness() - colorTextLightness) < abs(colorHighlightFg.lightness() - colorTextLightness))
            colorbase = colorHighlightBg;
        else
            colorbase = colorHighlightFg;
        singleColor = colorbase;
    }
    // Determine text color
    textColor = QColor(QApplication::palette().color(QPalette::WindowText));
}

QImage PlatformStyle::SingleColorImage(const QString& filename) const
{
    if (!colorizeIcons)
        return QImage(filename);
    return ColorizeImage(filename, SingleColor());
}

QIcon PlatformStyle::SingleColorIcon(const QString& filename) const
{
    if (!colorizeIcons)
        return QIcon(filename);
    return ColorizeIcon(filename, SingleColor());
}

QIcon PlatformStyle::SingleColorIcon(const QIcon& icon) const
{
    if (!colorizeIcons)
        return icon;
    return ColorizeIcon(icon, SingleColor());
}

QIcon PlatformStyle::TextColorIcon(const QString& filename) const
{
    return ColorizeIcon(filename, TextColor());
}

QIcon PlatformStyle::TextColorIcon(const QIcon& icon) const
{
    return ColorizeIcon(icon, TextColor());
}

const PlatformStyle *PlatformStyle::instantiate(const QString &platformId)
{
    for (unsigned x=0; x<platform_styles_count; ++x)
    {
        if (platformId == platform_styles[x].platformId)
        {
            return new PlatformStyle(
                    platform_styles[x].platformId,
                    platform_styles[x].imagesOnButtons,
                    platform_styles[x].colorizeIcons,
                    platform_styles[x].useExtraSpacing);
        }
    }
    return 0;
}

<|endoftext|>


<commit_before>// GRSimpleVals.cpp - Transfer functions for tracking simple values -*- C++ -*--
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines GRSimpleVals, a sub-class of GRTransferFuncs that
//  provides transfer functions for performing simple value tracking with
//  limited support for symbolics.
//
//===----------------------------------------------------------------------===//

#include "GRSimpleVals.h"
#include "clang/Analysis/PathSensitive/ValueState.h"
#include "clang/Basic/Diagnostic.h"
#include <sstream>

using namespace clang;

namespace clang {

template <typename ITERATOR>
static inline const PostStmt& GetLocation(ITERATOR I) {
  return cast<PostStmt>((*I)->getLocation());
}

template <>
inline const PostStmt& GetLocation(GRExprEngine::undef_arg_iterator I) {
  return cast<PostStmt>(I->first->getLocation());
}

template <typename ITERATOR>
static void EmitDiag(Diagnostic& Diag, SourceManager& SrcMgr,
                     unsigned ErrorDiag, ITERATOR I) {

  Expr* Exp = cast<Expr>(GetLocation(I).getStmt());
  cast<Expr>(GetLocation(I).getStmt());
  Diag.Report(FullSourceLoc(Exp->getExprLoc(), SrcMgr), ErrorDiag);
}

template <>
static void EmitDiag(Diagnostic& Diag, SourceManager& SrcMgr,
                     unsigned ErrorDiag, GRExprEngine::undef_arg_iterator I) {

  Expr* E1 = cast<Expr>(GetLocation(I).getStmt());
  Expr* E2 = cast<Expr>(I->second);

  SourceLocation Loc = E1->getExprLoc();
  SourceRange R = E2->getSourceRange();
  Diag.Report(FullSourceLoc(Loc, SrcMgr), ErrorDiag, 0, 0, &R, 1);
}

template <typename ITERATOR>
void EmitWarning(Diagnostic& Diag, SourceManager& SrcMgr,
                 ITERATOR I, ITERATOR E, const char* msg) {

  std::ostringstream Out;
  Out << "[CHECKER] " << msg;
  msg = Out.str().c_str();

  bool isFirst = true;
  unsigned ErrorDiag;
  llvm::SmallPtrSet<void*,10> CachedErrors;

  for (; I != E; ++I) {

    if (isFirst) {
      isFirst = false;
      ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, msg);
    }
    else {

      // HACK: Cache the location of the error.  Don't emit the same
      // warning for the same error type that occurs at the same program
      // location but along a different path.
      void* p = GetLocation(I).getRawData();

      if (CachedErrors.count(p))
        continue;

      CachedErrors.insert(p);
    }

    EmitDiag(Diag, SrcMgr, ErrorDiag, I);
  }
}

unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
                         Diagnostic& Diag, bool Visualize, bool TrimGraph) {

  if (Diag.hasErrorOccurred())
    return 0;

  GRCoreEngine<GRExprEngine> Eng(cfg, FD, Ctx);
  GRExprEngine* CheckerState = &Eng.getCheckerState();
  GRSimpleVals GRSV;
  CheckerState->setTransferFunctions(GRSV);

  // Execute the worklist algorithm.
  Eng.ExecuteWorkList(100000);

  SourceManager& SrcMgr = Ctx.getSourceManager();

  EmitWarning(Diag, SrcMgr,
              CheckerState->null_derefs_begin(),
              CheckerState->null_derefs_end(),
              "NULL pointer is dereferenced after it is checked for NULL.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_derefs_begin(),
              CheckerState->undef_derefs_end(),
              "Dereference of undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_derefs_begin(),
              CheckerState->undef_derefs_end(),
              "Dereference of undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->explicit_bad_divides_begin(),
              CheckerState->explicit_bad_divides_end(),
              "Division by zero/undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_results_begin(),
              CheckerState->undef_results_end(),
              "Result of operation is undefined.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->bad_calls_begin(),
              CheckerState->bad_calls_end(),
              "Call using a NULL or undefined function pointer value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_arg_begin(),
              CheckerState->undef_arg_end(),
      "Pass-by-value argument in function or message expression is undefined.");

#ifndef NDEBUG
  if (Visualize) CheckerState->ViewGraph(TrimGraph);
#endif

  return Eng.getGraph().size();
}

} // end clang namespace

//===----------------------------------------------------------------------===//
// Transfer function for Casts.
//===----------------------------------------------------------------------===//

RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, NonLVal X, QualType T) {

  if (!isa<nonlval::ConcreteInt>(X))
    return UnknownVal();

  BasicValueFactory& BasicVals = Eng.getBasicVals();

  llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
  V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
  V.extOrTrunc(Eng.getContext().getTypeSize(T));

  if (T->isPointerType())
    return lval::ConcreteInt(BasicVals.getValue(V));
  else
    return nonlval::ConcreteInt(BasicVals.getValue(V));
}

// Casts.

RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, LVal X, QualType T) {

  if (T->isPointerType() || T->isReferenceType())
    return X;

  assert (T->isIntegerType());

  if (!isa<lval::ConcreteInt>(X))
    return UnknownVal();

  BasicValueFactory& BasicVals = Eng.getBasicVals();

  llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
  V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
  V.extOrTrunc(Eng.getContext().getTypeSize(T));

  return nonlval::ConcreteInt(BasicVals.getValue(V));
}

// Unary operators.

RVal GRSimpleVals::EvalMinus(GRExprEngine& Eng, UnaryOperator* U, NonLVal X){

  switch (X.getSubKind()) {

    case nonlval::ConcreteIntKind:
      return cast<nonlval::ConcreteInt>(X).EvalMinus(Eng.getBasicVals(), U);

    default:
      return UnknownVal();
  }
}

RVal GRSimpleVals::EvalComplement(GRExprEngine& Eng, NonLVal X) {

  switch (X.getSubKind()) {

    case nonlval::ConcreteIntKind:
      return cast<nonlval::ConcreteInt>(X).EvalComplement(Eng.getBasicVals());

    default:
      return UnknownVal();
  }
}

// Binary operators.

RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
                             NonLVal L, NonLVal R)  {

  BasicValueFactory& BasicVals = Eng.getBasicVals();

  while (1) {

    switch (L.getSubKind()) {
      default:
        return UnknownVal();

      case nonlval::ConcreteIntKind:

        if (isa<nonlval::ConcreteInt>(R)) {
          const nonlval::ConcreteInt& L_CI = cast<nonlval::ConcreteInt>(L);
          const nonlval::ConcreteInt& R_CI = cast<nonlval::ConcreteInt>(R);
          return L_CI.EvalBinOp(BasicVals, Op, R_CI);
        }
        else {
          NonLVal tmp = R;
          R = L;
          L = tmp;
          continue;
        }

      case nonlval::SymbolValKind: {

        if (isa<nonlval::ConcreteInt>(R)) {
          const SymIntConstraint& C =
            BasicVals.getConstraint(cast<nonlval::SymbolVal>(L).getSymbol(), Op,
                                    cast<nonlval::ConcreteInt>(R).getValue());

          return nonlval::SymIntConstraintVal(C);
        }
        else
          return UnknownVal();
      }
    }
  }
}

// Binary Operators (except assignments and comma).

RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
                             LVal L, LVal R) {

  switch (Op) {

    default:
      return UnknownVal();

    case BinaryOperator::EQ:
      return EvalEQ(Eng, L, R);

    case BinaryOperator::NE:
      return EvalNE(Eng, L, R);
  }
}

// Pointer arithmetic.

RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
                             LVal L, NonLVal R) {
  return UnknownVal();
}

// Equality operators for LVals.

RVal GRSimpleVals::EvalEQ(GRExprEngine& Eng, LVal L, LVal R) {

  BasicValueFactory& BasicVals = Eng.getBasicVals();

  switch (L.getSubKind()) {

    default:
      assert(false && "EQ not implemented for this LVal.");
      return UnknownVal();

    case lval::ConcreteIntKind:

      if (isa<lval::ConcreteInt>(R)) {
        bool b = cast<lval::ConcreteInt>(L).getValue() ==
                 cast<lval::ConcreteInt>(R).getValue();

        return NonLVal::MakeIntTruthVal(BasicVals, b);
      }
      else if (isa<lval::SymbolVal>(R)) {

        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
                               BinaryOperator::EQ,
                               cast<lval::ConcreteInt>(L).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      break;

    case lval::SymbolValKind: {

      if (isa<lval::ConcreteInt>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
                               BinaryOperator::EQ,
                               cast<lval::ConcreteInt>(R).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      // FIXME: Implement == for lval Symbols.  This is mainly useful
      //  in iterator loops when traversing a buffer, e.g. while(z != zTerm).
      //  Since this is not useful for many checkers we'll punt on this for
      //  now.

      return UnknownVal();
    }

    case lval::DeclValKind:
    case lval::FuncValKind:
    case lval::GotoLabelKind:
      return NonLVal::MakeIntTruthVal(BasicVals, L == R);
  }

  return NonLVal::MakeIntTruthVal(BasicVals, false);
}

RVal GRSimpleVals::EvalNE(GRExprEngine& Eng, LVal L, LVal R) {

  BasicValueFactory& BasicVals = Eng.getBasicVals();

  switch (L.getSubKind()) {

    default:
      assert(false && "NE not implemented for this LVal.");
      return UnknownVal();

    case lval::ConcreteIntKind:

      if (isa<lval::ConcreteInt>(R)) {
        bool b = cast<lval::ConcreteInt>(L).getValue() !=
                 cast<lval::ConcreteInt>(R).getValue();

        return NonLVal::MakeIntTruthVal(BasicVals, b);
      }
      else if (isa<lval::SymbolVal>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
                                  BinaryOperator::NE,
                                  cast<lval::ConcreteInt>(L).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      break;

    case lval::SymbolValKind: {
      if (isa<lval::ConcreteInt>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
                                  BinaryOperator::NE,
                                  cast<lval::ConcreteInt>(R).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      // FIXME: Implement != for lval Symbols.  This is mainly useful
      //  in iterator loops when traversing a buffer, e.g. while(z != zTerm).
      //  Since this is not useful for many checkers we'll punt on this for
      //  now.

      return UnknownVal();

      break;
    }

    case lval::DeclValKind:
    case lval::FuncValKind:
    case lval::GotoLabelKind:
      return NonLVal::MakeIntTruthVal(BasicVals, L != R);
  }

  return NonLVal::MakeIntTruthVal(BasicVals, true);
}

//===----------------------------------------------------------------------===//
// Transfer function for Function Calls.
//===----------------------------------------------------------------------===//

void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst,
                            GRExprEngine& Eng,
                            GRStmtNodeBuilder<ValueState>& Builder,
                            CallExpr* CE, LVal L,
                            ExplodedNode<ValueState>* Pred) {

  ValueState* St = Pred->getState();

  // Invalidate all arguments passed in by reference (LVals).

  for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
        I != E; ++I) {

    RVal V = Eng.getStateManager().GetRVal(St, *I);

    if (isa<LVal>(V))
      St = Eng.getStateManager().SetRVal(St, cast<LVal>(V), UnknownVal());
  }

  Builder.Nodify(Dst, CE, Pred, St);
}
<commit_msg>In GRSimpleVals, added the generation of symbolic values for the return values of function calls. This is useful in pruning paths.<commit_after>// GRSimpleVals.cpp - Transfer functions for tracking simple values -*- C++ -*--
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines GRSimpleVals, a sub-class of GRTransferFuncs that
//  provides transfer functions for performing simple value tracking with
//  limited support for symbolics.
//
//===----------------------------------------------------------------------===//

#include "GRSimpleVals.h"
#include "clang/Analysis/PathSensitive/ValueState.h"
#include "clang/Basic/Diagnostic.h"
#include <sstream>

using namespace clang;

namespace clang {

template <typename ITERATOR>
static inline const PostStmt& GetLocation(ITERATOR I) {
  return cast<PostStmt>((*I)->getLocation());
}

template <>
inline const PostStmt& GetLocation(GRExprEngine::undef_arg_iterator I) {
  return cast<PostStmt>(I->first->getLocation());
}

template <typename ITERATOR>
static void EmitDiag(Diagnostic& Diag, SourceManager& SrcMgr,
                     unsigned ErrorDiag, ITERATOR I) {

  Expr* Exp = cast<Expr>(GetLocation(I).getStmt());
  cast<Expr>(GetLocation(I).getStmt());
  Diag.Report(FullSourceLoc(Exp->getExprLoc(), SrcMgr), ErrorDiag);
}

template <>
static void EmitDiag(Diagnostic& Diag, SourceManager& SrcMgr,
                     unsigned ErrorDiag, GRExprEngine::undef_arg_iterator I) {

  Expr* E1 = cast<Expr>(GetLocation(I).getStmt());
  Expr* E2 = cast<Expr>(I->second);

  SourceLocation Loc = E1->getExprLoc();
  SourceRange R = E2->getSourceRange();
  Diag.Report(FullSourceLoc(Loc, SrcMgr), ErrorDiag, 0, 0, &R, 1);
}

template <typename ITERATOR>
void EmitWarning(Diagnostic& Diag, SourceManager& SrcMgr,
                 ITERATOR I, ITERATOR E, const char* msg) {

  std::ostringstream Out;
  Out << "[CHECKER] " << msg;
  msg = Out.str().c_str();

  bool isFirst = true;
  unsigned ErrorDiag;
  llvm::SmallPtrSet<void*,10> CachedErrors;

  for (; I != E; ++I) {

    if (isFirst) {
      isFirst = false;
      ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, msg);
    }
    else {

      // HACK: Cache the location of the error.  Don't emit the same
      // warning for the same error type that occurs at the same program
      // location but along a different path.
      void* p = GetLocation(I).getRawData();

      if (CachedErrors.count(p))
        continue;

      CachedErrors.insert(p);
    }

    EmitDiag(Diag, SrcMgr, ErrorDiag, I);
  }
}

unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
                         Diagnostic& Diag, bool Visualize, bool TrimGraph) {

  if (Diag.hasErrorOccurred())
    return 0;

  GRCoreEngine<GRExprEngine> Eng(cfg, FD, Ctx);
  GRExprEngine* CheckerState = &Eng.getCheckerState();
  GRSimpleVals GRSV;
  CheckerState->setTransferFunctions(GRSV);

  // Execute the worklist algorithm.
  Eng.ExecuteWorkList(100000);

  SourceManager& SrcMgr = Ctx.getSourceManager();

  EmitWarning(Diag, SrcMgr,
              CheckerState->null_derefs_begin(),
              CheckerState->null_derefs_end(),
              "NULL pointer is dereferenced after it is checked for NULL.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_derefs_begin(),
              CheckerState->undef_derefs_end(),
              "Dereference of undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_derefs_begin(),
              CheckerState->undef_derefs_end(),
              "Dereference of undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->explicit_bad_divides_begin(),
              CheckerState->explicit_bad_divides_end(),
              "Division by zero/undefined value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_results_begin(),
              CheckerState->undef_results_end(),
              "Result of operation is undefined.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->bad_calls_begin(),
              CheckerState->bad_calls_end(),
              "Call using a NULL or undefined function pointer value.");

  EmitWarning(Diag, SrcMgr,
              CheckerState->undef_arg_begin(),
              CheckerState->undef_arg_end(),
      "Pass-by-value argument in function or message expression is undefined.");

#ifndef NDEBUG
  if (Visualize) CheckerState->ViewGraph(TrimGraph);
#endif

  return Eng.getGraph().size();
}

} // end clang namespace

//===----------------------------------------------------------------------===//
// Transfer function for Casts.
//===----------------------------------------------------------------------===//

RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, NonLVal X, QualType T) {

  if (!isa<nonlval::ConcreteInt>(X))
    return UnknownVal();

  BasicValueFactory& BasicVals = Eng.getBasicVals();

  llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
  V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
  V.extOrTrunc(Eng.getContext().getTypeSize(T));

  if (T->isPointerType())
    return lval::ConcreteInt(BasicVals.getValue(V));
  else
    return nonlval::ConcreteInt(BasicVals.getValue(V));
}

// Casts.

RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, LVal X, QualType T) {

  if (T->isPointerType() || T->isReferenceType())
    return X;

  assert (T->isIntegerType());

  if (!isa<lval::ConcreteInt>(X))
    return UnknownVal();

  BasicValueFactory& BasicVals = Eng.getBasicVals();

  llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
  V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
  V.extOrTrunc(Eng.getContext().getTypeSize(T));

  return nonlval::ConcreteInt(BasicVals.getValue(V));
}

// Unary operators.

RVal GRSimpleVals::EvalMinus(GRExprEngine& Eng, UnaryOperator* U, NonLVal X){

  switch (X.getSubKind()) {

    case nonlval::ConcreteIntKind:
      return cast<nonlval::ConcreteInt>(X).EvalMinus(Eng.getBasicVals(), U);

    default:
      return UnknownVal();
  }
}

RVal GRSimpleVals::EvalComplement(GRExprEngine& Eng, NonLVal X) {

  switch (X.getSubKind()) {

    case nonlval::ConcreteIntKind:
      return cast<nonlval::ConcreteInt>(X).EvalComplement(Eng.getBasicVals());

    default:
      return UnknownVal();
  }
}

// Binary operators.

RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
                             NonLVal L, NonLVal R)  {

  BasicValueFactory& BasicVals = Eng.getBasicVals();

  while (1) {

    switch (L.getSubKind()) {
      default:
        return UnknownVal();

      case nonlval::ConcreteIntKind:

        if (isa<nonlval::ConcreteInt>(R)) {
          const nonlval::ConcreteInt& L_CI = cast<nonlval::ConcreteInt>(L);
          const nonlval::ConcreteInt& R_CI = cast<nonlval::ConcreteInt>(R);
          return L_CI.EvalBinOp(BasicVals, Op, R_CI);
        }
        else {
          NonLVal tmp = R;
          R = L;
          L = tmp;
          continue;
        }

      case nonlval::SymbolValKind: {

        if (isa<nonlval::ConcreteInt>(R)) {
          const SymIntConstraint& C =
            BasicVals.getConstraint(cast<nonlval::SymbolVal>(L).getSymbol(), Op,
                                    cast<nonlval::ConcreteInt>(R).getValue());

          return nonlval::SymIntConstraintVal(C);
        }
        else
          return UnknownVal();
      }
    }
  }
}

// Binary Operators (except assignments and comma).

RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
                             LVal L, LVal R) {

  switch (Op) {

    default:
      return UnknownVal();

    case BinaryOperator::EQ:
      return EvalEQ(Eng, L, R);

    case BinaryOperator::NE:
      return EvalNE(Eng, L, R);
  }
}

// Pointer arithmetic.

RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
                             LVal L, NonLVal R) {
  return UnknownVal();
}

// Equality operators for LVals.

RVal GRSimpleVals::EvalEQ(GRExprEngine& Eng, LVal L, LVal R) {

  BasicValueFactory& BasicVals = Eng.getBasicVals();

  switch (L.getSubKind()) {

    default:
      assert(false && "EQ not implemented for this LVal.");
      return UnknownVal();

    case lval::ConcreteIntKind:

      if (isa<lval::ConcreteInt>(R)) {
        bool b = cast<lval::ConcreteInt>(L).getValue() ==
                 cast<lval::ConcreteInt>(R).getValue();

        return NonLVal::MakeIntTruthVal(BasicVals, b);
      }
      else if (isa<lval::SymbolVal>(R)) {

        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
                               BinaryOperator::EQ,
                               cast<lval::ConcreteInt>(L).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      break;

    case lval::SymbolValKind: {

      if (isa<lval::ConcreteInt>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
                               BinaryOperator::EQ,
                               cast<lval::ConcreteInt>(R).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      // FIXME: Implement == for lval Symbols.  This is mainly useful
      //  in iterator loops when traversing a buffer, e.g. while(z != zTerm).
      //  Since this is not useful for many checkers we'll punt on this for
      //  now.

      return UnknownVal();
    }

    case lval::DeclValKind:
    case lval::FuncValKind:
    case lval::GotoLabelKind:
      return NonLVal::MakeIntTruthVal(BasicVals, L == R);
  }

  return NonLVal::MakeIntTruthVal(BasicVals, false);
}

RVal GRSimpleVals::EvalNE(GRExprEngine& Eng, LVal L, LVal R) {

  BasicValueFactory& BasicVals = Eng.getBasicVals();

  switch (L.getSubKind()) {

    default:
      assert(false && "NE not implemented for this LVal.");
      return UnknownVal();

    case lval::ConcreteIntKind:

      if (isa<lval::ConcreteInt>(R)) {
        bool b = cast<lval::ConcreteInt>(L).getValue() !=
                 cast<lval::ConcreteInt>(R).getValue();

        return NonLVal::MakeIntTruthVal(BasicVals, b);
      }
      else if (isa<lval::SymbolVal>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
                                  BinaryOperator::NE,
                                  cast<lval::ConcreteInt>(L).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      break;

    case lval::SymbolValKind: {
      if (isa<lval::ConcreteInt>(R)) {
        const SymIntConstraint& C =
          BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
                                  BinaryOperator::NE,
                                  cast<lval::ConcreteInt>(R).getValue());

        return nonlval::SymIntConstraintVal(C);
      }

      // FIXME: Implement != for lval Symbols.  This is mainly useful
      //  in iterator loops when traversing a buffer, e.g. while(z != zTerm).
      //  Since this is not useful for many checkers we'll punt on this for
      //  now.

      return UnknownVal();

      break;
    }

    case lval::DeclValKind:
    case lval::FuncValKind:
    case lval::GotoLabelKind:
      return NonLVal::MakeIntTruthVal(BasicVals, L != R);
  }

  return NonLVal::MakeIntTruthVal(BasicVals, true);
}

//===----------------------------------------------------------------------===//
// Transfer function for Function Calls.
//===----------------------------------------------------------------------===//

void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst,
                            GRExprEngine& Eng,
                            GRStmtNodeBuilder<ValueState>& Builder,
                            CallExpr* CE, LVal L,
                            ExplodedNode<ValueState>* Pred) {

  ValueStateManager& StateMgr = Eng.getStateManager();
  ValueState* St = Builder.GetState(Pred);

  // Invalidate all arguments passed in by reference (LVals).

  for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
        I != E; ++I) {

    RVal V = StateMgr.GetRVal(St, *I);

    if (isa<LVal>(V))
      St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
  }

  // Make up a symbol for the return value of this function.

  if (CE->getType() != Eng.getContext().VoidTy) {
    unsigned Count = Builder.getCurrentBlockCount();
    SymbolID Sym = Eng.getSymbolManager().getCallRetValSymbol(CE, Count);

    RVal X = CE->getType()->isPointerType()
             ? cast<RVal>(lval::SymbolVal(Sym))
             : cast<RVal>(nonlval::SymbolVal(Sym));

    St = StateMgr.SetRVal(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
  }

  Builder.Nodify(Dst, CE, Pred, St);
}
<|endoftext|>