<commit_before>#include "routing/bicycle_directions.hpp"
#include "routing/car_model.hpp"
#include "routing/router_delegate.hpp"
#include "routing/routing_result_graph.hpp"
#include "routing/turns_generator.hpp"

#include "indexer/ftypes_matcher.hpp"
#include "indexer/index.hpp"
#include "indexer/scales.hpp"

#include "geometry/point2d.hpp"

namespace
{
using namespace routing;
using namespace routing::turns;

class RoutingResult : public IRoutingResult
{
public:
  RoutingResult(IRoadGraph::TEdgeVector const & routeEdges,
                BicycleDirectionsEngine::TAdjacentEdgesMap const & adjacentEdges,
                TUnpackedPathSegments const & pathSegments)
    : m_routeEdges(routeEdges)
    , m_adjacentEdges(adjacentEdges)
    , m_pathSegments(pathSegments)
    , m_routeLength(0)
  {
    for (auto const & edge : routeEdges)
    {
      m_routeLength += MercatorBounds::DistanceOnEarth(edge.GetStartJunction().GetPoint(),
                                                       edge.GetEndJunction().GetPoint());
    }
  }

  // turns::IRoutingResult overrides:
  TUnpackedPathSegments const & GetSegments() const override { return m_pathSegments; }

  void GetPossibleTurns(TNodeId node, m2::PointD const & ingoingPoint,
                        m2::PointD const & junctionPoint, size_t & ingoingCount,
                        TurnCandidates & outgoingTurns) const override
  {
    ingoingCount = 0;
    outgoingTurns.candidates.clear();

    auto const adjacentEdges = m_adjacentEdges.find(node);
    if (adjacentEdges == m_adjacentEdges.cend())
    {
      ASSERT(false, ());
      return;
    }

    ingoingCount = adjacentEdges->second.m_ingoingTurnsCount;
    outgoingTurns.candidates = adjacentEdges->second.m_outgoingTurns.candidates;
  }

  double GetPathLength() const override { return m_routeLength; }

  m2::PointD const & GetStartPoint() const override
  {
    CHECK(!m_routeEdges.empty(), ());
    return m_routeEdges.front().GetStartJunction().GetPoint();
  }

  m2::PointD const & GetEndPoint() const override
  {
    CHECK(!m_routeEdges.empty(), ());
    return m_routeEdges.back().GetEndJunction().GetPoint();
  }

private:
  IRoadGraph::TEdgeVector const & m_routeEdges;
  BicycleDirectionsEngine::TAdjacentEdgesMap const & m_adjacentEdges;
  TUnpackedPathSegments const & m_pathSegments;
  double m_routeLength;
};
}  // namespace

namespace routing
{
BicycleDirectionsEngine::BicycleDirectionsEngine(Index const & index) : m_index(index) {}

void BicycleDirectionsEngine::Generate(IRoadGraph const & graph, vector<Junction> const & path,
                                       Route::TTimes & times, Route::TTurns & turns,
                                       vector<m2::PointD> & routeGeometry,
                                       my::Cancellable const & cancellable)
{
  times.clear();
  turns.clear();
  routeGeometry.clear();
  m_adjacentEdges.clear();
  m_pathSegments.clear();

  size_t const pathSize = path.size();
  if (pathSize == 0)
    return;

  auto emptyPathWorkaround = [&]()
  {
    turns.emplace_back(pathSize - 1, turns::TurnDirection::ReachedYourDestination);
    this->m_adjacentEdges[0] = AdjacentEdges(1);  // There's one ingoing edge to the finish.
  };

  if (pathSize == 1)
  {
    emptyPathWorkaround();
    return;
  }

  CalculateTimes(graph, path, times);

  IRoadGraph::TEdgeVector routeEdges;
  if (!ReconstructPath(graph, path, routeEdges, cancellable))
  {
    LOG(LDEBUG, ("Couldn't reconstruct path."));
    emptyPathWorkaround();
    return;
  }
  if (routeEdges.empty())
  {
    emptyPathWorkaround();
    return;
  }

  // Filling |m_adjacentEdges|.
  m_adjacentEdges.insert(make_pair(0, AdjacentEdges(0)));
  for (size_t i = 1; i < pathSize; ++i)
  {
    Junction const & prevJunction = path[i - 1];
    Junction const & currJunction = path[i];
    IRoadGraph::TEdgeVector outgoingEdges, ingoingEdges;
    graph.GetOutgoingEdges(currJunction, outgoingEdges);
    graph.GetIngoingEdges(currJunction, ingoingEdges);

    AdjacentEdges adjacentEdges = AdjacentEdges(ingoingEdges.size());
    // Outgoing edge angle is not used for bicyle routing.
    adjacentEdges.m_outgoingTurns.isCandidatesAngleValid = false;
    adjacentEdges.m_outgoingTurns.candidates.reserve(outgoingEdges.size());
    ASSERT_EQUAL(routeEdges.size(), pathSize - 1, ());
    FeatureID const inFeatureId = routeEdges[i - 1].GetFeatureId();

    for (auto const & edge : outgoingEdges)
    {
      auto const & outFeatureId = edge.GetFeatureId();
      // Checking for if |edge| is a fake edge.
      if (!outFeatureId.IsValid())
        continue;
      adjacentEdges.m_outgoingTurns.candidates.emplace_back(0.0 /* angle */, outFeatureId.m_index,
                                                            GetHighwayClass(outFeatureId));
    }

    LoadedPathSegment pathSegment;
    if (inFeatureId.IsValid())
    {
      LoadPathGeometry(inFeatureId, {prevJunction.GetPoint(), currJunction.GetPoint()},
                       pathSegment);
    }

    m_adjacentEdges.insert(make_pair(inFeatureId.m_index, move(adjacentEdges)));
    m_pathSegments.push_back(move(pathSegment));
  }

  RoutingResult resultGraph(routeEdges, m_adjacentEdges, m_pathSegments);
  RouterDelegate delegate;
  Route::TTimes turnAnnotationTimes;
  Route::TStreets streetNames;
  MakeTurnAnnotation(resultGraph, delegate, routeGeometry, turns, turnAnnotationTimes, streetNames);
}

Index::FeaturesLoaderGuard & BicycleDirectionsEngine::GetLoader(MwmSet::MwmId const & id)
{
  if (!m_loader || id != m_loader->GetId())
    m_loader = make_unique<Index::FeaturesLoaderGuard>(m_index, id);
  return *m_loader;
}

ftypes::HighwayClass BicycleDirectionsEngine::GetHighwayClass(FeatureID const & featureId)
{
  FeatureType ft;
  GetLoader(featureId.m_mwmId).GetFeatureByIndex(featureId.m_index, ft);
  auto const highwayClass = ftypes::GetHighwayClass(ft);
  ASSERT_NOT_EQUAL(highwayClass, ftypes::HighwayClass::Error, ());
  ASSERT_NOT_EQUAL(highwayClass, ftypes::HighwayClass::Undefined, ());
  return highwayClass;
}

void BicycleDirectionsEngine::LoadPathGeometry(FeatureID const & featureId,
                                               vector<m2::PointD> const & path,
                                               LoadedPathSegment & pathSegment)
{
  pathSegment.Clear();

  if (!featureId.IsValid())
  {
    ASSERT(false, ());
    return;
  }

  FeatureType ft;
  GetLoader(featureId.m_mwmId).GetFeatureByIndex(featureId.m_index, ft);
  auto const highwayClass = ftypes::GetHighwayClass(ft);
  ASSERT_NOT_EQUAL(highwayClass, ftypes::HighwayClass::Error, ());
  ASSERT_NOT_EQUAL(highwayClass, ftypes::HighwayClass::Undefined, ());

  pathSegment.m_highwayClass = highwayClass;
  pathSegment.m_isLink = ftypes::IsLinkChecker::Instance()(ft);

  ft.GetName(FeatureType::DEFAULT_LANG, pathSegment.m_name);

  pathSegment.m_nodeId = featureId.m_index;
  pathSegment.m_onRoundabout = ftypes::IsRoundAboutChecker::Instance()(ft);
  pathSegment.m_path = path;
  // @TODO(bykoianko) It's better to fill pathSegment.m_weight.
}
}  // namespace routing
<commit_msg>[bicycle routing] Fixing asserts while generating turns for long routes.<commit_after>#include "routing/bicycle_directions.hpp"
#include "routing/car_model.hpp"
#include "routing/router_delegate.hpp"
#include "routing/routing_result_graph.hpp"
#include "routing/turns_generator.hpp"

#include "indexer/ftypes_matcher.hpp"
#include "indexer/index.hpp"
#include "indexer/scales.hpp"

#include "geometry/point2d.hpp"

namespace
{
using namespace routing;
using namespace routing::turns;

class RoutingResult : public IRoutingResult
{
public:
  RoutingResult(IRoadGraph::TEdgeVector const & routeEdges,
                BicycleDirectionsEngine::TAdjacentEdgesMap const & adjacentEdges,
                TUnpackedPathSegments const & pathSegments)
    : m_routeEdges(routeEdges)
    , m_adjacentEdges(adjacentEdges)
    , m_pathSegments(pathSegments)
    , m_routeLength(0)
  {
    for (auto const & edge : routeEdges)
    {
      m_routeLength += MercatorBounds::DistanceOnEarth(edge.GetStartJunction().GetPoint(),
                                                       edge.GetEndJunction().GetPoint());
    }
  }

  // turns::IRoutingResult overrides:
  TUnpackedPathSegments const & GetSegments() const override { return m_pathSegments; }

  void GetPossibleTurns(TNodeId node, m2::PointD const & /* ingoingPoint */,
                        m2::PointD const & /* junctionPoint */, size_t & ingoingCount,
                        TurnCandidates & outgoingTurns) const override
  {
    ingoingCount = 0;
    outgoingTurns.candidates.clear();

    auto const adjacentEdges = m_adjacentEdges.find(node);
    if (adjacentEdges == m_adjacentEdges.cend())
    {
      ASSERT(false, ());
      return;
    }

    ingoingCount = adjacentEdges->second.m_ingoingTurnsCount;
    outgoingTurns = adjacentEdges->second.m_outgoingTurns;
  }

  double GetPathLength() const override { return m_routeLength; }

  m2::PointD const & GetStartPoint() const override
  {
    CHECK(!m_routeEdges.empty(), ());
    return m_routeEdges.front().GetStartJunction().GetPoint();
  }

  m2::PointD const & GetEndPoint() const override
  {
    CHECK(!m_routeEdges.empty(), ());
    return m_routeEdges.back().GetEndJunction().GetPoint();
  }

private:
  IRoadGraph::TEdgeVector const & m_routeEdges;
  BicycleDirectionsEngine::TAdjacentEdgesMap const & m_adjacentEdges;
  TUnpackedPathSegments const & m_pathSegments;
  double m_routeLength;
};
}  // namespace

namespace routing
{
BicycleDirectionsEngine::BicycleDirectionsEngine(Index const & index) : m_index(index) {}

void BicycleDirectionsEngine::Generate(IRoadGraph const & graph, vector<Junction> const & path,
                                       Route::TTimes & times, Route::TTurns & turns,
                                       vector<m2::PointD> & routeGeometry,
                                       my::Cancellable const & cancellable)
{
  times.clear();
  turns.clear();
  routeGeometry.clear();
  m_adjacentEdges.clear();
  m_pathSegments.clear();

  size_t const pathSize = path.size();
  if (pathSize == 0)
    return;

  auto emptyPathWorkaround = [&]()
  {
    turns.emplace_back(pathSize - 1, turns::TurnDirection::ReachedYourDestination);
    this->m_adjacentEdges[0] = AdjacentEdges(1);  // There's one ingoing edge to the finish.
  };

  if (pathSize == 1)
  {
    emptyPathWorkaround();
    return;
  }

  CalculateTimes(graph, path, times);

  IRoadGraph::TEdgeVector routeEdges;
  if (!ReconstructPath(graph, path, routeEdges, cancellable))
  {
    LOG(LDEBUG, ("Couldn't reconstruct path."));
    emptyPathWorkaround();
    return;
  }
  if (routeEdges.empty())
  {
    emptyPathWorkaround();
    return;
  }

  // Filling |m_adjacentEdges|.
  m_adjacentEdges.insert(make_pair(0, AdjacentEdges(0)));
  for (size_t i = 1; i < pathSize; ++i)
  {
    Junction const & prevJunction = path[i - 1];
    Junction const & currJunction = path[i];
    IRoadGraph::TEdgeVector outgoingEdges, ingoingEdges;
    graph.GetOutgoingEdges(currJunction, outgoingEdges);
    graph.GetIngoingEdges(currJunction, ingoingEdges);

    AdjacentEdges adjacentEdges = AdjacentEdges(ingoingEdges.size());
    // Outgoing edge angle is not used for bicyle routing.
    adjacentEdges.m_outgoingTurns.isCandidatesAngleValid = false;
    adjacentEdges.m_outgoingTurns.candidates.reserve(outgoingEdges.size());
    ASSERT_EQUAL(routeEdges.size(), pathSize - 1, ());
    FeatureID const inFeatureId = routeEdges[i - 1].GetFeatureId();

    for (auto const & edge : outgoingEdges)
    {
      auto const & outFeatureId = edge.GetFeatureId();
      // Checking for if |edge| is a fake edge.
      if (!outFeatureId.IsValid())
        continue;
      adjacentEdges.m_outgoingTurns.candidates.emplace_back(0.0 /* angle */, outFeatureId.m_index,
                                                            GetHighwayClass(outFeatureId));
    }

    LoadedPathSegment pathSegment;
    if (inFeatureId.IsValid())
    {
      LoadPathGeometry(inFeatureId, {prevJunction.GetPoint(), currJunction.GetPoint()},
                       pathSegment);
    }

    m_adjacentEdges.insert(make_pair(inFeatureId.m_index, move(adjacentEdges)));
    m_pathSegments.push_back(move(pathSegment));
  }

  RoutingResult resultGraph(routeEdges, m_adjacentEdges, m_pathSegments);
  RouterDelegate delegate;
  Route::TTimes turnAnnotationTimes;
  Route::TStreets streetNames;
  MakeTurnAnnotation(resultGraph, delegate, routeGeometry, turns, turnAnnotationTimes, streetNames);
}

Index::FeaturesLoaderGuard & BicycleDirectionsEngine::GetLoader(MwmSet::MwmId const & id)
{
  if (!m_loader || id != m_loader->GetId())
    m_loader = make_unique<Index::FeaturesLoaderGuard>(m_index, id);
  return *m_loader;
}

ftypes::HighwayClass BicycleDirectionsEngine::GetHighwayClass(FeatureID const & featureId)
{
  FeatureType ft;
  GetLoader(featureId.m_mwmId).GetFeatureByIndex(featureId.m_index, ft);
  auto const highwayClass = ftypes::GetHighwayClass(ft);
  ASSERT_NOT_EQUAL(highwayClass, ftypes::HighwayClass::Error, ());
  ASSERT_NOT_EQUAL(highwayClass, ftypes::HighwayClass::Undefined, ());
  return highwayClass;
}

void BicycleDirectionsEngine::LoadPathGeometry(FeatureID const & featureId,
                                               vector<m2::PointD> const & path,
                                               LoadedPathSegment & pathSegment)
{
  pathSegment.Clear();

  if (!featureId.IsValid())
  {
    ASSERT(false, ());
    return;
  }

  FeatureType ft;
  GetLoader(featureId.m_mwmId).GetFeatureByIndex(featureId.m_index, ft);
  auto const highwayClass = ftypes::GetHighwayClass(ft);
  ASSERT_NOT_EQUAL(highwayClass, ftypes::HighwayClass::Error, ());
  ASSERT_NOT_EQUAL(highwayClass, ftypes::HighwayClass::Undefined, ());

  pathSegment.m_highwayClass = highwayClass;
  pathSegment.m_isLink = ftypes::IsLinkChecker::Instance()(ft);

  ft.GetName(FeatureType::DEFAULT_LANG, pathSegment.m_name);

  pathSegment.m_nodeId = featureId.m_index;
  pathSegment.m_onRoundabout = ftypes::IsRoundAboutChecker::Instance()(ft);
  pathSegment.m_path = path;
  // @TODO(bykoianko) It's better to fill pathSegment.m_weight.
}
}  // namespace routing
<|endoftext|>


<commit_before>namespace W
{
    template <typename T>
    class Bind : public Thing {
    public:
    };
    class Result : public Thing {

    };
    class Thing {
    public:
        virtual const Result& release();
        virtual Bind<Thing> clone() = 0;
    };
    class Container : public Thing {
    public:
    };
    template <typename T>
    class Array : public Container {

    };
    class Members : public Array<Node> {
    public:

    };
    class Node : public Thing {
    public:
        virtual Bind<Node> call(const String& msg, Array<Argument> args) {

        }
        virtual Members& getMembers() = 0;
    };
	class Message : public Thing {
	};
    class Method : public Node {
    public:
        virtual Bind<Node>& call(const Message& msg) {
        }
		virtual Node& call(const Arguments& args) = 0;
    };
    class Class : public Node {
    public:
        virtual const String& getName() const = 0;
        virtual const Array<Class>& getSupers() const = 0;
        virtual const Array<Class>& getSubs() const = 0;
        virtual Members& getMembers() { return _members; }
        Members& getMethods() { return _methods; }
        Members& getVariables() { return _variables; }
        Object incarnate() const {// World 객체를 만드는 것이다.
            return Object(*this);
        }

        virtual Bind<Node> call(const String& msg, Array<Argument> args) {

        }
        //  Class의 각 _variables는 부모의 _variables를 clone() 한 뒤, 자기만의 심볼을 뒤에 push 한 것이다.
        //          " _methods 동일. _members는 자연스럽게 이게 된 상태.
        //  ! 논리적으로 _members 안에는 중복 이름이 있어서는 안된다.

        Members _variables;
        Members _methods;
        Chain<Node> _members;
    };
    template <typename T>
    class Classer : public Class {
        //  TClasser는 World에 visible 하지 않다:
        //      visible하다는 것은 논리적으로는 "World에서 접근 가능함" 이라는 뜻이며,
        //      물리적으로는 "파싱테이블에 매핑되어있어서 Txt가 적절한 객체로 생성될 수 있음" 이라는 뜻이다.
        //      C++안에서만 Classer<T>를 사용할 수 있다.
    public:
    };
    class WorldClass : public Class {
    public:
    };

    //  Object는 World의 객체다. 객체는 항상 객체라는 타입이다. A라는 클래스의 객체와 B라는 클래스의 객체는 Native적으로,
    //  동일한 클래스의 객체다. 바로 이부분이 헷갈리기 쉬운 부분이며 동시에 World의 재사용성을 높여주는 부분이기도 하다.
    class Object : public Node {
    public:
        Object(Class& klass) {
            _class = klass;
            _variables = klass.getVariables();
            _members.chain(klass.getMethods());
            _members.chain(_variables);
        }

    Members& getMembers() { return _members; }
    Members& getVariables() { return _variables; }

    private:
        Weak<Class> _class; // 이게 뭘 가리키느냐에 따라서, 어떠한 World 객체인가가 결정되는 것이다.
        Members _variables;
        Chain<Node> _members;
    };

	//	RETURN_T=String& is by-ref and sharable.
	/* So, Above macro will expand like this,
	 *
	 * RET_T = "String&"
	 * NAME = "addString"
	 * __VA_ARGS__ = rest of arguments.
	 *
	 * class addStringMethod : public Method {
	 * 		W_DECL_CLASS(addStringMethod, Method)
	 *
	 * 		typedef Mashall<RET_T>::MashalledType ReturnType;
	 * 		ReturnType _return;
	 *
	 * public:
	 *		addStringMethod()
	 *			// Mashall<RET_T>::RefindType is String
	 *			// Mashall<RET_T>::MashalledType is Reference<String>
	 *			// Mashall<RET_T>::isReference is 1
	 *			// Mashall<RET_T>::isSharable is 1
	 *
	 * 			// Occupiable = Reference<Occupiable> 은, rhs의 Sharable의 값이 Occupiable로 들어간다
	 *			// 이는 Occupiable은 어떻게 해서라도 값vs값의 할당이 일어나야 하기 때문이다.
	 *			// 물론 Reference<Occupiable> = Occupiable의 경우에는 Reference::operator=()가 된다.
	 *			// 그래서 아래의 경우에는 원본이 Bind로 라이프사이클이 관리되고, 그것이 Sharable이든
	 *			// Occupiable이든 값은 return으로 들어갈 수 있다.
	 *			_return = Reference(Mashall<RET_T>::RefindType());
	 *
	 *			_arguments << Reference<MyFirstWorldModule>() // thisptr
	 *
	 *			char* __VA_ARGS_를 split하고, loop를 돌면서 적합한 TClass<T>를 만들어서 arguments
	 *			에 넣어야 한다. 이 것을 하는 도중에 T* arg,  T  *  args,  T  *args 같은 케이스들도
	 *			문제없이 파싱할 수 있어야 한다.
	 *
	 *			어떻게?
	 *
	 *
	 *			_fptr = &MyFirstWorldModule::addString;
	 *
	 *		}
	 *
	 *		String& (addStringMethod::*_fptr)(String&, __VA_ARGS_...);
	 *
	 * 		//	World에서 메소드를 실행하기 위한 가장 짦은 인터페이스이다.
	 *		//	Native를 위한 인자의 가공이 시작된다.
	 *		virtual Bind<Node> call(const Arguments& args) {
	 *			if(Mashall<RET_T>::sharable)
	 *				if(is_ref) // is_ref에는 Reference로 반환한경우도 포함이 되어야 한다.
	 *					return _return = (me->*_fptr)(args[0].to<String>(), args[1].to.... 재귀 );
	 *				else
	 *					//	RET_T는 Sharable인데, 값으로 반환한 경우다. 불가피하게 퍼포먼스가 소모.
	 *					return _return = (me->*_fptr)(args[0].to<String>(), args[1].to.... 재귀 ).clone();
	 *		}
	 * };
	 */
	#define WRD_DECL_2(T, S)	.......
	#define WRD_DECL_3(T, S, M)	\
		WRD_DECL_2(T,S)	\
	protected:	\
		static const Result& _onInitializeMethods(List<Method>& tray) {	\
			FOR_EACH()
		}

	//	사용법1:
	//		.HPP에서
	class MyFirstWorldModule : public Object {
		WRD_DECL_ONLY(MyFirstWorldModule, Object,
			String, addString, (String&, String&)
			//	조건1. ,로 구분한다.
			//	조건2. 인자명 없다.
		) // static onInitializeMethods() 구현된다.
			//	조건3. 시작과 끝 ()를 넣는다.

	public:
		String addString(String& arg1, String& arg2) {
			//	Reference의 사용방법1 :
			Reference<String> ret = new String(arg1 + arg2);
			//	방법2:
			Reference<String> ret = arg1.clone();
			*ret += arg2;
			//	방법3:
			Reference<String> ret = (arg1 + arg2).clone();
			//	방법4:
			Reference<String> ret = String::make();
			*ret = arg1 + arg2;

			return ret;
		}
	};
	//	.CPP 구현 없음.

	//	사용법2:
	//	.HPP에서
	class MyFirstWorldModule : public Object {
		WRD_DECL(MyFirstWorldModule, Object) // static onInitializeMethods(); 선언 된다.

	public:
		String addString(String& arg1, String& arg2); // 여기서 정의해도 상관없다.
	};
	//	.CPP에서
	WRD_DEF(MyFirstWorldModule,
		(String, addString, String&, String & const) // static onInitializeMethods() 구현들어간다.
	)
	String MyFirstWorldModule::addString(String& arg1, String & const arg2) {
		... dosomething ...
	}
}
<commit_msg>+ [class-design] main design & concept were finished. prototyping.<commit_after>namespace wrd
{
	//	typedef들:--------------------------------------------
	typedef int wid;
	typedef int wint;
	typedef bool wbool;
	typedef int wcount;
	class Result;
	template <typename S, typename T> class Bind;
	class Strong;
	class Weak;
	class Node;
	class Object;

	class Thing {
    public:
        virtual Result& release() = 0;
		virtual Bind<Strong, Thing> clone() = 0;
		//dump?
    };
	class Instance : public Thing { // Instance 관리가 가능함.
		//	w로 시작하는 작은 타입def는 primitive에 대한 typedef를 의미한다. 객체가 아니다.
		wid getId() const;
		wid _id;
	};

	//	Bind 컴포넌트:----------------------------------------
	class Weak : public Instance {
		Node& get();
		virtual Result& bind(const Node& trg);
		wbool isBinded() const;
	};
	class Strong : public Weak {
		virtual Result& bind(const Node& trg);
	};
	//	Prefix T는 템플릿을 의미한다.
	template <typename S, typename T>
	class TBind : public S {
		//	Weak::get이 virtual이 아니기때문에 여기서 메소드은폐가 된다. 그래서 중복에러가 나지 않는다.
		T& get();
	};
	//	편의용 템플릿. c++11의 alias declaration 를 사용한다.
	template <typename T>
	using TWeak = TBind<Weak, T>;
	template <typename T>
	using TStrong = TBind<Strong, T>;

	//	Container컴포넌트:------------------------------------------
	//		Container는 주의할것이, C++을 위한 것이 아니라 월드를 위한 Conatiner이라는 점이다. 그래서 기본타입이 무조건 Node이다.
	class Iterator : public Object {
	};
	class Container : public Object, public Containable {
		virtual Result& insert(const Iterator& pos, const Node& trg) = 0;
		virtual Result& remove(const Iterator& pos, const Node& trg) = 0;
		virtual Node& _get(const Iterator& pos) = 0;
		wcount getLength() const { return _length; }
		Node& get(const Iterator& pos) { return _get(pos); }
		virtual Iterator& getIterator() = 0;
		const Iterator& getIterator() const;
		Result& each(const Method& lambda);
		template <typename T>
		Result& each(T lambda);
		// 삽입가능한 타입을 말한다.
		// 생성시 한번 정해지면 변경이 불가능해야 한다.
		virtual Class& getTrait() { return TClass<Node>(); }

	protected:
		wcount _length;
	};
	class SolidContainer : public Container {
		wcount getSize() const { return _size; }
		virtual wcount resize(wcount newsize) = 0;

	protected:
		wcount _size;
	};
	class Array : public SolidContainer {
		class ArrayIterator : public Iterator {
		};
	};
	class List : public Container {
	};
	class Cell : public SolidContainer {
	};

	class Chain : public TCell<Container> {
		//	Control을 사용해서 Chain의 element인 Container들을 조작할 수 있다.
		class Control : public Container {
		};
	};

	template <typename S, typename T>
	class TContainer : public S {
		T& get(const Iterator& pos);
		virtual Class& getTrait() { return TClass<T>(); }
	};
	template <typename T>
	using TArray = TContainer<Array, T>;
	template <typename T>
	using TList = TContainer<List, T>;
	template <typename T>
	using TCell = TContainer<Cell, T>;

	//	MetaClass 컴포넌트	---------------------------------------
	class Type : public Object {
	};
	typedef TArray<Class> Classes;
	class Class : public Type {
		virtual const String& getName() const { return _name; }
		virtual const Classes& getSupers() const;
		virtual const Classes& getSubs() const;
		//	Shared Members: 모든 객체마다 share하는 클래스의 멤버들. 공유변수 및 Method가 여기에 속한다
		const Members& getShares() const { return _shares; }
		//	(Object) Dependent Members: 객체에 종속되는 멤버들. 객체마다 서로 다른 값을 갖는 멤버들로, 멤버변수가 여기에 속한다.
		const Members& getDependents() const { return _deps; }
		virtual Object instantiate() const = 0;
		virtual Node& call(const Message& msg);

		String _name;
		Array _shares;
		Array _deps;
		//	Trait가 Node다. 즉, Statement도, Class도 올 수 있다.
		//	_members는 _shares + _deps 로 구성된다.
	};
	template <typename T>
	class TInterfaceClass : public Type {
		virtual Object instantiate() const {
			//ERROR
			return Null();
		}
	};
	template <typename T>
	class TConcreteClass : public Type {
		virtual Object instantiate() const {
		}
	};
	//	Native 클래스들을 World에 visible하게 만들어주는 클래스.
	//	T::ClassSpecifier가 TConcrete혹은 TIneterface를 가리킨다.
	//  TClasser 자체는 World에 visible 하지 않다
	// 	모든 템플릿들은 World에 visible 하지 않다.
	template <typename T>
	class TClass : public T::ClassSpecifier {
	};
	class Method : public Type {
		virtual Result& execute();
	};
	class WorldMethod : public Method {
		Block _block;
	};
	class Statement : public Type {
		virtual Result& execute() = 0;
	};
	class InlineStatement : public Statement {
		Message _msg;
		Weak<Method> _method;
		// _this 포인터가 Node다. 이 Node에는 Statement, Method도 다 포함된다는 것이다.
		Weak<Object> _this;
	};
	class Block : public Statement {
		Array<Statement> _stmts;
	};

	//	기본 타입:	-----------------------------------------------
	//	객체, C++의 인스턴스를 말한다. 시스템에 여러개가 생길 수 있다.
	class Variable : public Node {
	};
	//	이름이 있다.
	class NamedVariable : public Variable {
		virtual String& getName() = 0;
		String _name;
	};
	//	자기만의 member를 가질 수 있다.
	class Object : public NamedVariable {
		Class _cls;
		virtual Container& getMembers() { return _members; }
        Object(Class& klass) {
            _class = klass;
            _variables = klass.getVariables();
            _members.chain(klass.getMethods());
            _members.chain(_variables);
        }
	    Members& getVariables() { return _member.getControl()[1]; }

		//	Member는 Class.members로부터 복사된다. _methods(share) + _variables(copy)
		Chain _members;
	};
	//	primitive 타입들은 속도가 중요하다. 최적화가 필요하다. Object로 해버리면 매번 members가 생성될 것이다.
	class Primitive : public Variable {
		virtual const String& getName() const {
			static String inner;
			return inner;
		}
	};
	class Number : public Primitive {
	};
	class Integer : public Number {
	};
	class Float : public Number {
	};
	class Result : public Primitive {
	};
	class Char : public Primitive {
	};
	class Null : public Primitive {
	};
	class Void : public Primitive {
	};
	// String은 밖에서 봤을때는 TCell<Char> 처럼 보여야한다.
	// 하지만 퍼포먼스 때문에 실제로는 char에대한 배열이여야 한다.
	// Container는 껍데기만 있다. 속을 wstring의 delegation으로 채운다.
	class String : public Container, private std::wstring {
	};
	class Members : public Array {
	};
	class Arguments : public Members {
	};
	//	World에 visible 하지 않으며(Node가 아님), Instance 관리도 필요없다(Instance가 아님).
	class Message : public Thing {
		String _name;
		Arguments _arguments;
	};
	//	Object를 바인딩하고 있으며 World에서는 Object와 분간이 가지 않는다. 즉, Reference의 T<클래스>는 없어야 한다. Object처럼 동작해야 한다.
	//	TString의 delegation한다.
	//	Bind와 Reference를 한데 묶을 수 없다(배열 같은 곳에) 하지만 World 코드 위에서 Bind를 사용하는 경우는 없을 것이다.
	class Reference : public NamedVariable {
		Reference();
		Reference(const Class& cls) : Super(cls) {}
		Object& get();
		wbool isBinded() const;

		virtual Container& getMembers() { return _obj->getMembers(); }
		TStrong<Object> _obj;
	};
	//	T는 Object보다 하위여야 한다.
	template <typename T>
	class TReference : public Reference {
		TReference() : Reference(TClass<T>()) {}
		//	virtual이 아니기에 hiding 되므로 에러가 아니다.
		T& get();
	};
    class Node : public Instance {
    public:
		virtual Node& call(const Message& msg)
        virtual Container& getMembers() {
			//	기본적으로 Class의 Member를 반환한다. 이렇게 하면 Node는 자신만의 변수를 갖지 못한다.
			return getClass().getMembers();
		}
		virtual Strong to(const Class& cls);
		virtual const String& getName() const = 0;
		virtual Result& setName(const String& newname) = 0;
    };

	class

	==================================================
    //  Object는 World의 객체다. 객체는 항상 객체라는 타입이다. A라는 클래스의 객체와 B라는 클래스의 객체는 Native적으로,
    //  동일한 클래스의 객체다. 바로 이부분이 헷갈리기 쉬운 부분이며 동시에 World의 재사용성을 높여주는 부분이기도 하다.

	//	RETURN_T=String& is by-ref and sharable.
	/* So, Above macro will expand like this,
	 *
	 * RET_T = "String&"
	 * NAME = "addString"
	 * __VA_ARGS__ = rest of arguments.
	 *
	 * class addStringMethod : public Method {
	 * 		W_DECL_CLASS(addStringMethod, Method)
	 *
	 * 		typedef Mashall<RET_T>::MashalledType ReturnType;
	 * 		ReturnType _return;
	 *
	 * public:
	 *		addStringMethod()
	 *			// Mashall<RET_T>::RefindType is String
	 *			// Mashall<RET_T>::MashalledType is Reference<String>
	 *			// Mashall<RET_T>::isReference is 1
	 *			// Mashall<RET_T>::isSharable is 1
	 *
	 * 			// Occupiable = Reference<Occupiable> 은, rhs의 Sharable의 값이 Occupiable로 들어간다
	 *			// 이는 Occupiable은 어떻게 해서라도 값vs값의 할당이 일어나야 하기 때문이다.
	 *			// 물론 Reference<Occupiable> = Occupiable의 경우에는 Reference::operator=()가 된다.
	 *			// 그래서 아래의 경우에는 원본이 Bind로 라이프사이클이 관리되고, 그것이 Sharable이든
	 *			// Occupiable이든 값은 return으로 들어갈 수 있다.
	 *			_return = Reference(Mashall<RET_T>::RefindType());
	 *
	 *			_arguments << Reference<MyFirstWorldModule>() // thisptr
	 *
	 *			char* __VA_ARGS_를 split하고, loop를 돌면서 적합한 TClass<T>를 만들어서 arguments
	 *			에 넣어야 한다. 이 것을 하는 도중에 T* arg,  T  *  args,  T  *args 같은 케이스들도
	 *			문제없이 파싱할 수 있어야 한다.
	 *
	 *			어떻게?
	 *
	 *
	 *			_fptr = &MyFirstWorldModule::addString;
	 *
	 *		}
	 *
	 *		String& (addStringMethod::*_fptr)(String&, __VA_ARGS_...);
	 *
	 * 		//	World에서 메소드를 실행하기 위한 가장 짦은 인터페이스이다.
	 *		//	Native를 위한 인자의 가공이 시작된다.
	 *		virtual Bind<Node> call(const Arguments& args) {
	 *			if(Mashall<RET_T>::sharable)
	 *				if(is_ref) // is_ref에는 Reference로 반환한경우도 포함이 되어야 한다.
	 *					return _return = (me->*_fptr)(args[0].to<String>(), args[1].to.... 재귀 );
	 *				else
	 *					//	RET_T는 Sharable인데, 값으로 반환한 경우다. 불가피하게 퍼포먼스가 소모.
	 *					return _return = (me->*_fptr)(args[0].to<String>(), args[1].to.... 재귀 ).clone();
	 *		}
	 * };
	 */
	#define WRD_DECL_2(T, S)	.......
	#define WRD_DECL_3(T, S, M)	\
		WRD_DECL_2(T,S)	\
	protected:	\
		static const Result& _onInitializeMethods(List<Method>& tray) {	\
			FOR_EACH()
		}

	//	사용법1:
	//		.HPP에서
	class MyFirstWorldModule : public Object {
		WRD_DECL_ONLY(MyFirstWorldModule, Object,
			String, addString, (String&, String&)
			//	조건1. ,로 구분한다.
			//	조건2. 인자명 없다.
		) // static onInitializeMethods() 구현된다.
			//	조건3. 시작과 끝 ()를 넣는다.

	public:
		String addString(String& arg1, String& arg2) {
			//	Reference의 사용방법1 :
			Reference<String> ret = new String(arg1 + arg2);
			//	방법2:
			Reference<String> ret = arg1.clone();
			*ret += arg2;
			//	방법3:
			Reference<String> ret = (arg1 + arg2).clone();
			//	방법4:
			Reference<String> ret = String::make();
			*ret = arg1 + arg2;

			return ret;
		}
	};
	//	.CPP 구현 없음.

	//	사용법2:
	//	.HPP에서
	class MyFirstWorldModule : public Object {
		WRD_DECL(MyFirstWorldModule, Object) // static onInitializeMethods(); 선언 된다.

	public:
		String addString(String& arg1, String& arg2); // 여기서 정의해도 상관없다.
	};
	//	.CPP에서
	WRD_DEF(MyFirstWorldModule,
		(String, addString, String&, String & const) // static onInitializeMethods() 구현들어간다.
	)
	String MyFirstWorldModule::addString(String& arg1, String & const arg2) {
		... dosomething ...
	}
}
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include "catch.hpp"

/* Include internals */
#include "cyclic.hpp"
/* And our tokenizer */
#include "tokenizers/strspn.h"
/* Include simhash */
#include "hash.hpp"

#include <string>
#include <stdint.h>

TEST_CASE("cyclic", "The cyclic hashing function stuff") {
    SECTION("rotation", "It can rotate integers by one bit") {
        /* Given these inputs... */
        uint64_t inputs[] = {
            0xDEADBEEFDEADBEEF, 0xAAAAAAAAAAAAAAAA, 0x5555555555555555
        };
        /* We should get these outputs */
        uint64_t outputs[] = {
            0xBD5B7DDFBD5B7DDF, 0x5555555555555555, 0xAAAAAAAAAAAAAAAA
        };
        /* How many examples do I have? */
        size_t count = 3;

        for (size_t i = 0; i < count; ++i) {
            REQUIRE(
                Simhash::Cyclic<uint64_t>::rotate(inputs[i]) == outputs[i]);
        }
    }

    SECTION("multiple rotation", "It can rotate by many bits") {
        REQUIRE(Simhash::Cyclic<uint64_t>::rotate(0xDEADBEEFDEADBEEF, 10)
            == 0xB6FBBF7AB6FBBF7A);
        REQUIRE(Simhash::Cyclic<uint64_t>::rotate(0xABCDEFFFABCDEFFF, 32)
            == 0xABCDEFFFABCDEFFF);
        REQUIRE(Simhash::Cyclic<uint64_t>::rotate(0xABCDEFFFABCDEFFF, 64)
            == 0xABCDEFFFABCDEFFF);
        /* Really large offsets should be rounded down and treated as ok */
        REQUIRE(Simhash::Cyclic<uint64_t>::rotate(0xABCDEFFFABCDEFFF, 1024)
            == 0xABCDEFFFABCDEFFF);
    }

    SECTION("cycling", "It can keep track of a cyclic hash correctly") {
        /* First, we'll instantiate a cyclic hasher with a window of 5 */
        Simhash::Cyclic<uint64_t> cyclic(5);
        /* Next, we're going to give this hash a sequence of longer than the
         * window, and then we'd like to make sure that the hashes that come
         * up are in fact different, and furthermore, that repeated sequences
         * that are sufficiently long will yield the same values */
        uint64_t values[] = {
            0xCAFEBABECAFEBABE,
            0xAAAAAAAAAAAAAAAA,
            0x5555555555555555,
            0xDEADBEEFDEADBEEF,
            0xFEEDEDFEEDEDFEED,
            0xBD5B7DDFBD5B7DDF,
            0xABEDABEDABEDABED,
            0xBADEBADEBADEBADE
        };
        const size_t count = 8;
        /* Now, we'll push each of these onto the cyclic hasher twice. The
         * first pass through, we expect the numbers to be different from the
         * second pass for the first four numbers. After that point, though,
         * the window should have sufficient time to reset */
        uint64_t results[2*count];
        for (size_t i = 0; i < 2; ++i) {
            for (size_t j = 0; j < count; ++j) {
                results[i*count+j] = cyclic.push(values[j]);
            }
        }
        REQUIRE(results[0] != results[ 8]); /* Unequal */
        REQUIRE(results[1] != results[ 9]);
        REQUIRE(results[2] != results[10]);
        REQUIRE(results[3] != results[11]);
        REQUIRE(results[4] == results[12]); /* Equal */
        REQUIRE(results[5] == results[13]);
        REQUIRE(results[6] == results[14]);
        REQUIRE(results[7] == results[15]);
    }
}

TEST_CASE("tokenizers", "We can get tokens from a string") {
    /* This is a string that we'd like to use for testing the tokenizer */
    const char* test_string = "what's new?How5is _ the ^# stuff";

    SECTION("strspn", "We can use the strspn tokenizer") {
        /* We need an instance of our actual tokenizer */
        Simhash::Strspn tokenizer;

        const char *current(NULL);
        const char *next(NULL);
        current = test_string;

        int64_t expected[] = {
            4, // 'what'
            1, // 's'
            3, // 'new'
            3, // 'How'
            2, // 'is'
            0, // '_'
            0, // ' '
            3, // 'the'
            0, // '^'
            0, // '#'
            0, // ' '
            5, // 'stuff'
        };

        for (size_t i = 0; i < 12; ++i) {
            next = tokenizer(current);
            REQUIRE((next - current) == expected[i]);
            current = next + 1;
        }

        /* Now we should be at the end */
        next = tokenizer(current);
        REQUIRE(next == NULL);
    }
}

TEST_CASE("simhash", "We can perform simhash") {
    std::string jabberwocky = "Twas brillig, and the slithy toves"
        "  Did gyre and gimble in the wabe:"
        "All mimsy were the borogoves,"
        "  And the mome raths outgrabe."
        "Beware the Jabberwock, my son!"
        "  The jaws that bite, the claws that catch!"
        "Beware the Jubjub bird, and shun"
        "  The frumious Bandersnatch!"
        "He took his vorpal sword in hand:"
        "  Long time the manxome foe he sought --"
        "So rested he by the Tumtum tree,"
        "  And stood awhile in thought."
        "And, as in uffish thought he stood,"
        "  The Jabberwock, with eyes of flame,"
        "Came whiffling through the tulgey wood,"
        "  And burbled as it came!"
        "One, two! One, two! And through and through"
        "  The vorpal blade went snicker-snack!"
        "He left it dead, and with its head"
        "  He went galumphing back."
        "And, has thou slain the Jabberwock?"
        "  Come to my arms, my beamish boy!"
        "O frabjous day! Callooh! Callay!'"
        "  He chortled in his joy.";

    std::string pope = "There once was a man named Pope"
        "who loved an oscilloscope."
        "  and the cyclical trace"
        "  of their carnal embrace"
        "had a damned-near-infinite slope";

    SECTION("Near-duplicates", "Can find near-duplicates") {
        /* Let's instantiate a simhasher */
        Simhash::Simhash<> hasher;
        uint64_t a = hasher(jabberwocky.c_str(), jabberwocky.length());
        /* Update jabberwocky to include who wrote it */
        jabberwocky += " - Lewis Carroll in 'Alice In Wonderland'";
        uint64_t b = hasher(jabberwocky.c_str(), jabberwocky.length());

        /* Now, make sure that the number of bits by which they differ is
         * small */
        a = a ^ b;
        size_t count = 0;
        while (a) {
            a = a & (a - 1); ++count;
        }
        REQUIRE(count != 0);
        REQUIRE(count <= 3);

        /* Now, let's make sure that we can verify that two strings are
         * nothing alike */
        a = hasher(pope.c_str(), pope.length());
        a = a ^ b;
        count = 0;
        while (a) {
            a = a & (a - 1); ++count;
        }
        REQUIRE(count > 5);
    }
}
<commit_msg>Drop trailing whitespace.<commit_after>#define CATCH_CONFIG_MAIN
#include "catch.hpp"

/* Include internals */
#include "cyclic.hpp"
/* And our tokenizer */
#include "tokenizers/strspn.h"
/* Include simhash */
#include "hash.hpp"

#include <string>
#include <stdint.h>

TEST_CASE("cyclic", "The cyclic hashing function stuff") {
    SECTION("rotation", "It can rotate integers by one bit") {
        /* Given these inputs... */
        uint64_t inputs[] = {
            0xDEADBEEFDEADBEEF, 0xAAAAAAAAAAAAAAAA, 0x5555555555555555
        };
        /* We should get these outputs */
        uint64_t outputs[] = {
            0xBD5B7DDFBD5B7DDF, 0x5555555555555555, 0xAAAAAAAAAAAAAAAA
        };
        /* How many examples do I have? */
        size_t count = 3;

        for (size_t i = 0; i < count; ++i) {
            REQUIRE(
                Simhash::Cyclic<uint64_t>::rotate(inputs[i]) == outputs[i]);
        }
    }

    SECTION("multiple rotation", "It can rotate by many bits") {
        REQUIRE(Simhash::Cyclic<uint64_t>::rotate(0xDEADBEEFDEADBEEF, 10)
            == 0xB6FBBF7AB6FBBF7A);
        REQUIRE(Simhash::Cyclic<uint64_t>::rotate(0xABCDEFFFABCDEFFF, 32)
            == 0xABCDEFFFABCDEFFF);
        REQUIRE(Simhash::Cyclic<uint64_t>::rotate(0xABCDEFFFABCDEFFF, 64)
            == 0xABCDEFFFABCDEFFF);
        /* Really large offsets should be rounded down and treated as ok */
        REQUIRE(Simhash::Cyclic<uint64_t>::rotate(0xABCDEFFFABCDEFFF, 1024)
            == 0xABCDEFFFABCDEFFF);
    }

    SECTION("cycling", "It can keep track of a cyclic hash correctly") {
        /* First, we'll instantiate a cyclic hasher with a window of 5 */
        Simhash::Cyclic<uint64_t> cyclic(5);
        /* Next, we're going to give this hash a sequence of longer than the
         * window, and then we'd like to make sure that the hashes that come
         * up are in fact different, and furthermore, that repeated sequences
         * that are sufficiently long will yield the same values */
        uint64_t values[] = {
            0xCAFEBABECAFEBABE,
            0xAAAAAAAAAAAAAAAA,
            0x5555555555555555,
            0xDEADBEEFDEADBEEF,
            0xFEEDEDFEEDEDFEED,
            0xBD5B7DDFBD5B7DDF,
            0xABEDABEDABEDABED,
            0xBADEBADEBADEBADE
        };
        const size_t count = 8;
        /* Now, we'll push each of these onto the cyclic hasher twice. The
         * first pass through, we expect the numbers to be different from the
         * second pass for the first four numbers. After that point, though,
         * the window should have sufficient time to reset */
        uint64_t results[2*count];
        for (size_t i = 0; i < 2; ++i) {
            for (size_t j = 0; j < count; ++j) {
                results[i*count+j] = cyclic.push(values[j]);
            }
        }
        REQUIRE(results[0] != results[ 8]); /* Unequal */
        REQUIRE(results[1] != results[ 9]);
        REQUIRE(results[2] != results[10]);
        REQUIRE(results[3] != results[11]);
        REQUIRE(results[4] == results[12]); /* Equal */
        REQUIRE(results[5] == results[13]);
        REQUIRE(results[6] == results[14]);
        REQUIRE(results[7] == results[15]);
    }
}

TEST_CASE("tokenizers", "We can get tokens from a string") {
    /* This is a string that we'd like to use for testing the tokenizer */
    const char* test_string = "what's new?How5is _ the ^# stuff";

    SECTION("strspn", "We can use the strspn tokenizer") {
        /* We need an instance of our actual tokenizer */
        Simhash::Strspn tokenizer;

        const char *current(NULL);
        const char *next(NULL);
        current = test_string;

        int64_t expected[] = {
            4, // 'what'
            1, // 's'
            3, // 'new'
            3, // 'How'
            2, // 'is'
            0, // '_'
            0, // ' '
            3, // 'the'
            0, // '^'
            0, // '#'
            0, // ' '
            5, // 'stuff'
        };

        for (size_t i = 0; i < 12; ++i) {
            next = tokenizer(current);
            REQUIRE((next - current) == expected[i]);
            current = next + 1;
        }

        /* Now we should be at the end */
        next = tokenizer(current);
        REQUIRE(next == NULL);
    }
}

TEST_CASE("simhash", "We can perform simhash") {
    std::string jabberwocky = "Twas brillig, and the slithy toves"
        "  Did gyre and gimble in the wabe:"
        "All mimsy were the borogoves,"
        "  And the mome raths outgrabe."
        "Beware the Jabberwock, my son!"
        "  The jaws that bite, the claws that catch!"
        "Beware the Jubjub bird, and shun"
        "  The frumious Bandersnatch!"
        "He took his vorpal sword in hand:"
        "  Long time the manxome foe he sought --"
        "So rested he by the Tumtum tree,"
        "  And stood awhile in thought."
        "And, as in uffish thought he stood,"
        "  The Jabberwock, with eyes of flame,"
        "Came whiffling through the tulgey wood,"
        "  And burbled as it came!"
        "One, two! One, two! And through and through"
        "  The vorpal blade went snicker-snack!"
        "He left it dead, and with its head"
        "  He went galumphing back."
        "And, has thou slain the Jabberwock?"
        "  Come to my arms, my beamish boy!"
        "O frabjous day! Callooh! Callay!'"
        "  He chortled in his joy.";

    std::string pope = "There once was a man named Pope"
        "who loved an oscilloscope."
        "  and the cyclical trace"
        "  of their carnal embrace"
        "had a damned-near-infinite slope";

    SECTION("Near-duplicates", "Can find near-duplicates") {
        /* Let's instantiate a simhasher */
        Simhash::Simhash<> hasher;
        uint64_t a = hasher(jabberwocky.c_str(), jabberwocky.length());
        /* Update jabberwocky to include who wrote it */
        jabberwocky += " - Lewis Carroll in 'Alice In Wonderland'";
        uint64_t b = hasher(jabberwocky.c_str(), jabberwocky.length());

        /* Now, make sure that the number of bits by which they differ is
         * small */
        a = a ^ b;
        size_t count = 0;
        while (a) {
            a = a & (a - 1); ++count;
        }
        REQUIRE(count != 0);
        REQUIRE(count <= 3);

        /* Now, let's make sure that we can verify that two strings are
         * nothing alike */
        a = hasher(pope.c_str(), pope.length());
        a = a ^ b;
        count = 0;
        while (a) {
            a = a & (a - 1); ++count;
        }
        REQUIRE(count > 5);
    }
}
<|endoftext|>


<commit_before>/*************************************************************************/
/* spdlog - an extremely fast and easy to use c++11 logging library.     */
/* Copyright (c) 2014 Gabi Melman.                                       */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

//
// bench.cpp : spdlog benchmarks
//
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <atomic>
#include "spdlog/spdlog.h"
#include "spdlog/async_logger.h"
#include "spdlog/sinks/file_sinks.h"
#include "spdlog/sinks/null_sink.h"
#include "utils.h"

using namespace std;
using namespace std::chrono;
using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;

void bench(int howmany, std::shared_ptr<spdlog::logger> log);
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);

int main(int argc, char* argv[])
{

    int howmany = 1000000;
    int threads = 10;
    bool auto_flush = false;
    int file_size = 30 * 1024 * 1024;
    int rotating_files = 5;

    try
    {

        if(argc > 1)
            howmany = atoi(argv[1]);
        if (argc > 2)
            threads =   atoi(argv[2]);

        cout << "*******************************************************************************\n";
        cout << "Single thread, " << format(howmany)  << " iterations, auto flush=" << auto_flush << endl;
        cout << "*******************************************************************************\n";

        auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st", file_size, rotating_files, auto_flush);
        bench(howmany, rotating_st);
        auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st", auto_flush);
        bench(howmany, daily_st);
        bench(howmany, spdlog::create<null_sink_st>("null_st"));

        cout << "\n*******************************************************************************\n";
        cout << threads << " threads sharing same logger, " << format(howmany)  << " iterations, auto_flush=" << auto_flush << endl;
        cout << "*******************************************************************************\n";

        auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt", file_size, rotating_files, auto_flush);
        bench_mt(howmany, rotating_mt, threads);

        auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt", auto_flush);
        bench_mt(howmany, daily_mt, threads);
        bench(howmany, spdlog::create<null_sink_st>("null_mt"));

        cout << "\n*******************************************************************************\n";
        cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations, auto_flush=" << auto_flush << endl;
        cout << "*******************************************************************************\n";

        spdlog::set_async_mode(howmany);
        auto daily_st_async = spdlog::daily_logger_st("daily_async", "logs/daily_async", auto_flush);
        bench_mt(howmany, daily_st_async, threads);

        spdlog::stop();

    }
    catch (std::exception &ex)
    {
        std::cerr << "Error: " << ex.what() << std::endl;
        perror("Last error");
    }
    return 0;
}

void bench(int howmany, std::shared_ptr<spdlog::logger> log)
{
    cout << log->name() << "...\t\t" << flush;
    auto start = system_clock::now();
    for (auto i = 0; i < howmany; ++i)
    {
        log->info("Hello logger: msg number {}", i);
    }

    auto delta = system_clock::now() - start;
    auto delta_d = duration_cast<duration<double>> (delta).count();
    cout << format(int(howmany / delta_d)) << "/sec" << endl;
}

void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{

    cout << log->name() << "...\t\t" << flush;
    std::atomic<int > msg_counter {0};
    vector<thread> threads;
    auto start = system_clock::now();
    for (int t = 0; t < thread_count; ++t)
    {
        threads.push_back(std::thread([&]()
        {
            for(;;)
            {
                int counter = ++msg_counter;
                if (counter > howmany) break;
                log->info("Hello logger: msg number ") << counter;
            }
        }));
    }

    for(auto &t:threads)
    {
        t.join();
    };

    auto delta = system_clock::now() - start;
    auto delta_d = duration_cast<duration<double>> (delta).count();
    cout << format(int(howmany / delta_d)) << "/sec" << endl;
}

<commit_msg>bench fix<commit_after>/*************************************************************************/
/* spdlog - an extremely fast and easy to use c++11 logging library.     */
/* Copyright (c) 2014 Gabi Melman.                                       */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

//
// bench.cpp : spdlog benchmarks
//
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <atomic>
#include "spdlog/spdlog.h"
#include "spdlog/async_logger.h"
#include "spdlog/sinks/file_sinks.h"
#include "spdlog/sinks/null_sink.h"
#include "utils.h"

using namespace std;
using namespace std::chrono;
using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;

void bench(int howmany, std::shared_ptr<spdlog::logger> log);
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);

int main(int argc, char* argv[])
{

    int howmany = 1000000;
    int threads = 10;
    bool auto_flush = false;
    int file_size = 30 * 1024 * 1024;
    int rotating_files = 5;

    try
    {

        if(argc > 1)
            howmany = atoi(argv[1]);
        if (argc > 2)
            threads =   atoi(argv[2]);

        cout << "*******************************************************************************\n";
        cout << "Single thread, " << format(howmany)  << " iterations, auto flush=" << auto_flush << endl;
        cout << "*******************************************************************************\n";

        auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st", file_size, rotating_files, auto_flush);
        bench(howmany, rotating_st);
        auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st", auto_flush);
        bench(howmany, daily_st);
        bench(howmany, spdlog::create<null_sink_st>("null_st"));

        cout << "\n*******************************************************************************\n";
        cout << threads << " threads sharing same logger, " << format(howmany)  << " iterations, auto_flush=" << auto_flush << endl;
        cout << "*******************************************************************************\n";

        auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt", file_size, rotating_files, auto_flush);
        bench_mt(howmany, rotating_mt, threads);

        auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt", auto_flush);
        bench_mt(howmany, daily_mt, threads);
        bench(howmany, spdlog::create<null_sink_st>("null_mt"));

        cout << "\n*******************************************************************************\n";
        cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations, auto_flush=" << auto_flush << endl;
        cout << "*******************************************************************************\n";

        spdlog::set_async_mode(howmany);
        auto daily_st_async = spdlog::daily_logger_st("daily_async", "logs/daily_async", auto_flush);
        bench_mt(howmany, daily_st_async, threads);

        spdlog::stop();

    }
    catch (std::exception &ex)
    {
        std::cerr << "Error: " << ex.what() << std::endl;
        perror("Last error");
    }
    return 0;
}

void bench(int howmany, std::shared_ptr<spdlog::logger> log)
{
    cout << log->name() << "...\t\t" << flush;
    auto start = system_clock::now();
    for (auto i = 0; i < howmany; ++i)
    {
        log->info("Hello logger: msg number {}", i);
    }

    auto delta = system_clock::now() - start;
    auto delta_d = duration_cast<duration<double>> (delta).count();
    cout << format(int(howmany / delta_d)) << "/sec" << endl;
}

void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{

    cout << log->name() << "...\t\t" << flush;
    std::atomic<int > msg_counter {0};
    vector<thread> threads;
    auto start = system_clock::now();
    for (int t = 0; t < thread_count; ++t)
    {
        threads.push_back(std::thread([&]()
        {
            for(;;)
            {
                int counter = ++msg_counter;
                if (counter > howmany) break;
                log->info("Hello logger: msg number {}", counter);
            }
        }));
    }

    for(auto &t:threads)
    {
        t.join();
    };

    auto delta = system_clock::now() - start;
    auto delta_d = duration_cast<duration<double>> (delta).count();
    cout << format(int(howmany / delta_d)) << "/sec" << endl;
}

<|endoftext|>


<commit_before>// Catch
#define CATCH_CONFIG_RUNNER
#include <catch.hpp>

// C++ standard library
#include <string>
#include <stdexcept>
#include <iostream>

// Mantella
#include <mantella>

std::string testDirectory;

int main(const int argc, const char* argv[]) {
  try {
    if (argc != 2) {
      throw std::invalid_argument("The location of the test directory must be added to the command line.");
    }

    testDirectory = argv[1];

    mant::Rng::setSeed(123456789);

    return Catch::Session().run();
  } catch(const std::exception& exception) {
    std::cout << exception.what();
  }
}
<commit_msg>Init MPI for tests (if requested)<commit_after>// Catch
#define CATCH_CONFIG_RUNNER
#include <catch.hpp>

// C++ standard library
#include <string>
#include <stdexcept>
#include <iostream>

// Mantella
#include <mantella>

std::string testDirectory;

int main(int argc, char* argv[]) {
#if defined(SUPPORT_MPI)
  MPI_Init(&argc, &argv);
#endif

  try {
    if (argc != 2) {
      throw std::invalid_argument("The location of the test directory must be added to the command line.");
    }

    testDirectory = argv[1];

    mant::Rng::setSeed(123456789);

    return Catch::Session().run();
  } catch(const std::exception& exception) {
    std::cout << exception.what();
  }

#if defined(SUPPORT_MPI)
  MPI_Finalize();
#endif
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2009, Arvid Norberg
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 the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <ctime>
#include <string>
#include <cstdio>
#include <boost/limits.hpp>
#include <boost/version.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/time.hpp"

#ifndef _WIN32
#include <unistd.h>
#endif

namespace libtorrent
{
	namespace aux
	{
		// used to cache the current time
		// every 100 ms. This is cheaper
		// than a system call and can be
		// used where more accurate time
		// is not necessary
		ptime g_current_time;
	}

	ptime const& TORRENT_EXPORT time_now() { return aux::g_current_time; }

	char const* time_now_string()
	{
//		time_t t = std::time(0);
//		tm* timeinfo = std::localtime(&t);
//		static char str[200];
//		std::strftime(str, 200, "%b %d %X", timeinfo);
//		return str;

		static const ptime start = time_now_hires();
		static char ret[200];
		int t = total_milliseconds(time_now_hires() - start);
		int h = t / 1000 / 60 / 60;
		t -= h * 60 * 60 * 1000;
		int m = t / 1000 / 60;
		t -= m * 60 * 1000;
		int s = t / 1000;
		t -= s * 1000;
		int ms = t;
		snprintf(ret, sizeof(ret), "%02d:%02d:%02d.%03d", h, m, s, ms);
		return ret;
	}

	std::string log_time()
	{
		static const ptime start = time_now_hires();
		char ret[200];
		snprintf(ret, sizeof(ret), "%"PRId64, total_microseconds(time_now_hires() - start));
		return ret;
	}
}

#if defined TORRENT_USE_BOOST_DATE_TIME

#include <boost/date_time/microsec_time_clock.hpp>

namespace libtorrent
{
	ptime time_now_hires()
	{ return boost::date_time::microsec_clock<ptime>::universal_time(); }
	ptime min_time()
	{ return boost::posix_time::ptime(boost::posix_time::min_date_time); }
	ptime max_time()
	{ return boost::posix_time::ptime(boost::posix_time::max_date_time); }
	time_duration seconds(int s) { return boost::posix_time::seconds(s); }
	time_duration milliseconds(int s) { return boost::posix_time::milliseconds(s); }
	time_duration microsec(int s) { return boost::posix_time::microsec(s); }
	time_duration minutes(int s) { return boost::posix_time::minutes(s); }
	time_duration hours(int s) { return boost::posix_time::hours(s); }

	int total_seconds(time_duration td)
	{ return td.total_seconds(); }
	int total_milliseconds(time_duration td)
	{ return td.total_milliseconds(); }
	boost::int64_t total_microseconds(time_duration td)
	{ return td.total_microseconds(); }
}

#else // TORRENT_USE_BOOST_DATE_TIME

namespace libtorrent
{
	ptime min_time() { return ptime(0); }
	ptime max_time() { return ptime((std::numeric_limits<boost::uint64_t>::max)()); }
}

#if defined TORRENT_USE_ABSOLUTE_TIME

#include <mach/mach_time.h>
#include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp"

// high precision timer for darwin intel and ppc

namespace libtorrent
{
	ptime time_now_hires()
	{
		static mach_timebase_info_data_t timebase_info = {0,0};
		if (timebase_info.denom == 0)
			mach_timebase_info(&timebase_info);
		boost::uint64_t at = mach_absolute_time();
		// make sure we don't overflow
		TORRENT_ASSERT((at >= 0 && at >= at / 1000 * timebase_info.numer / timebase_info.denom)
			|| (at < 0 && at < at / 1000 * timebase_info.numer / timebase_info.denom));
		return ptime(at / 1000 * timebase_info.numer / timebase_info.denom);
	}
}
#elif defined TORRENT_USE_QUERY_PERFORMANCE_TIMER

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include "libtorrent/assert.hpp"

namespace libtorrent
{
	namespace aux
	{
		boost::int64_t performance_counter_to_microseconds(boost::int64_t pc)
		{
			static LARGE_INTEGER performace_counter_frequency = {0,0};
			if (performace_counter_frequency.QuadPart == 0)
				QueryPerformanceFrequency(&performace_counter_frequency);

#ifdef TORRENT_DEBUG
			// make sure we don't overflow
			boost::int64_t ret = (pc * 1000 / performace_counter_frequency.QuadPart) * 1000;
			TORRENT_ASSERT((pc >= 0 && pc >= ret) || (pc < 0 && pc < ret));
#endif
			return (pc * 1000 / performace_counter_frequency.QuadPart) * 1000;
		}

		boost::int64_t microseconds_to_performance_counter(boost::int64_t ms)
		{
			static LARGE_INTEGER performace_counter_frequency = {0,0};
			if (performace_counter_frequency.QuadPart == 0)
				QueryPerformanceFrequency(&performace_counter_frequency);
#ifdef TORRENT_DEBUG
			// make sure we don't overflow
			boost::int64_t ret = (ms / 1000) * performace_counter_frequency.QuadPart / 1000;
			TORRENT_ASSERT((ms >= 0 && ms <= ret)
				|| (ms < 0 && ms > ret));
#endif
			return (ms / 1000) * performace_counter_frequency.QuadPart / 1000;
		}
	}

	ptime time_now_hires()
	{
		LARGE_INTEGER now;
		QueryPerformanceCounter(&now);
		return ptime(now.QuadPart);
	}
}

#elif defined TORRENT_USE_CLOCK_GETTIME

#include <time.h>
#include "libtorrent/assert.hpp"

namespace libtorrent
{
	ptime time_now_hires()
	{
		timespec ts;
		clock_gettime(CLOCK_MONOTONIC, &ts);
		return ptime(boost::uint64_t(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000);
	}
}

#elif defined TORRENT_USE_SYSTEM_TIME

#include <kernel/OS.h>

namespace libtorrent
{
	ptime time_now_hires()
	{ return ptime(system_time()); }
}

#endif // TORRENT_USE_SYSTEM_TIME

#endif // TORRENT_USE_BOOST_DATE_TIME

<commit_msg>fix windows DLL build<commit_after>/*

Copyright (c) 2009, Arvid Norberg
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 the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <ctime>
#include <string>
#include <cstdio>
#include <boost/limits.hpp>
#include <boost/version.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/time.hpp"

#ifndef _WIN32
#include <unistd.h>
#endif

namespace libtorrent
{
	namespace aux
	{
		// used to cache the current time
		// every 100 ms. This is cheaper
		// than a system call and can be
		// used where more accurate time
		// is not necessary
		ptime g_current_time;
	}

	TORRENT_EXPORT ptime const& time_now() { return aux::g_current_time; }

	char const* time_now_string()
	{
//		time_t t = std::time(0);
//		tm* timeinfo = std::localtime(&t);
//		static char str[200];
//		std::strftime(str, 200, "%b %d %X", timeinfo);
//		return str;

		static const ptime start = time_now_hires();
		static char ret[200];
		int t = total_milliseconds(time_now_hires() - start);
		int h = t / 1000 / 60 / 60;
		t -= h * 60 * 60 * 1000;
		int m = t / 1000 / 60;
		t -= m * 60 * 1000;
		int s = t / 1000;
		t -= s * 1000;
		int ms = t;
		snprintf(ret, sizeof(ret), "%02d:%02d:%02d.%03d", h, m, s, ms);
		return ret;
	}

	std::string log_time()
	{
		static const ptime start = time_now_hires();
		char ret[200];
		snprintf(ret, sizeof(ret), "%"PRId64, total_microseconds(time_now_hires() - start));
		return ret;
	}
}

#if defined TORRENT_USE_BOOST_DATE_TIME

#include <boost/date_time/microsec_time_clock.hpp>

namespace libtorrent
{
	ptime time_now_hires()
	{ return boost::date_time::microsec_clock<ptime>::universal_time(); }
	ptime min_time()
	{ return boost::posix_time::ptime(boost::posix_time::min_date_time); }
	ptime max_time()
	{ return boost::posix_time::ptime(boost::posix_time::max_date_time); }
	time_duration seconds(int s) { return boost::posix_time::seconds(s); }
	time_duration milliseconds(int s) { return boost::posix_time::milliseconds(s); }
	time_duration microsec(int s) { return boost::posix_time::microsec(s); }
	time_duration minutes(int s) { return boost::posix_time::minutes(s); }
	time_duration hours(int s) { return boost::posix_time::hours(s); }

	int total_seconds(time_duration td)
	{ return td.total_seconds(); }
	int total_milliseconds(time_duration td)
	{ return td.total_milliseconds(); }
	boost::int64_t total_microseconds(time_duration td)
	{ return td.total_microseconds(); }
}

#else // TORRENT_USE_BOOST_DATE_TIME

namespace libtorrent
{
	ptime min_time() { return ptime(0); }
	ptime max_time() { return ptime((std::numeric_limits<boost::uint64_t>::max)()); }
}

#if defined TORRENT_USE_ABSOLUTE_TIME

#include <mach/mach_time.h>
#include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp"

// high precision timer for darwin intel and ppc

namespace libtorrent
{
	ptime time_now_hires()
	{
		static mach_timebase_info_data_t timebase_info = {0,0};
		if (timebase_info.denom == 0)
			mach_timebase_info(&timebase_info);
		boost::uint64_t at = mach_absolute_time();
		// make sure we don't overflow
		TORRENT_ASSERT((at >= 0 && at >= at / 1000 * timebase_info.numer / timebase_info.denom)
			|| (at < 0 && at < at / 1000 * timebase_info.numer / timebase_info.denom));
		return ptime(at / 1000 * timebase_info.numer / timebase_info.denom);
	}
}
#elif defined TORRENT_USE_QUERY_PERFORMANCE_TIMER

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include "libtorrent/assert.hpp"

namespace libtorrent
{
	namespace aux
	{
		boost::int64_t performance_counter_to_microseconds(boost::int64_t pc)
		{
			static LARGE_INTEGER performace_counter_frequency = {0,0};
			if (performace_counter_frequency.QuadPart == 0)
				QueryPerformanceFrequency(&performace_counter_frequency);

#ifdef TORRENT_DEBUG
			// make sure we don't overflow
			boost::int64_t ret = (pc * 1000 / performace_counter_frequency.QuadPart) * 1000;
			TORRENT_ASSERT((pc >= 0 && pc >= ret) || (pc < 0 && pc < ret));
#endif
			return (pc * 1000 / performace_counter_frequency.QuadPart) * 1000;
		}

		boost::int64_t microseconds_to_performance_counter(boost::int64_t ms)
		{
			static LARGE_INTEGER performace_counter_frequency = {0,0};
			if (performace_counter_frequency.QuadPart == 0)
				QueryPerformanceFrequency(&performace_counter_frequency);
#ifdef TORRENT_DEBUG
			// make sure we don't overflow
			boost::int64_t ret = (ms / 1000) * performace_counter_frequency.QuadPart / 1000;
			TORRENT_ASSERT((ms >= 0 && ms <= ret)
				|| (ms < 0 && ms > ret));
#endif
			return (ms / 1000) * performace_counter_frequency.QuadPart / 1000;
		}
	}

	ptime time_now_hires()
	{
		LARGE_INTEGER now;
		QueryPerformanceCounter(&now);
		return ptime(now.QuadPart);
	}
}

#elif defined TORRENT_USE_CLOCK_GETTIME

#include <time.h>
#include "libtorrent/assert.hpp"

namespace libtorrent
{
	ptime time_now_hires()
	{
		timespec ts;
		clock_gettime(CLOCK_MONOTONIC, &ts);
		return ptime(boost::uint64_t(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000);
	}
}

#elif defined TORRENT_USE_SYSTEM_TIME

#include <kernel/OS.h>

namespace libtorrent
{
	ptime time_now_hires()
	{ return ptime(system_time()); }
}

#endif // TORRENT_USE_SYSTEM_TIME

#endif // TORRENT_USE_BOOST_DATE_TIME

<|endoftext|>


<commit_before>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkImageDecoder.h"
#include "SkNinePatch.h"
#include "SkPaint.h"
#include "SkUnPreMultiply.h"

class NinePatchView : public SampleView {
public:
    SkBitmap fBM;

	NinePatchView() {
        SkImageDecoder::DecodeFile("/skimages/btn_default_normal_disable.9.png", &fBM);

        // trim off the edge guide-lines
        SkBitmap tmp;
        SkIRect r;
        r.set(1, 1, fBM.width() - 1, fBM.height() - 1);
        fBM.extractSubset(&tmp, r);
        fBM.swap(tmp);

        fX = SkIntToScalar(fBM.width());
        fY = 0;
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "NinePatch");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    virtual void onDrawBackground(SkCanvas* canvas) {
        SkPaint p;
        p.setDither(true);
        p.setColor(0xFF909090);
        canvas->drawPaint(p);
    }

    static void test_rects(SkCanvas* canvas, const SkBitmap& bm, const SkPaint* paint) {
        static const SkIRect src[] = {
            { 0, 0, 18, 34 },
            { 18, 0, 19, 34 },
            { 19, 0, 36, 34 },
            { 0, 34, 18, 35 },
            { 18, 34, 19, 35 },
            { 19, 34, 36, 35 },
            { 0, 35, 18, 72 },
            { 18, 35, 19, 72 },
            { 19, 35, 36, 72 },
        };
        static const SkRect dst[] = {
            { 0, 0, 18, 34 },
            { 18, 0, 283, 34 },
            { 283, 0, 300, 34 },
            { 0, 34, 18, 163 },
            { 18, 34, 283, 163 },
            { 283, 34, 300, 163 },
            { 0, 163, 18, 200 },
            { 18, 163, 283, 200 },
            { 283, 163, 300, 200 },
        };
        for (size_t i = 0; i < SK_ARRAY_COUNT(src); i++) {
            canvas->drawBitmapRect(bm, &src[i], dst[i], paint);
        }
    }

    virtual void onDrawContent(SkCanvas* canvas) {
        canvas->drawBitmap(fBM, 0, 0);

        SkIRect margins;
        SkRect  dst;
        int d = 25;

        margins.set(d, d, d, d);
        margins.fLeft   = fBM.width()/2 - 1;
        margins.fTop    = fBM.height()/2 - 1;
        margins.fRight  = fBM.width() - margins.fLeft - 1;
        margins.fBottom = fBM.height() - margins.fTop - 1;

   //     canvas->translate(fX/5, fY/5);
        canvas->translate(0, 76);

        dst.set(0, 0, SkIntToScalar(200), SkIntToScalar(200));

        SkPaint paint;
        paint.setAntiAlias(false);
        paint.setDither(true);
        paint.setFilterBitmap(false);
    //    SkNinePatch::DrawNine(canvas, dst, fBM, margins, &paint);
        test_rects(canvas, fBM, &paint);
    }

    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
        fX = x / 1.5f;
        fY = y / 1.5f;
        fX = x; fY = y;
        this->inval(NULL);
        return this->INHERITED::onFindClickHandler(x, y);
    }
private:
    SkScalar fX, fY;
    typedef SampleView INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory() { return new NinePatchView; }
static SkViewRegister reg(MyFactory);

<commit_msg>update sample to test stretching + and - amounds<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkImageDecoder.h"
#include "SkNinePatch.h"
#include "SkPaint.h"
#include "SkUnPreMultiply.h"
#include "SkGpuDevice.h"

static void make_bitmap(SkBitmap* bitmap, GrContext* ctx, SkIRect* center) {
    SkDevice* dev;
    SkCanvas canvas;

    const int kFixed = 28;
    const int kStretchy = 8;
    const int kSize = 2*kFixed + kStretchy;

    if (ctx) {
        dev = new SkGpuDevice(ctx, SkBitmap::kARGB_8888_Config, kSize, kSize);
        *bitmap = dev->accessBitmap(false);
    } else {
        bitmap->setConfig(SkBitmap::kARGB_8888_Config, kSize, kSize);
        bitmap->allocPixels();
        dev = new SkDevice(*bitmap);
    }

    canvas.setDevice(dev)->unref();
    canvas.clear(0);

    SkRect r = SkRect::MakeWH(SkIntToScalar(kSize), SkIntToScalar(kSize));
    const SkScalar strokeWidth = SkIntToScalar(6);
    const SkScalar radius = SkIntToScalar(kFixed) - strokeWidth/2;

    center->setXYWH(kFixed, kFixed, kStretchy, kStretchy);

    SkPaint paint;
    paint.setAntiAlias(true);

#if 0
    r.inset(strokeWidth/2, strokeWidth/2);

    paint.setColor(SK_ColorBLUE);
    canvas.drawRoundRect(r, radius, radius, paint);
    paint.setColor(SK_ColorRED);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(strokeWidth);
    canvas.drawRoundRect(r, radius, radius, paint);
#else
    paint.setColor(0xFFFF0000);
    canvas.drawRoundRect(r, radius, radius, paint);
    r.setXYWH(SkIntToScalar(kFixed), 0, SkIntToScalar(kStretchy), SkIntToScalar(kSize));
    paint.setColor(0x8800FF00);
    canvas.drawRect(r, paint);
    r.setXYWH(0, SkIntToScalar(kFixed), SkIntToScalar(kSize), SkIntToScalar(kStretchy));
    paint.setColor(0x880000FF);
    canvas.drawRect(r, paint);
#endif
}

class NinePatchView : public SampleView {
public:
	NinePatchView() {}

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "NinePatch");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    static void drawNine(SkCanvas* canvas, const SkRect& dst, const SkBitmap& bm,
                         const SkIRect& center, const SkPaint* paint) {
        SkIRect margin;
        margin.set(center.fLeft, center.fTop, bm.width() - center.fRight,
                   bm.height() - center.fBottom);
        SkNinePatch::DrawNine(canvas, dst, bm, margin, paint);
    }

    virtual void onDrawContent(SkCanvas* canvas) {
        SkBitmap bm;
        SkIRect center;
        make_bitmap(&bm, SampleCode::GetGr(), &center);

        // amount of bm that should not be stretched (unless we have to)
        const SkScalar fixed = SkIntToScalar(bm.width() - center.width());

        const SkTSize<SkScalar> size[] = {
            { fixed * 4 / 5, fixed * 4 / 5 },   // shrink in both axes
            { fixed * 4 / 5, fixed * 4 },       // shrink in X
            { fixed * 4,     fixed * 4 / 5 },   // shrink in Y
            { fixed * 4,     fixed * 4 }
        };

        canvas->drawBitmap(bm, SkIntToScalar(10), SkIntToScalar(10), NULL);

        SkScalar x = SkIntToScalar(100);
        SkScalar y = SkIntToScalar(100);

        SkPaint paint;
        paint.setFilterBitmap(true);

        for (int iy = 0; iy < 2; ++iy) {
            for (int ix = 0; ix < 2; ++ix) {
                int i = ix * 2 + iy;
                SkRect r = SkRect::MakeXYWH(x + ix * fixed, y + iy * fixed,
                                            size[i].width(), size[i].height());
                drawNine(canvas, r, bm, center, &paint);
            }
        }
    }

private:
    SkScalar fX, fY;
    typedef SampleView INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory() { return new NinePatchView; }
static SkViewRegister reg(MyFactory);

<|endoftext|>


<commit_before>#include <cmath>
#include <memory>

#include "drake/Path.h"
#include "drake/systems/LCMSystem.h"
#include "drake/systems/cascade_system.h"
#include "drake/systems/Simulation.h"
#include "drake/systems/LinearSystem.h"
#include "drake/systems/plants/BotVisualizer.h"
#include "drake/systems/plants/RigidBodyTree.h"

#include "drake/examples/MultiCar/n_ary_state.h"
#include "drake/examples/MultiCar/n_ary_system.h"
#include "drake/examples/MultiCar/trivial_car.h"
#include "drake/examples/MultiCar/xyz_rpy.h"

int main(int argc, const char* argv[]) {

  // Make a linear system to map NPC car state to the state vector of a
  // floating joint, allowing motion and steering in the x-y plane only.
  //
  Drake::XyzRpy<double> y0(0., 0., 0., 0., 0., M_PI / 2.);

  const int insize = Drake::TrivialCarState<double>::RowsAtCompileTime;
  const int outsize = Drake::XyzRpy<double>::RowsAtCompileTime;
  Eigen::Matrix<double, outsize, insize> D;
  D <<
      1, 0,  0,  // x
      0, 1,  0,  // y
      0, 0,  0,  // z
      0, 0,  0,  // roll
      0, 0,  0,  // pitch
      0, 0, -1;  // yaw

  auto car_vis_adapter = std::make_shared<
    Drake::AffineSystem<Drake::NullVector,
                        Drake::TrivialCarState,
                        Drake::XyzRpy> >(
      Eigen::MatrixXd::Zero(0, 0),
      Eigen::MatrixXd::Zero(0, insize),
      Eigen::VectorXd::Zero(0),
      Eigen::MatrixXd::Zero(outsize, 0), D,
      toEigen(y0));

  const std::string SEDAN_URDF = Drake::getDrakePath() +
      "/examples/MultiCar/sedan.urdf";
  const std::string BREADTRUCK_URDF = Drake::getDrakePath() +
      "/examples/MultiCar/breadtruck.urdf";

  // RigidBodyTree for visualization.
  auto world_tree = std::make_shared<RigidBodyTree>();

  // NarySystem for car 'physics'.
  // NB:  One could compose the other way as well.
  auto cars_system = std::make_shared<Drake::NArySystem<Drake::TrivialCar> >();
  // NarySystem for car visualization.
  auto cars_vis_adapter = std::make_shared<Drake::NArySystem<decltype(car_vis_adapter)::element_type> >();

  // Create one Sedan.
  world_tree->addRobotFromURDF(SEDAN_URDF,
                               DrakeJoint::ROLLPITCHYAW,
                               nullptr /*weld_to_frame*/);
  // TODO maddog  Hmm... it appears that drake_visualizer wants unique names,
  //              on *links*, otherwise only one of the same-named links will
  //              be get updated joint parameters.
  world_tree->bodies.back()->linkname = "sedan1";
  auto sedan_system = std::make_shared<Drake::TrivialCar>(0., 5., 0.3, 2.0);
  cars_system->addSystem(sedan_system);
  cars_vis_adapter->addSystem(car_vis_adapter);

  // Create one Breadtruck.
  world_tree->addRobotFromURDF(BREADTRUCK_URDF,
                               DrakeJoint::ROLLPITCHYAW,
                               nullptr /*weld_to_frame*/);
  world_tree->bodies.back()->linkname = "breadtruck1";
  auto breadtruck_system = std::make_shared<Drake::TrivialCar>(15., 0., 0.7, 10.0);
  cars_system->addSystem(breadtruck_system);
  cars_vis_adapter->addSystem(car_vis_adapter);

  // Create another Sedan.
  world_tree->addRobotFromURDF(SEDAN_URDF,
                               DrakeJoint::ROLLPITCHYAW,
                               nullptr /*weld_to_frame*/);
  world_tree->bodies.back()->linkname = "sedan2";
  auto sedan2_system = std::make_shared<Drake::TrivialCar>(-5., 0., -0.3, -2.0);
  cars_system->addSystem(sedan2_system);
  cars_vis_adapter->addSystem(car_vis_adapter);

  // NpcCarSystem:
  //  U:  ()
  //  X:  ()
  //  Y:  (xy-position, heading)   SingleNpcCarState

  // BotVisualizer:  DrakeJoint::ROLLPITCHYAW per NPC
  //  U: (x, y, z, roll, pitch, yaw)
  //  X: ()
  //  Y: [== U]

  std::shared_ptr<lcm::LCM> lcm = std::make_shared<lcm::LCM>();
  auto visualizer =
      std::make_shared<Drake::BotVisualizer<
        decltype(cars_vis_adapter)::element_type::OutputVector> >(
            lcm, world_tree);

  // Compose the system together from the parts.
  auto the_system = Drake::cascade(Drake::cascade(
      cars_system, cars_vis_adapter), visualizer);

  decltype(the_system)::element_type::StateVector<double> initial_state;
  runLCM(the_system, lcm,
         0, std::numeric_limits<double>::infinity(), // timespan
         initial_state);

  return 0;
}
<commit_msg>Add 100 more 'cars'.  It's really slow now.<commit_after>#include <cmath>
#include <memory>
#include <sstream>

#include "drake/Path.h"
#include "drake/systems/LCMSystem.h"
#include "drake/systems/cascade_system.h"
#include "drake/systems/Simulation.h"
#include "drake/systems/LinearSystem.h"
#include "drake/systems/plants/BotVisualizer.h"
#include "drake/systems/plants/RigidBodyTree.h"

#include "drake/examples/MultiCar/n_ary_state.h"
#include "drake/examples/MultiCar/n_ary_system.h"
#include "drake/examples/MultiCar/trivial_car.h"
#include "drake/examples/MultiCar/xyz_rpy.h"

int main(int argc, const char* argv[]) {

  // Make a linear system to map NPC car state to the state vector of a
  // floating joint, allowing motion and steering in the x-y plane only.
  //
  Drake::XyzRpy<double> y0(0., 0., 0., 0., 0., M_PI / 2.);

  const int insize = Drake::TrivialCarState<double>::RowsAtCompileTime;
  const int outsize = Drake::XyzRpy<double>::RowsAtCompileTime;
  Eigen::Matrix<double, outsize, insize> D;
  D <<
      1, 0,  0,  // x
      0, 1,  0,  // y
      0, 0,  0,  // z
      0, 0,  0,  // roll
      0, 0,  0,  // pitch
      0, 0, -1;  // yaw

  auto car_vis_adapter = std::make_shared<
    Drake::AffineSystem<Drake::NullVector,
                        Drake::TrivialCarState,
                        Drake::XyzRpy> >(
      Eigen::MatrixXd::Zero(0, 0),
      Eigen::MatrixXd::Zero(0, insize),
      Eigen::VectorXd::Zero(0),
      Eigen::MatrixXd::Zero(outsize, 0), D,
      toEigen(y0));

  const std::string SEDAN_URDF = Drake::getDrakePath() +
      "/examples/MultiCar/sedan.urdf";
  const std::string BREADTRUCK_URDF = Drake::getDrakePath() +
      "/examples/MultiCar/breadtruck.urdf";

  // RigidBodyTree for visualization.
  auto world_tree = std::make_shared<RigidBodyTree>();

  // NarySystem for car 'physics'.
  // NB:  One could compose the other way as well.
  auto cars_system = std::make_shared<Drake::NArySystem<Drake::TrivialCar> >();
  // NarySystem for car visualization.
  auto cars_vis_adapter = std::make_shared<Drake::NArySystem<decltype(car_vis_adapter)::element_type> >();

  // Create one Sedan.
  world_tree->addRobotFromURDF(SEDAN_URDF,
                               DrakeJoint::ROLLPITCHYAW,
                               nullptr /*weld_to_frame*/);
  // TODO maddog  Hmm... it appears that drake_visualizer wants unique names,
  //              on *links*, otherwise only one of the same-named links will
  //              be get updated joint parameters.
  world_tree->bodies.back()->linkname = "sedan1";
  auto sedan_system = std::make_shared<Drake::TrivialCar>(0., 5., 0.3, 2.0);
  cars_system->addSystem(sedan_system);
  cars_vis_adapter->addSystem(car_vis_adapter);

  // Create one Breadtruck.
  world_tree->addRobotFromURDF(BREADTRUCK_URDF,
                               DrakeJoint::ROLLPITCHYAW,
                               nullptr /*weld_to_frame*/);
  world_tree->bodies.back()->linkname = "breadtruck1";
  auto breadtruck_system = std::make_shared<Drake::TrivialCar>(15., 0., 0.7, 10.0);
  cars_system->addSystem(breadtruck_system);
  cars_vis_adapter->addSystem(car_vis_adapter);

  // Create another Sedan.
  world_tree->addRobotFromURDF(SEDAN_URDF,
                               DrakeJoint::ROLLPITCHYAW,
                               nullptr /*weld_to_frame*/);
  world_tree->bodies.back()->linkname = "sedan2";
  auto sedan2_system = std::make_shared<Drake::TrivialCar>(-5., 0., -0.3, -2.0);
  cars_system->addSystem(sedan2_system);
  cars_vis_adapter->addSystem(car_vis_adapter);

  // Meh, need more cars!
  for (int i = 0; i < 100; ++i) {
    world_tree->addRobotFromURDF(
        (i % 2) ? SEDAN_URDF : BREADTRUCK_URDF,
        DrakeJoint::ROLLPITCHYAW,
        nullptr /*weld_to_frame*/);
    std::ostringstream name;
    name << "car-" << i;
    world_tree->bodies.back()->linkname = name.str();
    auto system = std::make_shared<Drake::TrivialCar>(
        (i % 19 - 10) * 10.,
        ((i + 11) % 23 - 11) * 10.,
        0.0,
        ((i % 10) - 5) * 2.0);
    cars_system->addSystem(system);
    cars_vis_adapter->addSystem(car_vis_adapter);
  }

  // NpcCarSystem:
  //  U:  ()
  //  X:  ()
  //  Y:  (xy-position, heading)   SingleNpcCarState

  // BotVisualizer:  DrakeJoint::ROLLPITCHYAW per NPC
  //  U: (x, y, z, roll, pitch, yaw)
  //  X: ()
  //  Y: [== U]

  std::shared_ptr<lcm::LCM> lcm = std::make_shared<lcm::LCM>();
  auto visualizer =
      std::make_shared<Drake::BotVisualizer<
        decltype(cars_vis_adapter)::element_type::OutputVector> >(
            lcm, world_tree);

  // Compose the system together from the parts.
  auto the_system = Drake::cascade(Drake::cascade(
      cars_system, cars_vis_adapter), visualizer);

  decltype(the_system)::element_type::StateVector<double> initial_state;
  Drake::SimulationOptions options;
  options.realtime_factor = 0.;
  runLCM(the_system, lcm,
      0, std::numeric_limits<double>::infinity(), // timespan
      initial_state,
      options);

  return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <thread>
#include <mutex>
#include <deque>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time>
#include <arpa/inet.h>
using namespace std;

typedef unsigned char BYTE;

const int BOARD_LENGTH     = 750;
const int BOARD_HEIGHT     = 500;
const int PLAYER_HEIGHT    = 125;
const int PLAYER1_X        = 30;
const int PLAYER2_X        = 720;
const int BALL_LENGTH      = 25;
const int NUMBER_OF_ROUNDS = 10;

// Thread safe queuing
mutex queMu;
deque<BYTE*> callQueue;

void add(BYTE* bytes) {
    lock_guard<mutex> locker(queMu);
    callQueue.push_back(bytes);
}
deque<BYTE*> getAll() {
    lock_guard<mutex> locker(queMu);
    deque<BYTE*> ret = callQueue; // deep copy
    callQueue.clear();
    return ret;
}

// listener listens for messages from the main server
void listener(int sockfd) {
    int size = 0;
    const int buffSize = 1400;
    BYTE recvBuff[buffSize];
    memset(recvBuff, '0' ,buffSize);

    while ((n = read(sockfd, recvBuff, buffSize-1) > 0) {
        BYTE* data = new BYTE[n];
        memcpy(data, recvBuff, n);
        add(data);
    }
    exit(1);
}

// connect connects to the Unix domain socket and returns the sockedfd
int connect(string USDAddr) {
    int sockfd = 0;
    struct sockaddr_un serv_addr;

    if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0))< 0) {
        cout << "Could not create socket\n";
        exit(1);
    }

    memcpy(serv_addr.sun_path, UDSaddr.c_str(), UDSaddr.length());
    serv_addr.sun_family = AF_UNIX;
    serv_addr.sun_path[UDSaddr.length()] = '\0';

    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0) {
        cout << "Connection Failed\n";
        exit(1);
    }

    return sockfd;
}

// gameLoop runs the game
int gameLoop(int sockfd, int tickRate) {
    if (tickRate < 0) {
        cout << "Tick rate must be above 0.\n";
        exit(1);
    }

    // simple game loop for now
    // will optimise
    while(true) {
        // TODO: update player positions
        // TODO: update ball position
        // TODO: send gamestate to server
    }
    return 1;
}

int main(int argc, char const *argv[]) {
    if (argc != 3) {
        cout << "Usage: " << argv[0] << " <UDS Address> <Tick Rate>\n";
        return 1;
    }
    string USDAddr = argv[1];
    int tickRate   = atoi(argv[2]);
    int sockfd     = connect(USDAddr);

    thread lis(listener, sockfd);
    lis.detach();

    auto begin = clock();
    int gameResult = gameLoop(sockfd);
    auto seconds = int(double(clock() - begin) / CLOCKS_PER_SEC);

    // return results to server
    return 0;
}
<commit_msg>Updating player positions<commit_after>#include <iostream>
#include <thread>
#include <mutex>
#include <deque>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time>
#include <arpa/inet.h>
using namespace std;

typedef unsigned char BYTE;

const int BOARD_LENGTH     = 750;
const int BOARD_HEIGHT     = 500;
const int PLAYER_HEIGHT    = 125;
const int PLAYER1_X        = 30;
const int PLAYER2_X        = 720;
const int BALL_LENGTH      = 25;
const int NUMBER_OF_ROUNDS = 10;

// Thread safe queuing
mutex queMu;
deque<BYTE*> callQueue;

void add(BYTE* bytes) {
    lock_guard<mutex> locker(queMu);
    callQueue.push_back(bytes);
}
deque<BYTE*> getAll() {
    lock_guard<mutex> locker(queMu);
    deque<BYTE*> ret = callQueue; // deep copy
    callQueue.clear();
    return ret;
}

// listener listens for messages from the main server
void listener(int sockfd) {
    int size = 0;
    const int buffSize = 1400;
    BYTE recvBuff[buffSize];
    memset(recvBuff, '0' ,buffSize);

    while ((n = read(sockfd, recvBuff, buffSize-1) > 0) {
        BYTE* data = new BYTE[n];
        memcpy(data, recvBuff, n);
        add(data);
    }
    exit(1);
}

// connect connects to the Unix domain socket and returns the sockedfd
int connect(string USDAddr) {
    int sockfd = 0;
    struct sockaddr_un serv_addr;

    if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0))< 0) {
        cout << "Could not create socket\n";
        exit(1);
    }

    memcpy(serv_addr.sun_path, UDSaddr.c_str(), UDSaddr.length());
    serv_addr.sun_family = AF_UNIX;
    serv_addr.sun_path[UDSaddr.length()] = '\0';

    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0) {
        cout << "Connection Failed\n";
        exit(1);
    }

    return sockfd;
}

// structure containing the game state
struct gameState {
    int round;
    int player1_position;
    int player2_position;
    int ballX;
    int ballY;
};

// structure containing a server message
struct serverMessage {
    int type;
    bool player1;
    int newPosition;
};

// union of server message struct and an array of bytes
union messageDecode {
    Byte* bytes;
    serverMessage result;
};

// updatePlayerPositions looks at the call queue and
// updates player positions
gameState updatePlayerPositions(gameState gs) {
    auto queue = getAll();
    auto ugs = gs;
    while (!queue.empty()) {
        auto data = queue.front();
        messageDecode srvMsg;
        srvMsg.bytes = data;
        if (srvMsg.result.type != 1) {
            cout << "received " << srvMsg.result.type << " type message from server\n";
            exit(1);
        }
        if (srvMsg.result.newPosition <= (BOARD_HEIGHT - PLAYER_HEIGHT) && srvMsg.result.newPosition >= 0) {
            if (srvMsg.result.player1) {
                ugs.player1_position = srvMsg.result.newPosition;
            } else {
                ugs.player2_position = srvMsg.result.newPosition;
            }
        }
        queue.pop_front();
    }
    return ugs;
}

// gameLoop runs the game
int gameLoop(int sockfd, int tickRate) {
    if (tickRate < 0) {
        cout << "Tick rate must be above 0.\n";
        exit(1);
    }

    gameState gs;
    gs.round = 1;
    gs.player1_position = gs.player2_position =
        (BOARD_HEIGHT/2) - (PLAYER_HEIGHT/2);
    gs.ballX = (BOARD_LENGTH/2) - (BALL_LENGTH/2);
    gs.ballY = (BOARD_HEIGHT/2) - (BALL_LENGTH/2);

    // simple game loop for now
    // will optimise
    while(true) {
        gs = updatePlayerPositions(gs);
        // TODO: update ball position
        // TODO: send gamestate to server
    }
    return 1;
}

int main(int argc, char const *argv[]) {
    if (argc != 3) {
        cout << "Usage: " << argv[0] << " <UDS Address> <Tick Rate>\n";
        return 1;
    }
    string USDAddr = argv[1];
    int tickRate   = atoi(argv[2]);
    int sockfd     = connect(USDAddr);

    thread lis(listener, sockfd);
    lis.detach();

    auto begin = clock();
    int gameResult = gameLoop(sockfd);
    auto seconds = int(double(clock() - begin) / CLOCKS_PER_SEC);

    // return results to server
    return 0;
}
<|endoftext|>