<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * 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
 *
 *****************************************************************************/

//$Id$

#ifndef FEATURE_STYLE_PROCESSOR_HPP
#define FEATURE_STYLE_PROCESSOR_HPP

// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>

#ifdef MAPNIK_DEBUG
//#include <mapnik/wall_clock_timer.hpp>
#endif
//stl
#include <vector>

namespace mapnik
{
template <typename Processor>
class feature_style_processor
{
    struct symbol_dispatch : public boost::static_visitor<>
    {
        symbol_dispatch (Processor & output,
                         Feature const& f,
                         proj_transform const& prj_trans)
            : output_(output),
              f_(f),
              prj_trans_(prj_trans)  {}

        template <typename T>
        void operator () (T const& sym) const
        {
            output_.process(sym,f_,prj_trans_);
        }

        Processor & output_;
        Feature const& f_;
        proj_transform const& prj_trans_;
    };
public:
    feature_style_processor(Map const& m)
        : m_(m) {}

    void apply()
    {
#ifdef MAPNIK_DEBUG
        //mapnik::wall_clock_progress_timer t(std::clog, "map rendering took: ");
#endif
        Processor & p = static_cast<Processor&>(*this);
        p.start_map_processing(m_);

        try
        {
            projection proj(m_.srs()); // map projection
            double scale_denom = mapnik::scale_denominator(m_,proj.is_geographic());
#ifdef MAPNIK_DEBUG
            std::clog << "scale denominator = " << scale_denom << "\n";
#endif
            std::vector<layer>::const_iterator itr = m_.layers().begin();
            std::vector<layer>::const_iterator end = m_.layers().end();

            while (itr != end)
            {
                if (itr->isVisible(scale_denom))
                {
                    apply_to_layer(*itr, p, proj, scale_denom);
                }
                ++itr;
            }
        }
        catch (proj_init_error& ex)
        {
            std::clog << "proj_init_error:" << ex.what() << "\n";
        }

        p.end_map_processing(m_);
    }
private:
    void apply_to_layer(layer const& lay, Processor & p,
                        projection const& proj0,double scale_denom)
    {
#ifdef MAPNIK_DEBUG
        //wall_clock_progress_timer timer(clog, "end layer rendering: ");
#endif
        p.start_layer_processing(lay);
        boost::shared_ptr<datasource> ds=lay.datasource();
        if (ds)
        {
            box2d<double> ext = m_.get_buffered_extent();
            projection proj1(lay.srs());
            proj_transform prj_trans(proj0,proj1);

            box2d<double> layer_ext = lay.envelope();

            double lx0 = layer_ext.minx();
            double ly0 = layer_ext.miny();
            double lz0 = 0.0;
            double lx1 = layer_ext.maxx();
            double ly1 = layer_ext.maxy();
            double lz1 = 0.0;
            // back project layers extent into main map projection
            prj_trans.backward(lx0,ly0,lz0);
            prj_trans.backward(lx1,ly1,lz1);

            // if no intersection then nothing to do for layer
            if ( lx0 > ext.maxx() || lx1 < ext.minx() || ly0 > ext.maxy() || ly1 < ext.miny() )
            {
                return;
            }

            // clip query bbox
            lx0 = std::max(ext.minx(),lx0);
            ly0 = std::max(ext.miny(),ly0);
            lx1 = std::min(ext.maxx(),lx1);
            ly1 = std::min(ext.maxy(),ly1);

            prj_trans.forward(lx0,ly0,lz0);
            prj_trans.forward(lx1,ly1,lz1);
            box2d<double> bbox(lx0,ly0,lx1,ly1);

            query::resolution_type res(m_.getWidth()/m_.getCurrentExtent().width(),m_.getHeight()/m_.getCurrentExtent().height());
            query q(bbox,res,scale_denom); //BBOX query

            std::vector<std::string> const& style_names = lay.styles();
            std::vector<std::string>::const_iterator stylesIter = style_names.begin();
            std::vector<std::string>::const_iterator stylesEnd = style_names.end();
            for (;stylesIter != stylesEnd; ++stylesIter)
            {
                std::set<std::string> names;
                attribute_collector collector(names);
                std::vector<rule_type*> if_rules;
                std::vector<rule_type*> else_rules;

                bool active_rules=false;

                boost::optional<feature_type_style const&> style=m_.find_style(*stylesIter);
                if (!style) continue;

                const std::vector<rule_type>& rules=(*style).get_rules();
                std::vector<rule_type>::const_iterator ruleIter=rules.begin();
                std::vector<rule_type>::const_iterator ruleEnd=rules.end();

                for (;ruleIter!=ruleEnd;++ruleIter)
                {
                    if (ruleIter->active(scale_denom))
                    {
                        active_rules=true;
                        // collect unique attribute names
                        collector(*ruleIter);
                        if (ruleIter->has_else_filter())
                        {
                            else_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                        else
                        {
                            if_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                    }
                }
                std::set<std::string>::const_iterator namesIter=names.begin();
                std::set<std::string>::const_iterator namesEnd =names.end();

                // push all property names
                for (;namesIter!=namesEnd;++namesIter)
                {
                    q.add_property_name(*namesIter);
                }
                if (active_rules)
                {
                    featureset_ptr fs=ds->features(q);
                    if (fs)
                    {
                        feature_ptr feature;
                        while ((feature = fs->next()))
                        {
                            bool do_else=true;
                            std::vector<rule_type*>::const_iterator itr=if_rules.begin();
                            std::vector<rule_type*>::const_iterator end=if_rules.end();
                            for (;itr != end;++itr)
                            {
                                expression_ptr const& expr=(*itr)->get_filter();
                                value_type result = boost::apply_visitor(evaluate<Feature,value_type>(*feature),*expr);
                                if (result.to_bool())
                                {
                                    do_else=false;
                                    const rule_type::symbolizers& symbols = (*itr)->get_symbolizers();
                                    rule_type::symbolizers::const_iterator symIter=symbols.begin();
                                    rule_type::symbolizers::const_iterator symEnd =symbols.end();
                                    for (;symIter != symEnd;++symIter)
                                    {
                                        boost::apply_visitor
                                            (symbol_dispatch(p,*feature,prj_trans),*symIter);
                                    }
                                }
                            }
                            if (do_else)
                            {
                                //else filter
                                std::vector<rule_type*>::const_iterator itr=
                                    else_rules.begin();
                                std::vector<rule_type*>::const_iterator end=
                                    else_rules.end();
                                for (;itr != end;++itr)
                                {
                                    const rule_type::symbolizers& symbols = (*itr)->get_symbolizers();
                                    rule_type::symbolizers::const_iterator symIter= symbols.begin();
                                    rule_type::symbolizers::const_iterator symEnd = symbols.end();

                                    for (;symIter!=symEnd;++symIter)
                                    {
                                        boost::apply_visitor
                                            (symbol_dispatch(p,*feature,prj_trans),*symIter);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        p.end_layer_processing(lay);
    }
    Map const& m_;
};
}

#endif //FEATURE_STYLE_PROCESSOR_HPP
<commit_msg>Output a warning if a style is not found.<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * 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
 *
 *****************************************************************************/

//$Id$

#ifndef FEATURE_STYLE_PROCESSOR_HPP
#define FEATURE_STYLE_PROCESSOR_HPP

// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>

#ifdef MAPNIK_DEBUG
//#include <mapnik/wall_clock_timer.hpp>
#endif
//stl
#include <vector>

namespace mapnik
{
template <typename Processor>
class feature_style_processor
{
    struct symbol_dispatch : public boost::static_visitor<>
    {
        symbol_dispatch (Processor & output,
                         Feature const& f,
                         proj_transform const& prj_trans)
            : output_(output),
              f_(f),
              prj_trans_(prj_trans)  {}

        template <typename T>
        void operator () (T const& sym) const
        {
            output_.process(sym,f_,prj_trans_);
        }

        Processor & output_;
        Feature const& f_;
        proj_transform const& prj_trans_;
    };
public:
    feature_style_processor(Map const& m)
        : m_(m) {}

    void apply()
    {
#ifdef MAPNIK_DEBUG
        //mapnik::wall_clock_progress_timer t(std::clog, "map rendering took: ");
#endif
        Processor & p = static_cast<Processor&>(*this);
        p.start_map_processing(m_);

        try
        {
            projection proj(m_.srs()); // map projection
            double scale_denom = mapnik::scale_denominator(m_,proj.is_geographic());
#ifdef MAPNIK_DEBUG
            std::clog << "scale denominator = " << scale_denom << "\n";
#endif
            std::vector<layer>::const_iterator itr = m_.layers().begin();
            std::vector<layer>::const_iterator end = m_.layers().end();

            while (itr != end)
            {
                if (itr->isVisible(scale_denom))
                {
                    apply_to_layer(*itr, p, proj, scale_denom);
                }
                ++itr;
            }
        }
        catch (proj_init_error& ex)
        {
            std::clog << "proj_init_error:" << ex.what() << "\n";
        }

        p.end_map_processing(m_);
    }
private:
    void apply_to_layer(layer const& lay, Processor & p,
                        projection const& proj0,double scale_denom)
    {
#ifdef MAPNIK_DEBUG
        //wall_clock_progress_timer timer(clog, "end layer rendering: ");
#endif
        p.start_layer_processing(lay);
        boost::shared_ptr<datasource> ds=lay.datasource();
        if (ds)
        {
            box2d<double> ext = m_.get_buffered_extent();
            projection proj1(lay.srs());
            proj_transform prj_trans(proj0,proj1);

            box2d<double> layer_ext = lay.envelope();

            double lx0 = layer_ext.minx();
            double ly0 = layer_ext.miny();
            double lz0 = 0.0;
            double lx1 = layer_ext.maxx();
            double ly1 = layer_ext.maxy();
            double lz1 = 0.0;
            // back project layers extent into main map projection
            prj_trans.backward(lx0,ly0,lz0);
            prj_trans.backward(lx1,ly1,lz1);

            // if no intersection then nothing to do for layer
            if ( lx0 > ext.maxx() || lx1 < ext.minx() || ly0 > ext.maxy() || ly1 < ext.miny() )
            {
                return;
            }

            // clip query bbox
            lx0 = std::max(ext.minx(),lx0);
            ly0 = std::max(ext.miny(),ly0);
            lx1 = std::min(ext.maxx(),lx1);
            ly1 = std::min(ext.maxy(),ly1);

            prj_trans.forward(lx0,ly0,lz0);
            prj_trans.forward(lx1,ly1,lz1);
            box2d<double> bbox(lx0,ly0,lx1,ly1);

            query::resolution_type res(m_.getWidth()/m_.getCurrentExtent().width(),m_.getHeight()/m_.getCurrentExtent().height());
            query q(bbox,res,scale_denom); //BBOX query

            std::vector<std::string> const& style_names = lay.styles();
            std::vector<std::string>::const_iterator stylesIter = style_names.begin();
            std::vector<std::string>::const_iterator stylesEnd = style_names.end();
            for (;stylesIter != stylesEnd; ++stylesIter)
            {
                std::set<std::string> names;
                attribute_collector collector(names);
                std::vector<rule_type*> if_rules;
                std::vector<rule_type*> else_rules;

                bool active_rules=false;

                boost::optional<feature_type_style const&> style=m_.find_style(*stylesIter);
                if (!style) {
                    std::clog << "WARNING: style '" << *stylesIter << "' required for layer '" << lay.name() << "' does not exist.\n";
                    continue;
                }

                const std::vector<rule_type>& rules=(*style).get_rules();
                std::vector<rule_type>::const_iterator ruleIter=rules.begin();
                std::vector<rule_type>::const_iterator ruleEnd=rules.end();

                for (;ruleIter!=ruleEnd;++ruleIter)
                {
                    if (ruleIter->active(scale_denom))
                    {
                        active_rules=true;
                        // collect unique attribute names
                        collector(*ruleIter);
                        if (ruleIter->has_else_filter())
                        {
                            else_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                        else
                        {
                            if_rules.push_back(const_cast<rule_type*>(&(*ruleIter)));
                        }
                    }
                }
                std::set<std::string>::const_iterator namesIter=names.begin();
                std::set<std::string>::const_iterator namesEnd =names.end();

                // push all property names
                for (;namesIter!=namesEnd;++namesIter)
                {
                    q.add_property_name(*namesIter);
                }
                if (active_rules)
                {
                    featureset_ptr fs=ds->features(q);
                    if (fs)
                    {
                        feature_ptr feature;
                        while ((feature = fs->next()))
                        {
                            bool do_else=true;
                            std::vector<rule_type*>::const_iterator itr=if_rules.begin();
                            std::vector<rule_type*>::const_iterator end=if_rules.end();
                            for (;itr != end;++itr)
                            {
                                expression_ptr const& expr=(*itr)->get_filter();
                                value_type result = boost::apply_visitor(evaluate<Feature,value_type>(*feature),*expr);
                                if (result.to_bool())
                                {
                                    do_else=false;
                                    const rule_type::symbolizers& symbols = (*itr)->get_symbolizers();
                                    rule_type::symbolizers::const_iterator symIter=symbols.begin();
                                    rule_type::symbolizers::const_iterator symEnd =symbols.end();
                                    for (;symIter != symEnd;++symIter)
                                    {
                                        boost::apply_visitor
                                            (symbol_dispatch(p,*feature,prj_trans),*symIter);
                                    }
                                }
                            }
                            if (do_else)
                            {
                                //else filter
                                std::vector<rule_type*>::const_iterator itr=
                                    else_rules.begin();
                                std::vector<rule_type*>::const_iterator end=
                                    else_rules.end();
                                for (;itr != end;++itr)
                                {
                                    const rule_type::symbolizers& symbols = (*itr)->get_symbolizers();
                                    rule_type::symbolizers::const_iterator symIter= symbols.begin();
                                    rule_type::symbolizers::const_iterator symEnd = symbols.end();

                                    for (;symIter!=symEnd;++symIter)
                                    {
                                        boost::apply_visitor
                                            (symbol_dispatch(p,*feature,prj_trans),*symIter);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        p.end_layer_processing(lay);
    }
    Map const& m_;
};
}

#endif //FEATURE_STYLE_PROCESSOR_HPP
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2015, John Haddon. 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 Image Engine Design nor the names of any
//       other contributors to this software 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.
//
//////////////////////////////////////////////////////////////////////////

#include "openvdb/openvdb.h"

#include "IECore/SceneInterface.h"
#include "IECore/SimpleTypedData.h"
#include "GafferVDB/TypeIds.h"
#include "GafferVDB/VDBObject.h"

#include "GafferScene/ScenePlug.h"

using namespace Imath;
using namespace IECore;
using namespace GafferVDB;

using namespace openvdb;
namespace
{

const SceneInterface::Name g_objectName("vdb");

class VDBScene : public SceneInterface
{

	public :

		IE_CORE_DECLARERUNTIMETYPEDEXTENSION( VDBScene, VDBSceneTypeId, IECore::SceneInterface );

		VDBScene( const std::string &fileName, IndexedIO::OpenMode openMode )
		: SceneInterface(),
			m_rootData( new RootData(fileName) )

		{
		}

		~VDBScene() override
		{
		}

		std::string fileName() const override
		{
			return rootData().m_fileName;
		}

		Name name() const override
		{
			if ( m_parent )
			{
				return g_objectName;
			}
			else
			{
				return Name();
			}

		}

		void path( Path &p ) const override
		{

			if ( m_parent )
			{
				p = { g_objectName };
			}
			else
			{
				p = {};
			}
		}

		////////////////////////////////////////////////////
		// Bounds
		////////////////////////////////////////////////////

		Imath::Box3d readBound( double time ) const override
		{
			const Imath::Box3f bound = rootData().m_vdbObject->bound();
			return Imath::Box3d(bound.min, bound.max);
		}

		 void writeBound( const Imath::Box3d &bound, double time ) override
		 {
			 throw IECore::NotImplementedException("");
		 }

		////////////////////////////////////////////////////
		// Transforms
		////////////////////////////////////////////////////

		ConstDataPtr readTransform( double time ) const override
		{
			return new M44dData;
		}

		Imath::M44d readTransformAsMatrix( double time ) const override
		{
			return M44d();
		}

		void writeTransform( const Data *transform, double time ) override
		{
			throw IECore::NotImplementedException("");
		}

		////////////////////////////////////////////////////
		// Attributes
		////////////////////////////////////////////////////

		bool hasAttribute( const Name &name ) const override
		{
			return false;
		}

		/// Fills attrs with the names of all attributes available in the current directory
		void attributeNames( NameList &attrs ) const override
		{
			attrs = {};
		}

		ConstObjectPtr readAttribute( const Name &name, double time ) const override
		{
			return nullptr;
		}

		void writeAttribute( const Name &name, const Object *attribute, double time ) override
		{
			throw IECore::NotImplementedException("");
		}

		////////////////////////////////////////////////////
		// Tags
		////////////////////////////////////////////////////

		bool hasTag( const Name &name, int filter = LocalTag ) const override
		{
			return false;
		}

		void readTags( NameList &tags, int filter = LocalTag ) const override
		{
			tags = {};
		}

		void writeTags( const NameList &tags ) override
		{
			throw IECore::NotImplementedException("");
		}

		////////////////////////////////////////////////////
		// Objects
		////////////////////////////////////////////////////

		bool hasObject() const override
		{
			return true;
		}

		ConstObjectPtr readObject( double time ) const override
		{
			if ( m_parent )
			{
				return rootData().m_vdbObject;
			}
			else
			{
				return nullptr;
			}

		}

		PrimitiveVariableMap readObjectPrimitiveVariables( const std::vector<InternedString> &primVarNames, double time ) const override
		{
			return PrimitiveVariableMap();
		}

		void writeObject( const Object *object, double time ) override
		{
			throw IECore::NotImplementedException("");
		}

		////////////////////////////////////////////////////
		// Hierarchy
		////////////////////////////////////////////////////

		/// Convenience method to determine if a child exists
		bool hasChild( const Name &name ) const override
		{
			if ( !m_parent && name == g_objectName)
			{
				return true;
			}

			return false;
		}
		/// Queries the names of any existing children of path() within
		/// the scene.
		void childNames( NameList &childNames ) const override
		{
			if ( m_parent )
			{
				childNames = NameList();
			}
			else
			{
				childNames = { g_objectName };
			}

		}
		/// Returns an object for the specified child location in the scene.
		/// If the child does not exist then it will behave according to the
		/// missingBehavior parameter. May throw and exception, may return a NULL pointer,
		/// or may create the child (if that is possible).
		/// Bounding boxes will be automatically propagated up from the children
		/// to the parent as it is written.
		SceneInterfacePtr child( const Name &name, MissingBehaviour missingBehaviour = ThrowIfMissing ) override
		{
			if ( m_parent )
			{
				if (missingBehaviour == ThrowIfMissing)
				{
					throw IECore::InvalidArgumentException("VDBSCene::child(): no child called \" + name.string()");
				}
				else if (missingBehaviour == CreateIfMissing)
				{
					throw IECore::InvalidArgumentException("VDBScene::child(): CreateIfMissing not supported");
				}
				return nullptr;
			}
			else
			{
				if (name == g_objectName)
				{
					return new VDBScene(this);
				}
				else if (missingBehaviour == ThrowIfMissing)
				{
					throw IECore::InvalidArgumentException("VDBSCene::child(): no child called \" + name.string()");
				}
				else if (missingBehaviour == CreateIfMissing)
				{
					throw IECore::InvalidArgumentException("VDBScene::child(): CreateIfMissing not supported");
				}
			}

			return SceneInterfacePtr();
		}

		/// Returns a read-only interface for a child location in the scene.
		ConstSceneInterfacePtr child( const Name &name, MissingBehaviour missingBehaviour = ThrowIfMissing ) const override
		{
			return const_cast< VDBScene* >( this )->child( name, missingBehaviour );
		}

		/// Returns a writable interface to a new child. Throws an exception if it already exists.
		/// Bounding boxes will be automatically propagated up from the children
		/// to the parent as it is written.
		SceneInterfacePtr createChild( const Name &name ) override
		{
			throw IECore::NotImplementedException("");
		}

		/// Returns a interface for querying the scene at the given path (full path).
		SceneInterfacePtr scene( const Path &path, MissingBehaviour missingBehaviour = ThrowIfMissing ) override
		{
			if ( path.empty() )
			{
				if ( m_parent )
				{
					return m_parent;
				}
				else
				{
					return this;
				}
			}
			else if ( path.size() == 1 && path[0] == g_objectName )
			{
				if ( m_parent )
				{
					return this;
				}
				else
				{
					return new VDBScene( this );
				}
			}
			else
			{
				if (missingBehaviour == ThrowIfMissing)
				{
					std::string pathStr;
					GafferScene::ScenePlug::pathToString(path, pathStr);
					bool isRoot = (m_parent != nullptr);
					if ( isRoot )
					{
						throw IECore::InvalidArgumentException("VDBSCene::scene(): no path called '" + pathStr + "' is root!" );
					}
					else
					{
						throw IECore::InvalidArgumentException("VDBSCene::scene(): no path called '" + pathStr + "'");
					}

				}
				else if (missingBehaviour == CreateIfMissing)
				{
					throw IECore::NotImplementedException("VDBScene::scene(): CreateIfMissing not supported");
				}
				return nullptr;
			}
		}

		/// Returns a const interface for querying the scene at the given path (full path).
		ConstSceneInterfacePtr scene( const Path &path, MissingBehaviour missingBehaviour = ThrowIfMissing ) const override
		{
			return const_cast< VDBScene* >( this )->scene( path, missingBehaviour );
		}

		////////////////////////////////////////////////////
		// Hash
		////////////////////////////////////////////////////

		void hash( HashType hashType, double time, MurmurHash &h ) const override
		{
			SceneInterface::hash (hashType, time, h);
			h.append( hashType );

			if ( hashType == ChildNamesHash )
			{
				h.append( m_parent == nullptr );
			}
			else if ( hashType == ObjectHash || hashType == BoundHash)
			{
				h.append( rootData().m_fileName );
				h.append( m_parent == nullptr );
			}
			else if ( hashType == HierarchyHash )
			{
				h.append( m_parent == nullptr );
			}
		}

	private :

		VDBScene( VDBScene* parent )
		: m_parent( parent )
		{
		}

		static FileFormatDescription<VDBScene> g_description;

		struct RootData
		{
			RootData(const std::string& filename)
			: m_fileName(filename),
			  m_vdbObject(new VDBObject(m_fileName) )
			{
			}

			std::string m_fileName;
			VDBObject::Ptr m_vdbObject;
		};

		RootData &rootData() const
		{
			if ( m_parent )
				return m_parent->rootData();
			else
				return *m_rootData;
		}

		std::shared_ptr<RootData> m_rootData;
		Ptr m_parent;

};

IE_CORE_DEFINERUNTIMETYPED( VDBScene )

SceneInterface::FileFormatDescription<VDBScene> VDBScene::g_description(".vdb", IndexedIO::Read );

} // namespace
<commit_msg>VDBScene : remove duplicate logic<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2015, John Haddon. 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 Image Engine Design nor the names of any
//       other contributors to this software 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.
//
//////////////////////////////////////////////////////////////////////////

#include "openvdb/openvdb.h"

#include "IECore/SceneInterface.h"
#include "IECore/SimpleTypedData.h"
#include "GafferVDB/TypeIds.h"
#include "GafferVDB/VDBObject.h"

#include "GafferScene/ScenePlug.h"

using namespace Imath;
using namespace IECore;
using namespace GafferVDB;

using namespace openvdb;
namespace
{

const SceneInterface::Name g_objectName("vdb");

class VDBScene : public SceneInterface
{

	public :

		IE_CORE_DECLARERUNTIMETYPEDEXTENSION( VDBScene, VDBSceneTypeId, IECore::SceneInterface );

		VDBScene( const std::string &fileName, IndexedIO::OpenMode openMode )
		: SceneInterface(),
			m_rootData( new RootData(fileName) )

		{
		}

		~VDBScene() override
		{
		}

		std::string fileName() const override
		{
			return rootData().m_fileName;
		}

		Name name() const override
		{
			if ( m_parent )
			{
				return g_objectName;
			}
			else
			{
				return Name();
			}

		}

		void path( Path &p ) const override
		{

			if ( m_parent )
			{
				p = { g_objectName };
			}
			else
			{
				p = {};
			}
		}

		////////////////////////////////////////////////////
		// Bounds
		////////////////////////////////////////////////////

		Imath::Box3d readBound( double time ) const override
		{
			const Imath::Box3f bound = rootData().m_vdbObject->bound();
			return Imath::Box3d(bound.min, bound.max);
		}

		 void writeBound( const Imath::Box3d &bound, double time ) override
		 {
			 throw IECore::NotImplementedException("");
		 }

		////////////////////////////////////////////////////
		// Transforms
		////////////////////////////////////////////////////

		ConstDataPtr readTransform( double time ) const override
		{
			return new M44dData;
		}

		Imath::M44d readTransformAsMatrix( double time ) const override
		{
			return M44d();
		}

		void writeTransform( const Data *transform, double time ) override
		{
			throw IECore::NotImplementedException("");
		}

		////////////////////////////////////////////////////
		// Attributes
		////////////////////////////////////////////////////

		bool hasAttribute( const Name &name ) const override
		{
			return false;
		}

		/// Fills attrs with the names of all attributes available in the current directory
		void attributeNames( NameList &attrs ) const override
		{
			attrs = {};
		}

		ConstObjectPtr readAttribute( const Name &name, double time ) const override
		{
			return nullptr;
		}

		void writeAttribute( const Name &name, const Object *attribute, double time ) override
		{
			throw IECore::NotImplementedException("");
		}

		////////////////////////////////////////////////////
		// Tags
		////////////////////////////////////////////////////

		bool hasTag( const Name &name, int filter = LocalTag ) const override
		{
			return false;
		}

		void readTags( NameList &tags, int filter = LocalTag ) const override
		{
			tags = {};
		}

		void writeTags( const NameList &tags ) override
		{
			throw IECore::NotImplementedException("");
		}

		////////////////////////////////////////////////////
		// Objects
		////////////////////////////////////////////////////

		bool hasObject() const override
		{
			return true;
		}

		ConstObjectPtr readObject( double time ) const override
		{
			if ( m_parent )
			{
				return rootData().m_vdbObject;
			}
			else
			{
				return nullptr;
			}

		}

		PrimitiveVariableMap readObjectPrimitiveVariables( const std::vector<InternedString> &primVarNames, double time ) const override
		{
			return PrimitiveVariableMap();
		}

		void writeObject( const Object *object, double time ) override
		{
			throw IECore::NotImplementedException("");
		}

		////////////////////////////////////////////////////
		// Hierarchy
		////////////////////////////////////////////////////

		/// Convenience method to determine if a child exists
		bool hasChild( const Name &name ) const override
		{
			if ( !m_parent && name == g_objectName)
			{
				return true;
			}

			return false;
		}
		/// Queries the names of any existing children of path() within
		/// the scene.
		void childNames( NameList &childNames ) const override
		{
			if ( m_parent )
			{
				childNames = NameList();
			}
			else
			{
				childNames = { g_objectName };
			}

		}
		/// Returns an object for the specified child location in the scene.
		/// If the child does not exist then it will behave according to the
		/// missingBehavior parameter. May throw and exception, may return a NULL pointer,
		/// or may create the child (if that is possible).
		/// Bounding boxes will be automatically propagated up from the children
		/// to the parent as it is written.
		SceneInterfacePtr child( const Name &name, MissingBehaviour missingBehaviour = ThrowIfMissing ) override
		{
			if ( !m_parent && name == g_objectName)
			{
				return new VDBScene( this );
			}
			else if (missingBehaviour == ThrowIfMissing)
			{
				throw IECore::InvalidArgumentException("VDBSCene::child(): no child called \" + name.string()");
			}
			else if (missingBehaviour == CreateIfMissing)
			{
				throw IECore::InvalidArgumentException("VDBScene::child(): CreateIfMissing not supported");
			}

			return nullptr;
		}

		/// Returns a read-only interface for a child location in the scene.
		ConstSceneInterfacePtr child( const Name &name, MissingBehaviour missingBehaviour = ThrowIfMissing ) const override
		{
			return const_cast< VDBScene* >( this )->child( name, missingBehaviour );
		}

		/// Returns a writable interface to a new child. Throws an exception if it already exists.
		/// Bounding boxes will be automatically propagated up from the children
		/// to the parent as it is written.
		SceneInterfacePtr createChild( const Name &name ) override
		{
			throw IECore::NotImplementedException("");
		}

		/// Returns a interface for querying the scene at the given path (full path).
		SceneInterfacePtr scene( const Path &path, MissingBehaviour missingBehaviour = ThrowIfMissing ) override
		{
			if ( path.empty() )
			{
				if ( m_parent )
				{
					return m_parent;
				}
				else
				{
					return this;
				}
			}
			else if ( path.size() == 1 && path[0] == g_objectName )
			{
				if ( m_parent )
				{
					return this;
				}
				else
				{
					return new VDBScene( this );
				}
			}
			else
			{
				if (missingBehaviour == ThrowIfMissing)
				{
					std::string pathStr;
					GafferScene::ScenePlug::pathToString(path, pathStr);
					bool isRoot = (m_parent != nullptr);
					if ( isRoot )
					{
						throw IECore::InvalidArgumentException("VDBSCene::scene(): no path called '" + pathStr + "' is root!" );
					}
					else
					{
						throw IECore::InvalidArgumentException("VDBSCene::scene(): no path called '" + pathStr + "'");
					}

				}
				else if (missingBehaviour == CreateIfMissing)
				{
					throw IECore::NotImplementedException("VDBScene::scene(): CreateIfMissing not supported");
				}
				return nullptr;
			}
		}

		/// Returns a const interface for querying the scene at the given path (full path).
		ConstSceneInterfacePtr scene( const Path &path, MissingBehaviour missingBehaviour = ThrowIfMissing ) const override
		{
			return const_cast< VDBScene* >( this )->scene( path, missingBehaviour );
		}

		////////////////////////////////////////////////////
		// Hash
		////////////////////////////////////////////////////

		void hash( HashType hashType, double time, MurmurHash &h ) const override
		{
			SceneInterface::hash (hashType, time, h);
			h.append( hashType );

			if ( hashType == ChildNamesHash )
			{
				h.append( m_parent == nullptr );
			}
			else if ( hashType == ObjectHash || hashType == BoundHash)
			{
				h.append( rootData().m_fileName );
				h.append( m_parent == nullptr );
			}
			else if ( hashType == HierarchyHash )
			{
				h.append( m_parent == nullptr );
			}
		}

	private :

		VDBScene( VDBScene* parent )
		: m_parent( parent )
		{
		}

		static FileFormatDescription<VDBScene> g_description;

		struct RootData
		{
			RootData(const std::string& filename)
			: m_fileName(filename),
			  m_vdbObject(new VDBObject(m_fileName) )
			{
			}

			std::string m_fileName;
			VDBObject::Ptr m_vdbObject;
		};

		RootData &rootData() const
		{
			if ( m_parent )
				return m_parent->rootData();
			else
				return *m_rootData;
		}

		std::shared_ptr<RootData> m_rootData;
		Ptr m_parent;

};

IE_CORE_DEFINERUNTIMETYPED( VDBScene )

SceneInterface::FileFormatDescription<VDBScene> VDBScene::g_description(".vdb", IndexedIO::Read );

} // namespace
<|endoftext|>


<commit_before>//
//  language_primary.cpp
//  TameParse
//
//  Created by Andrew Hunter on 10/09/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <string>
#include <sstream>

#include "Language/bootstrap.h"

#include "language_primary.h"
#include "tameparse_language.h"

using namespace std;
using namespace dfa;
using namespace lr;
using namespace language;

// Checks that a given phrase is lexed as the specified symbol
static bool test_lex(string phrase, const lexer& lex, int expectedSymbol) {
    // Create a lexeme stream
    stringstream source(phrase);
    lexeme_stream* lxs = lex.create_stream_from(source);

    // Get the next lexeme
    lexeme* match;
    (*lxs) >> match;

    bool result = true;
    if (match->content().size() != phrase.size()) {
        for (int x=0; x<match->content().size(); x++) {
            cerr << (char)match->content()[x];
        }
        cerr << endl;
        result = false;
    }
    if (match->matched() != expectedSymbol) {
        cerr << match->matched() << endl;
        result = false;
    }

    // Finished with the stream
    delete match;
    delete lxs;

    return result;
}

void test_language_primary::run_tests() {
	// Test that the lexer can match some particular symbols
    report("MatchIdentifier1", test_lex("fdsu", tameparse_language::lexer, tameparse_language::t::identifier));
    report("MatchIdentifier2", test_lex("some-identifier", tameparse_language::lexer, tameparse_language::t::identifier));
    report("MatchIdentifier3", test_lex("id128", tameparse_language::lexer, tameparse_language::t::identifier));
    report("MatchIdentifier4", test_lex("identifier", tameparse_language::lexer, tameparse_language::t::identifier));
    report("MatchNonterminal1", test_lex("<nonterminal>", tameparse_language::lexer, tameparse_language::t::nonterminal));
    report("MatchRegex1", test_lex("/regex/", tameparse_language::lexer, tameparse_language::t::regex));
    report("MatchString1", test_lex("\"string\"", tameparse_language::lexer, tameparse_language::t::string));
    report("MatchCharacter1", test_lex("'c'", tameparse_language::lexer, tameparse_language::t::character));
    report("MatchCharacter2", test_lex("'\\n'", tameparse_language::lexer, tameparse_language::t::character));

    report("MatchLanguage", test_lex("language", tameparse_language::lexer, tameparse_language::t::language));
    report("MatchGrammar", test_lex("grammar", tameparse_language::lexer, tameparse_language::t::grammar));
    report("MatchLexer", test_lex("lexer", tameparse_language::lexer, tameparse_language::t::lexer));
    report("MatchLexerSymbols", test_lex("lexer-symbols", tameparse_language::lexer, tameparse_language::t::lexer_symbols));
    report("MatchWeak", test_lex("weak", tameparse_language::lexer, tameparse_language::t::weak));
    report("MatchIgnore", test_lex("ignore", tameparse_language::lexer, tameparse_language::t::ignore));
    report("MatchKeywords", test_lex("keywords", tameparse_language::lexer, tameparse_language::t::keywords));
    report("MatchWhitespace", test_lex("  ", tameparse_language::lexer, tameparse_language::t::whitespace));
    report("MatchNewline", test_lex("\n", tameparse_language::lexer, tameparse_language::t::newline));
    report("MatchComment1", test_lex("// Comment", tameparse_language::lexer, tameparse_language::t::comment));
    report("MatchComment2", test_lex("///", tameparse_language::lexer, tameparse_language::t::comment));

    // Create a lexer for the language definition
    bootstrap bs;
    stringstream bootstrapDefinition(bootstrap::get_default_language_definition());

    lexeme_stream* defaultStream = tameparse_language::lexer.create_stream_from(bootstrapDefinition);

    // Create a parser for it
#if 0
    typedef parser<int, simple_parser_actions, debug_parser_trace<2> > debug_parser;

    debug_parser parser(tameparse_language::lr_tables);
    debug_parser::state* defParser = parser.create_parser(new simple_parser_actions(defaultStream));
#else
    simple_parser::state* defParser = tameparse_language::simple_parser.create_parser(new simple_parser_actions(defaultStream));
#endif

    // Try parsing the language
    bool acceptedDefault = defParser->parse();

    report("CanParseLanguageDefinition", acceptedDefault);
}
<commit_msg>Comment as just '//' is ambiguous with a regular expression, and the compiler prefers the regex form. This is fixed by making a regex be non-empty. Added a test for this specific condition.<commit_after>//
//  language_primary.cpp
//  TameParse
//
//  Created by Andrew Hunter on 10/09/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include <string>
#include <sstream>

#include "Language/bootstrap.h"

#include "language_primary.h"
#include "tameparse_language.h"

using namespace std;
using namespace dfa;
using namespace lr;
using namespace language;

// Checks that a given phrase is lexed as the specified symbol
static bool test_lex(string phrase, const lexer& lex, int expectedSymbol) {
    // Create a lexeme stream
    stringstream source(phrase);
    lexeme_stream* lxs = lex.create_stream_from(source);

    // Get the next lexeme
    lexeme* match;
    (*lxs) >> match;

    bool result = true;
    if (match->content().size() != phrase.size()) {
        for (int x=0; x<match->content().size(); x++) {
            cerr << (char)match->content()[x];
        }
        cerr << endl;
        result = false;
    }
    if (match->matched() != expectedSymbol) {
        cerr << match->matched() << endl;
        result = false;
    }

    // Finished with the stream
    delete match;
    delete lxs;

    return result;
}

void test_language_primary::run_tests() {
	// Test that the lexer can match some particular symbols
    report("MatchIdentifier1", test_lex("fdsu", tameparse_language::lexer, tameparse_language::t::identifier));
    report("MatchIdentifier2", test_lex("some-identifier", tameparse_language::lexer, tameparse_language::t::identifier));
    report("MatchIdentifier3", test_lex("id128", tameparse_language::lexer, tameparse_language::t::identifier));
    report("MatchIdentifier4", test_lex("identifier", tameparse_language::lexer, tameparse_language::t::identifier));
    report("MatchNonterminal1", test_lex("<nonterminal>", tameparse_language::lexer, tameparse_language::t::nonterminal));
    report("MatchRegex1", test_lex("/regex/", tameparse_language::lexer, tameparse_language::t::regex));
    report("MatchString1", test_lex("\"string\"", tameparse_language::lexer, tameparse_language::t::string));
    report("MatchCharacter1", test_lex("'c'", tameparse_language::lexer, tameparse_language::t::character));
    report("MatchCharacter2", test_lex("'\\n'", tameparse_language::lexer, tameparse_language::t::character));

    report("MatchLanguage", test_lex("language", tameparse_language::lexer, tameparse_language::t::language));
    report("MatchGrammar", test_lex("grammar", tameparse_language::lexer, tameparse_language::t::grammar));
    report("MatchLexer", test_lex("lexer", tameparse_language::lexer, tameparse_language::t::lexer));
    report("MatchLexerSymbols", test_lex("lexer-symbols", tameparse_language::lexer, tameparse_language::t::lexer_symbols));
    report("MatchWeak", test_lex("weak", tameparse_language::lexer, tameparse_language::t::weak));
    report("MatchIgnore", test_lex("ignore", tameparse_language::lexer, tameparse_language::t::ignore));
    report("MatchKeywords", test_lex("keywords", tameparse_language::lexer, tameparse_language::t::keywords));
    report("MatchWhitespace", test_lex("  ", tameparse_language::lexer, tameparse_language::t::whitespace));
    report("MatchNewline", test_lex("\n", tameparse_language::lexer, tameparse_language::t::newline));
    report("MatchComment1", test_lex("// Comment", tameparse_language::lexer, tameparse_language::t::comment));
    report("MatchComment2", test_lex("///", tameparse_language::lexer, tameparse_language::t::comment));
    report("MatchComment3", test_lex("//", tameparse_language::lexer, tameparse_language::t::comment));

    // Create a lexer for the language definition
    bootstrap bs;
    stringstream bootstrapDefinition(bootstrap::get_default_language_definition());

    lexeme_stream* defaultStream = tameparse_language::lexer.create_stream_from(bootstrapDefinition);

    // Create a parser for it
#if 0
    typedef parser<int, simple_parser_actions, debug_parser_trace<2> > debug_parser;

    debug_parser parser(tameparse_language::lr_tables);
    debug_parser::state* defParser = parser.create_parser(new simple_parser_actions(defaultStream));
#else
    simple_parser::state* defParser = tameparse_language::simple_parser.create_parser(new simple_parser_actions(defaultStream));
#endif

    // Try parsing the language
    bool acceptedDefault = defParser->parse();

    report("CanParseLanguageDefinition", acceptedDefault);
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm 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.
//
////////////////////////////////////////////////////////////////////////////

#include "sync_test_utils.hpp"

#include "sync/sync_manager.hpp"
#include "sync/sync_user.hpp"
#include <realm/util/logger.hpp>
#include <realm/util/scope_exit.hpp>

using namespace realm;
using namespace realm::util;
using File = realm::util::File;

static const std::string base_path = tmp_dir() + "/realm_objectstore_sync_manager/";

namespace {

bool validate_user_in_vector(std::vector<std::shared_ptr<SyncUser>> vector,
                             const std::string& identity,
                             const std::string& url,
                             const std::string& token) {
    for (auto& user : vector) {
        if (user->identity() == identity && user->server_url() == url && user->refresh_token() == token) {
            return true;
        }
    }
    return false;
}

}

TEST_CASE("sync_manager: basic property APIs") {
    auto cleanup = util::make_scope_exit([=]() noexcept { SyncManager::shared().reset_for_testing(); });
    reset_test_directory(base_path);
    SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoMetadata);

    SECTION("should work for log level") {
        SyncManager::shared().set_log_level(util::Logger::Level::info);
        REQUIRE(SyncManager::shared().log_level() == util::Logger::Level::info);
        SyncManager::shared().set_log_level(util::Logger::Level::error);
        REQUIRE(SyncManager::shared().log_level() == util::Logger::Level::error);
    }

    SECTION("should work for 'should reconnect immediately'") {
        SyncManager::shared().set_client_should_reconnect_immediately(true);
        REQUIRE(SyncManager::shared().client_should_reconnect_immediately());
        SyncManager::shared().set_client_should_reconnect_immediately(false);
        REQUIRE(!SyncManager::shared().client_should_reconnect_immediately());
    }

    SECTION("should work for 'should validate SSL'") {
        SyncManager::shared().set_client_should_validate_ssl(true);
        REQUIRE(SyncManager::shared().client_should_validate_ssl());
        SyncManager::shared().set_client_should_validate_ssl(false);
        REQUIRE(!SyncManager::shared().client_should_validate_ssl());
    }
}

TEST_CASE("sync_manager: `path_for_realm` API") {
    auto cleanup = util::make_scope_exit([=]() noexcept { SyncManager::shared().reset_for_testing(); });
    reset_test_directory(base_path);
    SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoMetadata);

    SECTION("should work properly") {
        const std::string identity = "foobarbaz";
        const std::string raw_url = "realms://foo.bar.example.com/realm/something/~/123456/xyz";
        const auto expected = base_path + "realm-object-server/foobarbaz/realms%3A%2F%2Ffoo.bar.example.com%2Frealm%2Fsomething%2F%7E%2F123456%2Fxyz";
        REQUIRE(SyncManager::shared().path_for_realm(identity, raw_url) == expected);
        // This API should also generate the directory if it doesn't already exist.
        REQUIRE_DIR_EXISTS(base_path + "realm-object-server/foobarbaz/");
    }
}

TEST_CASE("sync_manager: persistent user state management") {
    auto cleanup = util::make_scope_exit([=]() noexcept { SyncManager::shared().reset_for_testing(); });
    reset_test_directory(base_path);
    auto file_manager = SyncFileManager(base_path);
    // Open the metadata separately, so we can investigate it ourselves.
    SyncMetadataManager manager(file_manager.metadata_path(), false);

    const std::string url_1 = "https://example.realm.com/1/";
    const std::string url_2 = "https://example.realm.com/2/";
    const std::string url_3 = "https://example.realm.com/3/";
    const std::string token_1 = "foo_token";
    const std::string token_2 = "bar_token";
    const std::string token_3 = "baz_token";

    SECTION("when users are persisted") {
        const std::string identity_1 = "foo-1";
        const std::string identity_2 = "bar-1";
        const std::string identity_3 = "baz-1";
        // First, create a few users and add them to the metadata.
        auto u1 = SyncUserMetadata(manager, identity_1);
        u1.set_state(url_1, token_1);
        auto u2 = SyncUserMetadata(manager, identity_2);
        u2.set_state(url_2, token_2);
        auto u3 = SyncUserMetadata(manager, identity_3);
        u3.set_state(url_3, token_3);
        // The fourth user is an "invalid" user: no token, so shouldn't show up.
        auto u_invalid = SyncUserMetadata(manager, "invalid_user");
        REQUIRE(manager.all_unmarked_users().size() == 4);

        SECTION("they should be added to the active users list when metadata is enabled") {
            SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoEncryption);
            auto users = SyncManager::shared().all_users();
            REQUIRE(users.size() == 3);
            REQUIRE(validate_user_in_vector(users, identity_1, url_1, token_1));
            REQUIRE(validate_user_in_vector(users, identity_2, url_2, token_2));
            REQUIRE(validate_user_in_vector(users, identity_3, url_3, token_3));
        }
        SECTION("they should not be added to the active users list when metadata is disabled") {
            SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoMetadata);
            auto users = SyncManager::shared().all_users();
            REQUIRE(users.size() == 0);
        }
    }

    SECTION("when users are marked") {
        const std::string identity_1 = "foo-2";
        const std::string identity_2 = "bar-2";
        const std::string identity_3 = "baz-2";
        // Pre-populate the user directories.
        const auto user_dir_1 = file_manager.user_directory(identity_1);
        const auto user_dir_2 = file_manager.user_directory(identity_2);
        const auto user_dir_3 = file_manager.user_directory(identity_3);
        create_dummy_realm(user_dir_1 + "123456789");
        create_dummy_realm(user_dir_1 + "foo");
        create_dummy_realm(user_dir_2 + "123456789");
        create_dummy_realm(user_dir_3 + "foo");
        create_dummy_realm(user_dir_3 + "bar");
        create_dummy_realm(user_dir_3 + "baz");
        // Create the user metadata.
        auto u1 = SyncUserMetadata(manager, identity_1);
        u1.mark_for_removal();
        auto u2 = SyncUserMetadata(manager, identity_2);
        u2.mark_for_removal();
        // Don't mark this user for deletion.
        auto u3 = SyncUserMetadata(manager, identity_3);
        u3.set_state(url_3, token_3);

        SECTION("they should be cleaned up if metadata is enabled") {
            SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoEncryption);
            auto users = SyncManager::shared().all_users();
            REQUIRE(users.size() == 1);
            REQUIRE(validate_user_in_vector(users, identity_3, url_3, token_3));
            REQUIRE_DIR_DOES_NOT_EXIST(user_dir_1);
            REQUIRE_DIR_DOES_NOT_EXIST(user_dir_2);
            REQUIRE_DIR_EXISTS(user_dir_3);
        }
        SECTION("they should be left alone if metadata is disabled") {
            SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoMetadata);
            auto users = SyncManager::shared().all_users();
            REQUIRE_DIR_EXISTS(user_dir_1);
            REQUIRE_DIR_EXISTS(user_dir_2);
            REQUIRE_DIR_EXISTS(user_dir_3);
        }
    }
}

TEST_CASE("sync_manager: metadata") {
    auto cleanup = util::make_scope_exit([=]() noexcept { SyncManager::shared().reset_for_testing(); });
    reset_test_directory(base_path);

    SECTION("should be reset in case of decryption error") {
		SyncManager::shared().configure_file_system(base_path,
                                                    SyncManager::MetadataMode::Encryption,
                                                    make_test_encryption_key());

		SyncManager::shared().reset_for_testing();

		SyncManager::shared().configure_file_system(base_path,
                                                    SyncManager::MetadataMode::Encryption,
                                                    make_test_encryption_key(),
                                                    true);
    }
}
<commit_msg>fix indentation<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm 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.
//
////////////////////////////////////////////////////////////////////////////

#include "sync_test_utils.hpp"

#include "sync/sync_manager.hpp"
#include "sync/sync_user.hpp"
#include <realm/util/logger.hpp>
#include <realm/util/scope_exit.hpp>

using namespace realm;
using namespace realm::util;
using File = realm::util::File;

static const std::string base_path = tmp_dir() + "/realm_objectstore_sync_manager/";

namespace {

bool validate_user_in_vector(std::vector<std::shared_ptr<SyncUser>> vector,
                             const std::string& identity,
                             const std::string& url,
                             const std::string& token) {
    for (auto& user : vector) {
        if (user->identity() == identity && user->server_url() == url && user->refresh_token() == token) {
            return true;
        }
    }
    return false;
}

}

TEST_CASE("sync_manager: basic property APIs") {
    auto cleanup = util::make_scope_exit([=]() noexcept { SyncManager::shared().reset_for_testing(); });
    reset_test_directory(base_path);
    SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoMetadata);

    SECTION("should work for log level") {
        SyncManager::shared().set_log_level(util::Logger::Level::info);
        REQUIRE(SyncManager::shared().log_level() == util::Logger::Level::info);
        SyncManager::shared().set_log_level(util::Logger::Level::error);
        REQUIRE(SyncManager::shared().log_level() == util::Logger::Level::error);
    }

    SECTION("should work for 'should reconnect immediately'") {
        SyncManager::shared().set_client_should_reconnect_immediately(true);
        REQUIRE(SyncManager::shared().client_should_reconnect_immediately());
        SyncManager::shared().set_client_should_reconnect_immediately(false);
        REQUIRE(!SyncManager::shared().client_should_reconnect_immediately());
    }

    SECTION("should work for 'should validate SSL'") {
        SyncManager::shared().set_client_should_validate_ssl(true);
        REQUIRE(SyncManager::shared().client_should_validate_ssl());
        SyncManager::shared().set_client_should_validate_ssl(false);
        REQUIRE(!SyncManager::shared().client_should_validate_ssl());
    }
}

TEST_CASE("sync_manager: `path_for_realm` API") {
    auto cleanup = util::make_scope_exit([=]() noexcept { SyncManager::shared().reset_for_testing(); });
    reset_test_directory(base_path);
    SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoMetadata);

    SECTION("should work properly") {
        const std::string identity = "foobarbaz";
        const std::string raw_url = "realms://foo.bar.example.com/realm/something/~/123456/xyz";
        const auto expected = base_path + "realm-object-server/foobarbaz/realms%3A%2F%2Ffoo.bar.example.com%2Frealm%2Fsomething%2F%7E%2F123456%2Fxyz";
        REQUIRE(SyncManager::shared().path_for_realm(identity, raw_url) == expected);
        // This API should also generate the directory if it doesn't already exist.
        REQUIRE_DIR_EXISTS(base_path + "realm-object-server/foobarbaz/");
    }
}

TEST_CASE("sync_manager: persistent user state management") {
    auto cleanup = util::make_scope_exit([=]() noexcept { SyncManager::shared().reset_for_testing(); });
    reset_test_directory(base_path);
    auto file_manager = SyncFileManager(base_path);
    // Open the metadata separately, so we can investigate it ourselves.
    SyncMetadataManager manager(file_manager.metadata_path(), false);

    const std::string url_1 = "https://example.realm.com/1/";
    const std::string url_2 = "https://example.realm.com/2/";
    const std::string url_3 = "https://example.realm.com/3/";
    const std::string token_1 = "foo_token";
    const std::string token_2 = "bar_token";
    const std::string token_3 = "baz_token";

    SECTION("when users are persisted") {
        const std::string identity_1 = "foo-1";
        const std::string identity_2 = "bar-1";
        const std::string identity_3 = "baz-1";
        // First, create a few users and add them to the metadata.
        auto u1 = SyncUserMetadata(manager, identity_1);
        u1.set_state(url_1, token_1);
        auto u2 = SyncUserMetadata(manager, identity_2);
        u2.set_state(url_2, token_2);
        auto u3 = SyncUserMetadata(manager, identity_3);
        u3.set_state(url_3, token_3);
        // The fourth user is an "invalid" user: no token, so shouldn't show up.
        auto u_invalid = SyncUserMetadata(manager, "invalid_user");
        REQUIRE(manager.all_unmarked_users().size() == 4);

        SECTION("they should be added to the active users list when metadata is enabled") {
            SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoEncryption);
            auto users = SyncManager::shared().all_users();
            REQUIRE(users.size() == 3);
            REQUIRE(validate_user_in_vector(users, identity_1, url_1, token_1));
            REQUIRE(validate_user_in_vector(users, identity_2, url_2, token_2));
            REQUIRE(validate_user_in_vector(users, identity_3, url_3, token_3));
        }
        SECTION("they should not be added to the active users list when metadata is disabled") {
            SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoMetadata);
            auto users = SyncManager::shared().all_users();
            REQUIRE(users.size() == 0);
        }
    }

    SECTION("when users are marked") {
        const std::string identity_1 = "foo-2";
        const std::string identity_2 = "bar-2";
        const std::string identity_3 = "baz-2";
        // Pre-populate the user directories.
        const auto user_dir_1 = file_manager.user_directory(identity_1);
        const auto user_dir_2 = file_manager.user_directory(identity_2);
        const auto user_dir_3 = file_manager.user_directory(identity_3);
        create_dummy_realm(user_dir_1 + "123456789");
        create_dummy_realm(user_dir_1 + "foo");
        create_dummy_realm(user_dir_2 + "123456789");
        create_dummy_realm(user_dir_3 + "foo");
        create_dummy_realm(user_dir_3 + "bar");
        create_dummy_realm(user_dir_3 + "baz");
        // Create the user metadata.
        auto u1 = SyncUserMetadata(manager, identity_1);
        u1.mark_for_removal();
        auto u2 = SyncUserMetadata(manager, identity_2);
        u2.mark_for_removal();
        // Don't mark this user for deletion.
        auto u3 = SyncUserMetadata(manager, identity_3);
        u3.set_state(url_3, token_3);

        SECTION("they should be cleaned up if metadata is enabled") {
            SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoEncryption);
            auto users = SyncManager::shared().all_users();
            REQUIRE(users.size() == 1);
            REQUIRE(validate_user_in_vector(users, identity_3, url_3, token_3));
            REQUIRE_DIR_DOES_NOT_EXIST(user_dir_1);
            REQUIRE_DIR_DOES_NOT_EXIST(user_dir_2);
            REQUIRE_DIR_EXISTS(user_dir_3);
        }
        SECTION("they should be left alone if metadata is disabled") {
            SyncManager::shared().configure_file_system(base_path, SyncManager::MetadataMode::NoMetadata);
            auto users = SyncManager::shared().all_users();
            REQUIRE_DIR_EXISTS(user_dir_1);
            REQUIRE_DIR_EXISTS(user_dir_2);
            REQUIRE_DIR_EXISTS(user_dir_3);
        }
    }
}

TEST_CASE("sync_manager: metadata") {
    auto cleanup = util::make_scope_exit([=]() noexcept { SyncManager::shared().reset_for_testing(); });
    reset_test_directory(base_path);

    SECTION("should be reset in case of decryption error") {
        SyncManager::shared().configure_file_system(base_path,
                                                    SyncManager::MetadataMode::Encryption,
                                                    make_test_encryption_key());

        SyncManager::shared().reset_for_testing();

        SyncManager::shared().configure_file_system(base_path,
                                                    SyncManager::MetadataMode::Encryption,
                                                    make_test_encryption_key(),
                                                    true);
    }
}
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/PointCloud.h>
#include <sensor_msgs/point_cloud_conversion.h>
#include <tf/transform_listener.h>
#include <octomap/octomap.h>
#include <octomap/OcTree.h>
#include <octomap_msgs/Octomap.h>
#include <octomap_msgs/conversions.h>
#include <geometry_msgs/PointStamped.h>

#include <string>
#include <math.h>
#include <vector>

#include "dmath/geometry.h"

class ArtificialPotentialField{
public:
    ArtificialPotentialField(ros::NodeHandle &node) :
        base_link_("base_link"),
        cmd_pub_(node.advertise<geometry_msgs::Twist>("cmd_vel", 10)),
        obs_sub_(node.subscribe("octomap_full", 10, &ArtificialPotentialField::obstacleCallback, this))

    {
        collision_map_.header.stamp = ros::Time(0);
    }

    void spin(){
        ros::Rate r(10);

        ros::Duration(1).sleep();
        geometry_msgs::Twist cmd;
        cmd.linear.z = 0.15;
        cmd_pub_.publish(cmd);
        ros::Duration(3).sleep();

        cmd.linear.z = 0;
        cmd_pub_.publish(cmd);
        ros::Duration(3).sleep();

        const double force = 0.025;

        while(ros::ok()){
            if(collision_map_.header.stamp != ros::Time(0)){
                std::vector<dmath::Vector3D> obstacles_lc;
                std::string map_frame = collision_map_.header.frame_id;
                octomap::OcTree *tree = dynamic_cast<octomap::OcTree*>(octomap_msgs::msgToMap(collision_map_));
                octomap::OcTree::leaf_iterator const end_it = tree->end_leafs();
                for(octomap::OcTree::leaf_iterator it = tree->begin_leafs(0); it != end_it; it++){
                    geometry_msgs::PointStamped p_in, p_out;
                    p_in.header.frame_id = map_frame;
                    p_in.point.x = it.getX();
                    p_in.point.y = it.getY();
                    p_in.point.z = it.getZ();
                    tf_listener_.transformPoint(base_link_, p_in, p_out);
                    obstacles_lc.push_back(dmath::Vector3D(p_out.point.x, p_out.point.y, p_out.point.z));
                }
                ROS_INFO_STREAM("size = " << obstacles_lc.size());

                dmath::Vector3D Fs;
                for(int i=0; i < obstacles_lc.size(); i++){
                    Fs += get_potential_force(obstacles_lc[i], 0, 0.5, 1.0, 1.5);
                }

                //dmath::Vector3D g;
                //Fs += get_potential_force(g, 2, 0, 1.5, 1);

                dmath::Vector3D vel = Fs * force;
                cmd.linear.x = vel.y;
                cmd.linear.y = vel.x;
                cmd.linear.z = vel.z;

                ROS_INFO_STREAM("cmd = " << cmd);
                cmd_pub_.publish(cmd);
            }
            r.sleep();
            ros::spinOnce();
        }
    }

private:
    dmath::Vector3D get_potential_force(const dmath::Vector3D &dest_lc, double A = 1, double B = 1, double n = 1, double m = 1){
        dmath::Vector3D u = dest_lc;
        u = normalize(u);

        const double d = magnitude(dest_lc);
        double U = 0;
        if(fabs(d) > dmath::tol){
            U = -A/pow(d, n) + B/pow(d, m);
        }

        return U * u;
    }

    void obstacleCallback(const octomap_msgs::OctomapPtr &obs_msg){
        collision_map_ = *obs_msg;
    }

    octomap_msgs::Octomap collision_map_;
    ros::Publisher cmd_pub_;
    ros::Subscriber obs_sub_;
    tf::TransformListener tf_listener_;
    std::string base_link_;
};

int main(int argc, char *argv[]){
    ros::init(argc, argv, "apf_planner");

    ros::NodeHandle node;
    ArtificialPotentialField apf(node);
    apf.spin();

    return 0;
}

<commit_msg>Add an block for catching exception of tf<commit_after>#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/PointCloud.h>
#include <sensor_msgs/point_cloud_conversion.h>
#include <tf/transform_listener.h>
#include <octomap/octomap.h>
#include <octomap/OcTree.h>
#include <octomap_msgs/Octomap.h>
#include <octomap_msgs/conversions.h>
#include <geometry_msgs/PointStamped.h>

#include <string>
#include <math.h>
#include <vector>

#include "dmath/geometry.h"

class ArtificialPotentialField{
public:
    ArtificialPotentialField(ros::NodeHandle &node) :
        base_link_("base_link"),
        cmd_pub_(node.advertise<geometry_msgs::Twist>("cmd_vel", 10)),
        obs_sub_(node.subscribe("octomap_full", 10, &ArtificialPotentialField::obstacleCallback, this))

    {
        collision_map_.header.stamp = ros::Time(0);
    }

    void spin(){
        ros::Rate r(10);

        ros::Duration(1).sleep();
        geometry_msgs::Twist cmd;
        cmd.linear.z = 0.15;
        cmd_pub_.publish(cmd);
        ros::Duration(3).sleep();

        cmd.linear.z = 0;
        cmd_pub_.publish(cmd);
        ros::Duration(3).sleep();

        const double force = 0.025;

        while(ros::ok()){
            if(collision_map_.header.stamp != ros::Time(0)){
                std::vector<dmath::Vector3D> obstacles_lc;
                std::string map_frame = collision_map_.header.frame_id;
                octomap::OcTree *tree = dynamic_cast<octomap::OcTree*>(octomap_msgs::msgToMap(collision_map_));
                octomap::OcTree::leaf_iterator const end_it = tree->end_leafs();
                for(octomap::OcTree::leaf_iterator it = tree->begin_leafs(0); it != end_it; it++){
                    geometry_msgs::PointStamped p_in, p_out;
                    p_in.header.frame_id = map_frame;
                    p_in.point.x = it.getX();
                    p_in.point.y = it.getY();
                    p_in.point.z = it.getZ();

                    try{
                        tf_listener_.transformPoint(base_link_, p_in, p_out);
                    }catch(tf::TransformException &ex){
                        ROS_ERROR_STREAM("Exception trying to transform octomap: " << ex.what());
                    }

                    obstacles_lc.push_back(dmath::Vector3D(p_out.point.x, p_out.point.y, p_out.point.z));
                }
                ROS_INFO_STREAM("size = " << obstacles_lc.size());

                dmath::Vector3D Fs;
                for(int i=0; i < obstacles_lc.size(); i++){
                    Fs += get_potential_force(obstacles_lc[i], 0, 0.5, 1.0, 1.5);
                }

                //dmath::Vector3D g;
                //Fs += get_potential_force(g, 2, 0, 1.5, 1);

                dmath::Vector3D vel = Fs * force;
                cmd.linear.x = vel.y;
                cmd.linear.y = vel.x;
                cmd.linear.z = vel.z;

                ROS_INFO_STREAM("cmd = " << cmd);
                cmd_pub_.publish(cmd);
            }
            r.sleep();
            ros::spinOnce();
        }
    }

private:
    dmath::Vector3D get_potential_force(const dmath::Vector3D &dest_lc, double A = 1, double B = 1, double n = 1, double m = 1){
        dmath::Vector3D u = dest_lc;
        u = normalize(u);

        const double d = magnitude(dest_lc);
        double U = 0;
        if(fabs(d) > dmath::tol){
            U = -A/pow(d, n) + B/pow(d, m);
        }

        return U * u;
    }

    void obstacleCallback(const octomap_msgs::OctomapPtr &obs_msg){
        collision_map_ = *obs_msg;
    }

    octomap_msgs::Octomap collision_map_;
    ros::Publisher cmd_pub_;
    ros::Subscriber obs_sub_;
    tf::TransformListener tf_listener_;
    std::string base_link_;
};

int main(int argc, char *argv[]){
    ros::init(argc, argv, "apf_planner");

    ros::NodeHandle node;
    ArtificialPotentialField apf(node);
    apf.spin();

    return 0;
}

<|endoftext|>


<commit_before>/*
* Key codes for multiple platforms
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#pragma once

#if defined(_WIN32)
#define KEY_ESCAPE VK_ESCAPE
#define KEY_F1 VK_F1
#define KEY_F2 VK_F2
#define KEY_W 0x57
#define KEY_A 0x41
#define KEY_S 0x53
#define KEY_D 0x44
#define KEY_P 0x50
//
#define KEY_SPACE 0x20
#define KEY_KPADD 0x6B
#define KEY_KPSUB 0x6D
#define KEY_B 0x42
#define KEY_F 0x46
#define KEY_L 0x4C
#define KEY_N 0x4E
#define KEY_O 0x4F
#define KEY_T 0x54
//
#elif defined(__ANDROID__)
#elif defined(__linux__)
#define KEY_ESCAPE 0x9
#define KEY_F1 0x43
#define KEY_F2 0x44
#define KEY_W 0x19
#define KEY_A 0x26
#define KEY_S 0x27
#define KEY_D 0x28
#define KEY_P 0x21
//
#define KEY_SPACE 0x41
#define KEY_KPADD 0x56
#define KEY_KPSUB 0x52
#define KEY_B 0x38
#define KEY_F 0x29
#define KEY_L 0x2E
#define KEY_N 0x39
#define KEY_O 0x20
#define KEY_T 0x1C
//
#endif

// todo: Android gamepad keycodes outside of define for now
#define GAMEPAD_BUTTON_A 0x1000
#define GAMEPAD_BUTTON_B 0x1001
#define GAMEPAD_BUTTON_X 0x1002
#define GAMEPAD_BUTTON_Y 0x1003
#define GAMEPAD_BUTTON_L1 0x1004
#define GAMEPAD_BUTTON_R1 0x1005
#define GAMEPAD_BUTTON_START 0x1006
<commit_msg>Dummy keycodes for Android (required for compiling examples using the new keycodes)<commit_after>/*
* Key codes for multiple platforms
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#pragma once

#if defined(_WIN32)
#define KEY_ESCAPE VK_ESCAPE
#define KEY_F1 VK_F1
#define KEY_F2 VK_F2
#define KEY_W 0x57
#define KEY_A 0x41
#define KEY_S 0x53
#define KEY_D 0x44
#define KEY_P 0x50
#define KEY_SPACE 0x20
#define KEY_KPADD 0x6B
#define KEY_KPSUB 0x6D
#define KEY_B 0x42
#define KEY_F 0x46
#define KEY_L 0x4C
#define KEY_N 0x4E
#define KEY_O 0x4F
#define KEY_T 0x54
#elif defined(__ANDROID__)
// Dummy key codes
#define KEY_ESCAPE 0x0
#define KEY_F1 0x1
#define KEY_F2 0x2
#define KEY_W 0x3
#define KEY_A 0x4
#define KEY_S 0x5
#define KEY_D 0x6
#define KEY_P 0x7
#define KEY_SPACE 0x8
#define KEY_KPADD 0x9
#define KEY_KPSUB 0xA
#define KEY_B 0xB
#define KEY_F 0xC
#define KEY_L 0xD
#define KEY_N 0xE
#define KEY_O 0xF
#define KEY_T 0x10
#elif defined(__linux__)
#define KEY_ESCAPE 0x9
#define KEY_F1 0x43
#define KEY_F2 0x44
#define KEY_W 0x19
#define KEY_A 0x26
#define KEY_S 0x27
#define KEY_D 0x28
#define KEY_P 0x21
#define KEY_SPACE 0x41
#define KEY_KPADD 0x56
#define KEY_KPSUB 0x52
#define KEY_B 0x38
#define KEY_F 0x29
#define KEY_L 0x2E
#define KEY_N 0x39
#define KEY_O 0x20
#define KEY_T 0x1C
#endif

// todo: Android gamepad keycodes outside of define for now
#define GAMEPAD_BUTTON_A 0x1000
#define GAMEPAD_BUTTON_B 0x1001
#define GAMEPAD_BUTTON_X 0x1002
#define GAMEPAD_BUTTON_Y 0x1003
#define GAMEPAD_BUTTON_L1 0x1004
#define GAMEPAD_BUTTON_R1 0x1005
#define GAMEPAD_BUTTON_START 0x1006
<|endoftext|>


<commit_before>/*
Copyright 2016, Jernej Kovacic

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.
*/

/**
 * @name
 * @author Jernej Kovacic
 *
 * Implementation of auxiliary functions that fill integer vector(s) with
 * elements' consecutive indices.
 */

#include <cstddef>
#include <vector>

#include "../settings/omp_settings.h"
#include "omp/omp_header.h"
#include "omp/omp_coarse.h"

#include "util/FillVectors.h"

// An anonymous namespace for "private" functions:
namespace math {  namespace util {  namespace
{

/*
 * Preallocates and fills vectors 'v1' and optionally 'v2' with consecutive
 * values between 0 and N-1.
 *
 * @note The function attempts to resize 'v1' and optionally 'v2', however it does
 *       not handle the exception std::bad_alloc (thrown when not enough memory is
 *       available). The exception is transferred to the caller. It is recommended
 *       that 'v1' and optionally 'v2' are preallocated prior to calling this function.
 *
 * @param N - size of vector(s)
 * @param v1 - first vector
 * @param v2 - second vector (ignored if 'bothVectors' is false)
 * @param bothVectors - if false, only 'v1' is preallocated and filled with initial positions
 */
void fillVectorsWithInitialConsecutiveIndices(
        const std::size_t N,
        std::vector<std::size_t>& v1,
        std::vector<std::size_t>& v2,
        const bool bothVectors
      )
{
    v1.resize(N);

    if ( true == bothVectors )
    {
        v2.resize(N);
    }

    /*
     * Fill 'v1' and optionally 'v2' with initial positions.
     */
    #pragma omp parallel num_threads(ompIdeal(N)) \
                if(N>OMP_CHUNKS_PER_THREAD) \
                default(none) shared(v1, v2)
    {
        OMP_COARSE_GRAINED_PAR_INIT_VARS(N);

        typename std::vector<std::size_t>::iterator it1 = v1.begin() + istart;
        typename std::vector<std::size_t>::iterator it2 = v2.begin() + istart;
        std::size_t i = istart;
        for ( std::size_t cntr=0;
              cntr<elems_per_thread && it1!=v1.end();
              ++cntr, ++i, ++it1 )
        {
            std::size_t& v1cur = *it1;
            std::size_t& v2cur = *it2;

            v1cur = i;
            if ( true == bothVectors )
            {
                v2cur = i;
                ++it2;
            }
        }

        (void) iend;
    }  // omp parallel

}

}}} // anonymous namespace

/**
 * Preallocates and fills vectors 'v1' and 'v2' with consecutive values
 * between 0 and N-1.
 *
 * @note The function attempts to resize 'v1' and 'v2', however it does not handle
 *       the exception std::bad_alloc (thrown when not enough memory is available).
 *       The exception is transferred to the caller. It is recommended that 'v1'
 *       and 'v2' are preallocated prior to calling this function.
 *
 * @param N - size of vector
 * @param v1 - first vector to fill
 * @param v2 - second vector to fill
 */
void math::util::fillVectorsWithConsecutiveIndices(
        const std::size_t N,
        std::vector<std::size_t>& v1,
        std::vector<std::size_t>& v2 )
{
    math::util::fillVectorsWithInitialConsecutiveIndices(N, v1, v2, true);
}

/**
 * Preallocates and fills vector 'v' with consecutive values between 0 and N-1.
 *
 * @note The function attempts to resize 'v', however it does not handle
 *       the exception std::bad_alloc (thrown when not enough memory is available).
 *       The exception is transferred to the caller. It is recommended that 'v'
 *       is preallocated prior to calling this function.
 *
 * @param N - size of vector
 * @param v - vector to fill
 */
void math::util::fillVectorWithConsecutiveIndices(
        const std::size_t N,
        std::vector<std::size_t>& v )
{
    math::util::fillVectorsWithInitialConsecutiveIndices(N, v, v, false);
}
<commit_msg>stylistic improvement<commit_after>/*
Copyright 2016, Jernej Kovacic

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.
*/

/**
 * @name
 * @author Jernej Kovacic
 *
 * Implementation of auxiliary functions that fill integer vector(s) with
 * elements' consecutive indices.
 */

#include <cstddef>
#include <vector>

#include "../settings/omp_settings.h"
#include "omp/omp_header.h"
#include "omp/omp_coarse.h"

#include "util/FillVectors.h"

// An anonymous namespace for "private" functions:
namespace math {  namespace util {  namespace
{

/*
 * Preallocates and fills vectors 'v1' and optionally 'v2' with consecutive
 * values between 0 and N-1.
 *
 * @note The function attempts to resize 'v1' and optionally 'v2', however it does
 *       not handle the exception std::bad_alloc (thrown when not enough memory is
 *       available). The exception is transferred to the caller. It is recommended
 *       that 'v1' and optionally 'v2' are preallocated prior to calling this function.
 *
 * @param N - size of vector(s)
 * @param v1 - first vector
 * @param v2 - second vector (ignored if 'bothVectors' is false)
 * @param bothVectors - if false, only 'v1' is preallocated and filled with initial positions
 */
void fillVectorsWithInitialConsecutiveIndices(
        const std::size_t N,
        std::vector<std::size_t>& v1,
        std::vector<std::size_t>& v2,
        const bool bothVectors
      )
{
    v1.resize(N);

    if ( true == bothVectors )
    {
        v2.resize(N);
    }

    /*
     * Fill 'v1' and optionally 'v2' with initial positions.
     */
    #pragma omp parallel num_threads(ompIdeal(N)) \
                if(N>OMP_CHUNKS_PER_THREAD) \
                default(none) shared(v1, v2)
    {
        OMP_COARSE_GRAINED_PAR_INIT_VARS(N);

        typename std::vector<std::size_t>::iterator it1 = v1.begin() + istart;
        typename std::vector<std::size_t>::iterator it2 = v2.begin() + istart;
        std::size_t i = istart;
        for ( std::size_t cntr=0;
              cntr<elems_per_thread && it1!=v1.end();
              ++cntr, ++i, ++it1 )
        {
            std::size_t& v1cur = *it1;
            std::size_t& v2cur = *it2;

            v1cur = i;
            if ( true == bothVectors )
            {
                v2cur = i;
                ++it2;
            }
        }

        (void) iend;
    }  // omp parallel

}

}}} // anonymous namespace

/**
 * Preallocates and fills vectors 'v1' and 'v2' with consecutive values
 * between 0 and N-1.
 *
 * @note The function attempts to resize 'v1' and 'v2', however it does not handle
 *       the exception std::bad_alloc (thrown when not enough memory is available).
 *       The exception is transferred to the caller. It is recommended that 'v1'
 *       and 'v2' are preallocated prior to calling this function.
 *
 * @param N - size of vector
 * @param v1 - first vector to fill
 * @param v2 - second vector to fill
 */
void math::util::fillVectorsWithConsecutiveIndices(
        const std::size_t N,
        std::vector<std::size_t>& v1,
        std::vector<std::size_t>& v2 )
{
    math::util::fillVectorsWithInitialConsecutiveIndices(N, v1, v2, true);
}

/**
 * Preallocates and fills vector 'v' with consecutive values between 0 and N-1.
 *
 * @note The function attempts to resize 'v', however it does not handle
 *       the exception std::bad_alloc (thrown when not enough memory is available).
 *       The exception is transferred to the caller. It is recommended that 'v'
 *       is preallocated prior to calling this function.
 *
 * @param N - size of vector
 * @param v - vector to fill
 */
void math::util::fillVectorWithConsecutiveIndices(
        const std::size_t N,
        std::vector<std::size_t>& v )
{
    math::util::fillVectorsWithInitialConsecutiveIndices(N, v, v, false);
}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_REV_CORE_SET_ZERO_ALL_ADJOINTS_NESTED_HPP
#define STAN_MATH_REV_CORE_SET_ZERO_ALL_ADJOINTS_NESTED_HPP

#include <stan/math/rev/core/vari.hpp>
#include <stan/math/rev/core/chainable_alloc.hpp>
#include <stan/math/rev/core/chainablestack.hpp>
#include <stan/math/rev/core/empty_nested.hpp>
#include <stdexcept>

namespace stan {
  namespace math {

    /**
     * Reset all adjoint values in the top nested portion of the stack
     * to zero.
     */
    static void set_zero_all_adjoints_nested() {
      if (empty_nested())
        throw std::logic_error("empty_nested() must be false before calling"
                               " set_zero_all_adjoints_nested()");
      size_t start1 = ChainableStack::nested_var_stack_sizes_.back();
      // avoid wrap with unsigned when start1 == 0
      for (size_t i = (start1 == 0) ? 0 : (start1 - 1);
           i < ChainableStack::var_stack_.size(); ++i)
        ChainableStack::var_stack_[i]->set_zero_adjoint();

      size_t start2 = ChainableStack::nested_var_nochain_stack_sizes_.back();
      for (size_t i = (start2 == 0) ? 0U : start2 - 1;
           i < ChainableStack::var_nochain_stack_.size(); ++i) {
        ChainableStack::var_nochain_stack_[i]->set_zero_adjoint();
      }
    }

  }
}
#endif
<commit_msg>made boundary conditions consistent<commit_after>#ifndef STAN_MATH_REV_CORE_SET_ZERO_ALL_ADJOINTS_NESTED_HPP
#define STAN_MATH_REV_CORE_SET_ZERO_ALL_ADJOINTS_NESTED_HPP

#include <stan/math/rev/core/vari.hpp>
#include <stan/math/rev/core/chainable_alloc.hpp>
#include <stan/math/rev/core/chainablestack.hpp>
#include <stan/math/rev/core/empty_nested.hpp>
#include <stdexcept>

namespace stan {
  namespace math {

    /**
     * Reset all adjoint values in the top nested portion of the stack
     * to zero.
     */
    static void set_zero_all_adjoints_nested() {
      if (empty_nested())
        throw std::logic_error("empty_nested() must be false before calling"
                               " set_zero_all_adjoints_nested()");
      size_t start1 = ChainableStack::nested_var_stack_sizes_.back();
      // avoid wrap with unsigned when start1 == 0
      for (size_t i = (start1 == 0U) ? 0U : (start1 - 1);
           i < ChainableStack::var_stack_.size(); ++i)
        ChainableStack::var_stack_[i]->set_zero_adjoint();

      size_t start2 = ChainableStack::nested_var_nochain_stack_sizes_.back();
      for (size_t i = (start2 == 0U) ? 0U : (start2 - 1);
           i < ChainableStack::var_nochain_stack_.size(); ++i) {
        ChainableStack::var_nochain_stack_[i]->set_zero_adjoint();
      }
    }

  }
}
#endif
<|endoftext|>


<commit_before>/* MergeSort.c

	Este programa realiza el algoritmo paralelizado del MergeSort para ordenar una lista desordenada, el cual consiste en:
		Dividir la lista recursivamente en sublistas de aproximadamente la mitad del tamano hasta que su tamano sea 1
		Ordenar cada sublista recursivamente usando este algoritmo
		Mezclar cada sublista hasta que se forme una sola

	El programa ordena con p procesos una lista de n valores entre 0 y m, donde
		p es el numero de procesos, lo define el usuario en "mpiexcec". Debe de ser potencia de 2
		n es el tamaÃ±o de la lista a ordenas, se los pide al usuario el proceso raiz. Debe de se divisible por p
		m es el rango de posibles valores que pueden aparecer en la lista, se los pide al usuario el proceso raiz. Debe ser <=60

	Al final se despliega
		Lista ordenada, si el usuario lo desea
		Tiempo que tardo el ordenamieto
		Valores de p, n y m
		Numero de veces que aparecia en la lista cada uno de los posibles valores del 0 a m
*/

#include <stdio.h>
#include "mpi.h"
#include <stdlib.h>

#include<iostream>
#include <chrono>
#include <ctime>

using namespace std;

int main( int argc, char *argv[] )
{
    int*  lista;        /* Lista que debe ser ordenada*/
    int* lista_local;
    int  n;            /*  Dimension de los 2 vectores dada por el usuario */
    int m;	       /*  Limite de numeros aleatorios de la lista */
    int  p;            /*  Numero de procesos que corren */
    int  my_rank;      /*  Identificacion de cada proceso*/
    int r;
    int t;

    void Genera_vector(int lista[], int n, int m);   /* Genera valores aleatorios para n vector de enteros*/

    MPI_Init(&argc, &argv); /* Inicializacion del ambiente para MPI.
                            En C MPI_Init se puede usar para pasar los argumentos de la linea de comando
                            a todos los procesos, aunque no es requerido, depende de la implementacion */

    MPI_Comm_size(MPI_COMM_WORLD, &p); /* Se le pide al comunicador MPI_COMM_WORLD que
                                          almacene en p el numero de procesos de ese comunicador.
                                          O sea para este caso, p indicara el num total de procesos que corren*/

    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); /* Se le pide al comunicador MPI_COMM_WORL que devuelva en
                                                la variable my_rank la identificacion del proceso "llamador"
                                                la identificacion es un numero de 0 a p-1 */

    MPI_Comm rcom, tcom;
    MPI_Group original;

    MPI_Comm_group(MPI_COMM_WORLD, &original);
    MPI_Comm_create(MPI_COMM_WORLD, original, &rcom);
    MPI_Comm_create(MPI_COMM_WORLD, original, &tcom);

    if (my_rank == 0) {   /* LO QUE SIGUE LO REALIZA UNICAMENTE EL PROCESO 0 (PROCESO RAIZ o PRINCIPAL) */
      std::cout << "Digite el tamano de la lista\n" << endl;
      std::cin >> n;

      std::cout << "Digite el limite de valores aleatorios en la lista" << endl;
	    std::cin >> m;

      lista = (int *)malloc(n*sizeof(int));
      if(lista==NULL){
		    std::cout << "Error al asignar memoria a la lista" << endl;
		    return 0;
      }
      Genera_vector(lista, n, m);

	for(int i=0; i < n; i++) {
        std::cout << lista[i] << " ";
  	}

      r = n % p;
      t = (n - r)/p;
    }

      MPI_Bcast(&t, 1, MPI_INT, 0, MPI_COMM_WORLD);
   	MPI_Bcast(&r, 1, MPI_INT, 0, MPI_COMM_WORLD);
      lista_local = (int *)malloc((t+1)*sizeof(int));

      MPI_Scatter(lista, t + 1, MPI_INT, lista_local, t + 1, MPI_INT, 0, rcom);
      MPI_Scatter(lista, t, MPI_INT, lista_local, t, MPI_INT, 0, tcom);

   std::cout << "Yo soy el proceso " << my_rank << " ";
   for(int i=0; i <= t+1; i++) {
        std::cout << lista_local[i] << "\n" << endl;
   }

    if (my_rank == 0) {
	free(lista);

	}
     free(lista_local);

   MPI_Finalize();

   return 0;
}

void Genera_vector(int lista[], int n,  int m)
{
      int i;
      for (i = 0; i < n; i++) {
        //lista[i]= 0 + rand()%(m+1-0);
	lista[i]= i;
      }
}
<commit_msg>cambios para poder repartir la lista<commit_after>/* MergeSort.c

	Este programa realiza el algoritmo paralelizado del MergeSort para ordenar una lista desordenada, el cual consiste en:
		Dividir la lista recursivamente en sublistas de aproximadamente la mitad del tamano hasta que su tamano sea 1
		Ordenar cada sublista recursivamente usando este algoritmo
		Mezclar cada sublista hasta que se forme una sola

	El programa ordena con p procesos una lista de n valores entre 0 y m, donde
		p es el numero de procesos, lo define el usuario en "mpiexcec". Debe de ser potencia de 2
		n es el tamaÃ±o de la lista a ordenas, se los pide al usuario el proceso raiz. Debe de se divisible por p
		m es el rango de posibles valores que pueden aparecer en la lista, se los pide al usuario el proceso raiz. Debe ser <=60

	Al final se despliega
		Lista ordenada, si el usuario lo desea
		Tiempo que tardo el ordenamieto
		Valores de p, n y m
		Numero de veces que aparecia en la lista cada uno de los posibles valores del 0 a m
*/

#include <stdio.h>
#include "mpi.h"
#include <stdlib.h>

#include<iostream>
#include <chrono>
#include <ctime>

using namespace std;

int main( int argc, char *argv[] )
{
    int* lista;        /* Lista que debe ser ordenada*/
    int* lista_cantidadMenor;
    int* lista_local;
    int  n;            /*  Dimension de los 2 vectores dada por el usuario */
    int m;	       /*  Limite de numeros aleatorios de la lista */
    int  p;            /*  Numero de procesos que corren */
    int  my_rank;      /*  Identificacion de cada proceso*/
    int r;
    int t;

    int cantidadMenorTag = 11011;

    void Genera_vector(int lista[], int n, int m);   /* Genera valores aleatorios para n vector de enteros*/

    MPI_Init(&argc, &argv); /* Inicializacion del ambiente para MPI. */

    MPI_Comm_size(MPI_COMM_WORLD, &p); //Cantidad de procesos inicializados.

    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); //El rango del proceso "local".

    MPI_Comm balancer_comm; //Este comunicador sirve entre procesos que tengan el mísmo número de items.
    MPI_Group original_group;

    MPI_Comm_group(MPI_COMM_WORLD, &original_group); //

    if (my_rank == 0) {   /* LO QUE SIGUE LO REALIZA UNICAMENTE EL PROCESO 0 (PROCESO RAIZ o PRINCIPAL) */
      std::cout << "Digite el tamano de la lista\n" << endl;
      std::cin >> n;

      std::cout << "Digite el limite de valores aleatorios en la lista" << endl;
	    std::cin >> m;

      lista = (int *)malloc(n*sizeof(int));
      if(lista==NULL){
		    std::cout << "Error al asignar memoria a la lista" << endl;
		    return 0;
      }
      Genera_vector(lista, n, m);

    	for(int i=0; i < n; i++) {
        std::cout <<"parent WORLD: " << lista[i] << " ";
      }

      r = n % p;  //Restante de la division de items en la lista entre los procesos.
                  //También indica los r primero procesos a recibir t+1 items.
      t = (n - r)/p;  //Cuantos items por proceso para que tengan el mismo número de procesos (no contando los restantes).

      lista_cantidadMenor = lista+r;

      if(r != 0){
      MPI_Send (lista_cantidadMenor,n-r,MPI_INT,r,cantidadMenorTag, MPI_COMM_WORLD);  //Mandamos la lista de cantidades menores al pocesador que se convertira
                                                                                //en la raiz de su comunicador que se crea al hacer el split después.
      std::cout << "0 is done sending lista_cantidadMenor" << std::endl;
      }
      free(lista_cantidadMenor);
    }

    MPI_Bcast(&t, 1, MPI_INT, 0, MPI_COMM_WORLD);
   	MPI_Bcast(&r, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

    if(my_rank == r-1)//Soy el proceso raíz del segundo subgrupo de comm.
    {
      MPI_Recv(lista,n-r,MPI_INT,r-1,cantidadMenorTag,MPI_COMM_WORLD,MPI_STATUS_IGNORE); //Recibir la lista de cantidades menores
    }

    //Vamos a dividir los procesos en dos sub comunicadores. El de color 1 que recibe t+1 items en sus listas.
    //El de color 2 que recibe t items. Esto para garantizar una manera de recibir cualquier cantidad de n de items.

    int color = my_rank < r ? 1 : 0; //Esto es para calcular el color (identificar procesos de un comunicador) del proceso.

    //Aquí es donde se reparte los procesos según color y se identifican con el COMM handler balancer_comm.
    MPI_Comm_split(MPI_COMM_WORLD, color, my_rank, &balancer_comm);

    //Ahora, dependiendo del color, la lista será del tamaño t+1, o t.
    lista_local = (int *)malloc((t+color)*sizeof(int));

    if(r > 0){
      //Vamos a repartir la lista. Para los procesos en COMM_WORLD con rank menor a r, esto reciben t+1, para los otro t.
      MPI_Scatter(lista, t + 1, MPI_INT, lista_local, t + 1, MPI_INT, 0, balancer_comm);
      MPI_Scatter(lista, t, MPI_INT, lista_local, t, MPI_INT, r-1, balancer_comm);
    }else{
      lista_local = lista;
    }

  std::cout << "Yo soy el proceso " << my_rank << " del comunicador: "<< balancer_comm << " first: " << lista_local[0] << std::endl;

  if(my_rank == 0 || my_rank == r-1){
	   free(lista);
  }

  free(lista_local);

  MPI_Finalize();

   return 0;
}

void Genera_vector(int lista[], int n,  int m)
{
      int i;
      for (i = 0; i < n; i++) {
        //lista[i]= 0 + rand()%(m+1-0);
	         lista[i]= i;
      }
}
<|endoftext|>