text:
// Copyright (C) 2018 Thanaphon Chavengsaksongkram <as12production@gmail.com>, He Sun <he.sun@ed.ac.uk>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#include <gtest/gtest.h>
#include <gSparse/GraphCSVWriter.hpp>
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <memory>
#include <string>
#include <fstream>

/*******************************************************
 * Set up and utility functions
 * ******************************************************/

//This function compares whether two files are the same
bool compareFiles(const std::string& p1, const std::string& p2)
{
	std::ifstream f1(p1, std::ifstream::binary | std::ifstream::ate);
	std::ifstream f2(p2, std::ifstream::binary | std::ifstream::ate);
	if (f1.fail() || f2.fail())
	{
		return false; //file problem
	}
	//seek back to beginning and use std::equal to compare contents
	f1.seekg(0, std::ifstream::beg);
	f2.seekg(0, std::ifstream::beg);
	return std::equal(std::istreambuf_iterator<char>(f1.rdbuf()),
		std::istreambuf_iterator<char>(),
		std::istreambuf_iterator<char>(f2.rdbuf()));
}

/* Dummy graph for testing
    TODO: Could leverage Google Mock for this
*/
class DummyGraph : public gSparse::IGraph
{
private:
	gSparse::SparsePrecisionMatrix dummy;
	gSparse::EdgeMatrix dummyEdge;
	gSparse::PrecisionRowMatrix dummyWeight;
public:
	DummyGraph()
	{
		dummyEdge = gSparse::EdgeMatrix(3, 2);
		dummyWeight = gSparse::PrecisionRowMatrix(3, 1);
		dummyEdge(0, 0) = 1; dummyEdge(0, 1) = 2;
		dummyEdge(1, 0) = 2; dummyEdge(1, 1) = 3;
		dummyEdge(2, 0) = 3; dummyEdge(2, 1) = 1;
		dummyWeight << 1, 2, 3;
	}
	/* Get Interface*/
	const gSparse::SparsePrecisionMatrix & GetAdjacentMatrix() const
	{
		return dummy;
	}
	const gSparse::SparsePrecisionMatrix & GetIncidentMatrix() const
	{
		return dummy;
	}
	const gSparse::SparsePrecisionMatrix & GetDegreeMatrix() const
	{
		return dummy;
	}
	const gSparse::SparsePrecisionMatrix & GetLaplacianMatrix() const
	{
		return (dummy);
	}
	const gSparse::SparsePrecisionMatrix & GetWeightMatrix() const
	{
		return dummy;
	}
	const gSparse::EdgeMatrix & GetEdgeList() const
	{
		return dummyEdge;;
	}
	const gSparse::PrecisionRowMatrix & GetWeightList() const
	{
		return dummyWeight;
	}
	std::size_t GetEdgeCount() const {
		return 0;
	}
	std::size_t GetNodeCount() const {
		return 0;
	}
};

/*******************************************************
 * Test Suites
 * ******************************************************/
TEST(GraphCSVWriter, Write1)
{
	/* Testing Initialization */
	gSparse::GraphCSVWriter csvWriter("csvwriter-edges.csv", "csvwriter-weight.csv", " ");

    //Building Validation data
	gSparse::EdgeMatrix  Edges(3, 2);
	Edges(0, 0) = 1; Edges(0, 1) = 2;
	Edges(1, 0) = 2; Edges(1, 1) = 3;
	Edges(2, 0) = 3; Edges(2, 1) = 1;

    //Building weight validation data
	Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>  Weight(3, 1);
	Weight << 1, 2, 3;

    // Write the file
    csvWriter.Write(Edges, Weight);

    // Compare if they are the same
	EXPECT_EQ(true, compareFiles("csvwriter-edges.csv", "test-edges.csv"));
	EXPECT_EQ(true, compareFiles("csvwriter-weight.csv", "test-weight.csv"));
}

TEST(GraphCSVWriter, Write2)
{
    /* Testing Initialization */
    gSparse::GraphWriter csvWriter = std::make_shared<gSparse::GraphCSVWriter>("csvwriter-edges.csv",
    "csvwriter-weight.csv",
    " ") ;

	//Building Validation data
	gSparse::EdgeMatrix  Edges(3, 2);
	Edges(0, 0) = 1; Edges(0, 1) = 2;
	Edges(1, 0) = 2; Edges(1, 1) = 3;
	Edges(2, 0) = 3; Edges(2, 1) = 1;

	//Building weight validation data

	gSparse::PrecisionMatrix  Weight(3, 1);
	Weight << 1, 2, 3;

    // Write the file
	csvWriter->Write(Edges, Weight);
	 // Compare if they are the same
	EXPECT_EQ(true, compareFiles("csvwriter-edges.csv", "test-edges.csv"));
	EXPECT_EQ(true, compareFiles("csvwriter-weight.csv", "test-weight.csv"));
}

TEST(GraphCSVWriter, WriteGraphObject)
{
    /* Testing Initialization */
    gSparse::GraphWriter csvWriter = std::make_shared<gSparse::GraphCSVWriter>("csvwriter-edges.csv",
    "csvwriter-weight.csv",
    " ");

    /* Write file based on data from graph */
	gSparse::Graph dummy(new DummyGraph());
	csvWriter->Write(dummy);
	EXPECT_EQ(true, compareFiles("csvwriter-edges.csv", "test-edges.csv"));
	EXPECT_EQ(true, compareFiles("csvwriter-weight.csv", "test-weight.csv"));
}
TEST(GraphCSVWriter, WriteEdgeOnly)
{
    /* Testing Initialization */
    gSparse::GraphWriter csvWriter = std::make_shared<gSparse::GraphCSVWriter>("csvwriter-edges.csv",
    "None",
    " ") ;

	//Building Validation data
	gSparse::EdgeMatrix  Edges(3, 2);
	Edges(0, 0) = 1; Edges(0, 1) = 2;
	Edges(1, 0) = 2; Edges(1, 1) = 3;
	Edges(2, 0) = 3; Edges(2, 1) = 1;

    // Write the file
	csvWriter->Write(Edges);
    EXPECT_EQ(true, compareFiles("csvwriter-edges.csv", "test-edges.csv"));
}

TEST(GraphCSVWriter, WriteGraphError1)
{
    /* Testing Initialization */
    gSparse::GraphWriter csvWriter = std::make_shared<gSparse::GraphCSVWriter>("csvwriter-edges.csv",
    "None",
    " ");

    /* Write file based on data from graph */
	gSparse::Graph dummy(new DummyGraph());
	EXPECT_ANY_THROW(csvWriter->Write(dummy));
}
TEST(GraphCSVWriter, WriteGraphError2)
{
    /* Testing Initialization */
    gSparse::GraphWriter csvWriter = std::make_shared<gSparse::GraphCSVWriter>("csvwriter-edges.csv",
    "None",
    " ");

    /* Write file based on data from graph */
	gSparse::Graph dummy;
	EXPECT_ANY_THROW(csvWriter->Write(dummy));
}

TEST(GraphCSVWriter, WriteGraphError3)
{
    /* Testing Initialization */
    gSparse::GraphWriter csvWriter = std::make_shared<gSparse::GraphCSVWriter>("csvwriter-edges.csv",
    "None",
    " ") ;

	//Building Validation data
	gSparse::EdgeMatrix  Edges(3, 2);
	Edges(0, 0) = 1; Edges(0, 1) = 2;
	Edges(1, 0) = 2; Edges(1, 1) = 3;
	Edges(2, 0) = 3; Edges(2, 1) = 1;

	//Building weight validation data

	gSparse::PrecisionMatrix  Weight(3, 1);
	Weight << 1, 2, 3;

    // Write the file, expects error
	EXPECT_ANY_THROW(csvWriter->Write(Edges, Weight));
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}


text:
///////////////////////////////////////////////////////////////////////////////
//  Copyright Christopher Kormanyos 2016.
//  Distributed under the Boost Software License,
//  Version 1.0. (See accompanying file LICENSE_1_0.txt
//  or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <iomanip>
#include <iostream>

#include <boost/fixed_point/fixed_point.hpp>
#include <boost/math/special_functions/bessel.hpp>

int main()
{
  // Ensure that the built-in types have sufficient digits.
  static_assert(std::numeric_limits<long double>::digits > std::numeric_limits<int>::digits + 7,
                "Error: Not enough digits are available in long double for this example");

  // Use as many range digits as are available in built-in int.
  typedef boost::fixed_point::negatable<
    std::numeric_limits<int>::digits,             // Use as many range digits as there are digits in int.
    -(  std::numeric_limits<long double>::digits  // Obtain the remaining resolution digits from long double (minus those from int).
      - std::numeric_limits<int>::digits)>
  fixed_point_type;

  const fixed_point_type v = fixed_point_type(3) / 7;
  const fixed_point_type x = fixed_point_type(1) / 4;

  const fixed_point_type jv = boost::math::cyl_bessel_j(v, x);

  // Calculate the approximate decimal precision of the resolution.
  const int decimal_resolution = ((  std::numeric_limits<long double>::digits
                                   - std::numeric_limits<int>::digits) * 301) / 1000;

  // Calculated value: 0.457863
  // Expected   value: 0.457857, see Wolfram Alpha with N[BesselJ[3/7, 1/4], 6]
  std::cout << std::setprecision(decimal_resolution)
            << std::fixed
            << jv
            << std::endl;
}

ext: cpp


text:
//  (C) Copyright 2008-10 Anthony Williams
//  (C) Copyright 2011-2015 Vicente J. Botet Escriba
//
//  Distributed under the Boost Software License, Version 1.0. (See
//  accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_THREAD_FUTURES_WAIT_FOR_ANY_HPP
#define BOOST_THREAD_FUTURES_WAIT_FOR_ANY_HPP

#include <boost/thread/detail/config.hpp>

#include <boost/thread/detail/move.hpp>
#include <boost/thread/futures/is_future_type.hpp>
#include <boost/thread/lock_algorithms.hpp>
#include <boost/thread/mutex.hpp>

#include <boost/core/enable_if.hpp>
#include <boost/next_prior.hpp>
#include <boost/scoped_array.hpp>

#include <iterator>
#include <vector>

namespace boost
{
  namespace detail
  {
    template <class Future>
    class waiter_for_any_in_seq
    {
      struct registered_waiter;
      typedef std::vector<int>::size_type count_type;

      struct registered_waiter
      {
        typedef Future future_type;
        future_type* future_;
        typedef typename Future::notify_when_ready_handle notify_when_ready_handle;
        notify_when_ready_handle handle;
        count_type index;

        registered_waiter(future_type & a_future,
            notify_when_ready_handle handle_, count_type index_) :
          future_(&a_future), handle(handle_), index(index_)
        {
        }
      };

      struct all_futures_lock
      {
#ifdef _MANAGED
        typedef std::ptrdiff_t count_type_portable;
#else
        typedef count_type count_type_portable;
#endif
        count_type_portable count;
        boost::scoped_array<boost::unique_lock<boost::mutex> > locks;

        all_futures_lock(std::vector<registered_waiter>& waiters) :
          count(waiters.size()), locks(new boost::unique_lock<boost::mutex>[count])
        {
          for (count_type_portable i = 0; i < count; ++i)
          {
            locks[i] = BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(waiters[i].future_->mutex()));
          }
        }

        void lock()
        {
          boost::lock(locks.get(), locks.get() + count);
        }

        void unlock()
        {
          for (count_type_portable i = 0; i < count; ++i)
          {
            locks[i].unlock();
          }
        }
      };

      boost::condition_variable_any cv;
      std::vector<registered_waiter> waiters_;
      count_type future_count;

    public:
      waiter_for_any_in_seq() :
        future_count(0)
      {
      }

      template <typename F>
      void add(F& f)
      {
        if (f.valid())
        {
          registered_waiter waiter(f, f.notify_when_ready(cv), future_count);
          try
          {
            waiters_.push_back(waiter);
          }
          catch (...)
          {
            f.future_->unnotify_when_ready(waiter.handle);
            throw;
          }
          ++future_count;
        }
      }

#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
      template <typename F1, typename ... Fs>
      void add(F1& f1, Fs&... fs)
      {
        add(f1);
        add(fs...);
      }
#endif

      count_type wait()
      {
        all_futures_lock lk(waiters_);
        for (;;)
        {
          for (count_type i = 0; i < waiters_.size(); ++i)
          {
            if (waiters_[i].future_->is_ready(lk.locks[i]))
            {
              return waiters_[i].index;
            }
          }
          cv.wait(lk);
        }
      }

      ~waiter_for_any_in_seq()
      {
        for (count_type i = 0; i < waiters_.size(); ++i)
        {
          waiters_[i].future_->unnotify_when_ready(waiters_[i].handle);
        }
      }
    };
  }

  template <typename Iterator>
  typename boost::disable_if<is_future_type<Iterator> , Iterator>::type wait_for_any(Iterator begin, Iterator end)
  {
    if (begin == end) return end;

    detail::waiter_for_any_in_seq<typename std::iterator_traits<Iterator>::value_type> waiter;
    for (Iterator current = begin; current != end; ++current)
    {
      waiter.add(*current);
    }
    return boost::next(begin, waiter.wait());
  }
}

#endif // header

ext: hpp

max_stars_repo_name: rudylee/expo

max_issues_repo_name: rudylee/expo

max_forks_repo_name: rudylee/expo


text:
/* ----------------------------------------------------------------------------
 * Copyright 2020, Jesus Tordesillas Torres, Aerospace Controls Laboratory
 * Massachusetts Institute of Technology
 * All Rights Reserved
 * Authors: Jesus Tordesillas, et al.
 * See LICENSE file for the license information
 * -------------------------------------------------------------------------- */

#pragma once

#include <Eigen/Dense>

#include <geometry_msgs/PoseStamped.h>
#include <visualization_msgs/MarkerArray.h>
#include <ros/ros.h>
#include <visualization_msgs/Marker.h>
#include <visualization_msgs/MarkerArray.h>
#include <rviz_visual_tools/rviz_visual_tools.h>
#include <snapstack_msgs/State.h>
#include <snapstack_msgs/Goal.h>

// #include <mader_msgs/Mode.h>
#include <mader_msgs/WhoPlans.h>
#include <mader_msgs/DynTraj.h>

#include "utils.hpp"
#include "mader.hpp"
#include "mader_types.hpp"

#include "timer.hpp"

namespace rvt = rviz_visual_tools;

class MaderRos
{
public:
  MaderRos(ros::NodeHandle nh1, ros::NodeHandle nh2, ros::NodeHandle nh3);
  ~MaderRos();

private:
  std::unique_ptr<Mader> mader_ptr_;

  void publishOwnTraj(const mt::PieceWisePol& pwp);
  void publishPlanes(std::vector<Hyperplane3D>& planes);

  // class methods
  void pubTraj(const std::vector<mt::state>& data);
  void terminalGoalCB(const geometry_msgs::PoseStamped& msg);
  void pubState(const mt::state& msg, const ros::Publisher pub);
  void stateCB(const snapstack_msgs::State& msg);
  // void modeCB(const mader_msgs::Mode& msg);
  void whoPlansCB(const mader_msgs::WhoPlans& msg);
  void pubCB(const ros::TimerEvent& e);
  void replanCB(const ros::TimerEvent& e);
  void trajCB(const mader_msgs::DynTraj& msg);

  // void clearMarkerSetOfArrows();
  void clearMarkerActualTraj();
  void clearMarkerColoredTraj();

  void pubActualTraj();
  visualization_msgs::MarkerArray clearArrows();
  // geometry_msgs::Vector3 mu::vectorNull();

  void clearMarkerArray(visualization_msgs::MarkerArray* tmp, ros::Publisher* publisher);

  void publishPoly(const vec_E<Polyhedron<3>>& poly);
  // visualization_msgs::MarkerArray Matrix2ColoredMarkerArray(Eigen::MatrixXd& X, int type);

  void publishText();

  void publishFOV();

  void pubObstacles(mt::Edges edges_obstacles);

  void verify(bool cond, std::string info_if_false);

  mt::state state_;

  std::string world_name_ = "world";

  rvt::RvizVisualToolsPtr visual_tools_;

  visualization_msgs::Marker E_;
  visualization_msgs::Marker A_;
  visualization_msgs::Marker setpoint_;

  ros::NodeHandle nh1_;
  ros::NodeHandle nh2_;
  ros::NodeHandle nh3_;

  ros::Publisher pub_point_G_;
  ros::Publisher pub_point_G_term_;
  ros::Publisher pub_goal_;
  ros::Publisher pub_traj_safe_;
  ros::Publisher pub_setpoint_;
  ros::Publisher pub_actual_traj_;

  ros::Publisher pub_point_A_;

  ros::Publisher pub_traj_safe_colored_;

  ros::Publisher pub_text_;
  ros::Publisher pub_traj_;

  ros::Publisher poly_safe_pub_;

  ros::Publisher pub_fov_;
  ros::Publisher pub_obstacles_;

  ros::Subscriber sub_term_goal_;
  // ros::Subscriber sub_mode_;
  ros::Subscriber sub_whoplans_;
  ros::Subscriber sub_state_;
  ros::Subscriber sub_traj_;

  ros::Timer pubCBTimer_;
  ros::Timer replanCBTimer_;

  mt::parameters par_;  // where all the parameters are

  std::string name_drone_;

  std::vector<std::string> traj_;  // trajectory of the dynamic obstacle

  visualization_msgs::MarkerArray traj_safe_colored_;

  int actual_trajID_ = 0;

  int num_of_LPs_run_ = 0;
  int num_of_QCQPs_run_ = 0;

  int id_;  // id of the drone

  bool published_initial_position_ = false;

  Eigen::Affine3d W_T_B_;

  mt::PieceWisePol pwp_last_;

  MADER_timers::Timer timer_stop_;
};

max_stars_repo_name: shubham-shahh/mader

max_issues_repo_name: shubham-shahh/mader

max_forks_repo_name: shubham-shahh/mader


text:
// Copyright Eric Niebler 2009
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/mpl for documentation.

// $Id: string.cpp 49240 2009-04-01 09:21:07Z eric_niebler $
// $Date: 2009-04-01 02:21:07 -0700 (Wed, 1 Apr 2009) $
// $Revision: 49240 $

#include <string>
#include <cstring>
#include <iostream>

#include <boost/mpl/string.hpp>

#include <boost/mpl/at.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/erase.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/advance.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/pop_back.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/detail/lightweight_test.hpp>

namespace mpl = boost::mpl;

// Accept a string as a template parameter!
template<char const *sz>
struct greeting
{
    std::string say_hello() const
    {
        return sz;
    }
};

struct push_char
{
    push_char(std::string &str)
      : str_(&str)
    {}

    void operator()(char ch) const
    {
        this->str_->push_back(ch);
    }

    std::string *str_;
};

int main()
{
    // Test mpl::size of strings
    {
        typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full;
        typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> full;

        BOOST_MPL_ASSERT_RELATION(0,  ==, (mpl::size<mpl::string<> >::value));
        BOOST_MPL_ASSERT_RELATION(1,  ==, (mpl::size<mpl::string<'a'> >::value));
        BOOST_MPL_ASSERT_RELATION(2,  ==, (mpl::size<mpl::string<'ab'> >::value));
        BOOST_MPL_ASSERT_RELATION(2,  ==, (mpl::size<mpl::string<'a','b'> >::value));
        BOOST_MPL_ASSERT_RELATION(4,  ==, (mpl::size<mpl::string<'abcd'> >::value));
        BOOST_MPL_ASSERT_RELATION(5,  ==, (mpl::size<mpl::string<'abcd','e'> >::value));
        BOOST_MPL_ASSERT_RELATION(31, ==, (mpl::size<almost_full>::value));
        BOOST_MPL_ASSERT_RELATION(32, ==, (mpl::size<full>::value));
    }

    // Test mpl::begin and mpl::end with strings
    {
        typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full;
        typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> full;

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::begin<mpl::string<> >::type
              , mpl::end<mpl::string<> >::type
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::begin<mpl::string<'a'> >::type
              , mpl::string_iterator<mpl::string<'a'>, 0, 0>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::end<mpl::string<'a'> >::type
              , mpl::string_iterator<mpl::string<'a'>, 1, 0>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::begin<almost_full>::type
              , mpl::string_iterator<almost_full, 0, 0>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::end<almost_full>::type
              , mpl::string_iterator<almost_full, 8, 0>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::begin<full>::type
              , mpl::string_iterator<full, 0, 0>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::end<full>::type
              , mpl::string_iterator<full, 8, 0>
            >
        ));
    }

    // testing push_back
    {
        typedef mpl::push_back<mpl::string<>, mpl::char_<'a'> >::type t1;
        BOOST_MPL_ASSERT((boost::is_same<t1, mpl::string<'a'> >));

        typedef mpl::push_back<t1, mpl::char_<'b'> >::type t2;
        BOOST_MPL_ASSERT((boost::is_same<t2, mpl::string<'ab'> >));

        typedef mpl::push_back<t2, mpl::char_<'c'> >::type t3;
        BOOST_MPL_ASSERT((boost::is_same<t3, mpl::string<'abc'> >));

        typedef mpl::push_back<t3, mpl::char_<'d'> >::type t4;
        BOOST_MPL_ASSERT((boost::is_same<t4, mpl::string<'abcd'> >));

        typedef mpl::push_back<t4, mpl::char_<'e'> >::type t5;
        BOOST_MPL_ASSERT((boost::is_same<t5, mpl::string<'abcd','e'> >));

        typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full;
        typedef mpl::push_back<almost_full, mpl::char_<'X'> >::type t6;
        BOOST_MPL_ASSERT((boost::is_same<t6, mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaX'> >));
    }

    // Test mpl::next
    {
        typedef mpl::string<'a','bc','def','ghij'> s;

        typedef mpl::begin<s>::type i0;
        BOOST_MPL_ASSERT((boost::is_same<i0, mpl::string_iterator<s,0,0> >));

        typedef mpl::next<i0>::type i1;
        BOOST_MPL_ASSERT((boost::is_same<i1, mpl::string_iterator<s,1,0> >));

        typedef mpl::next<i1>::type i2;
        BOOST_MPL_ASSERT((boost::is_same<i2, mpl::string_iterator<s,1,1> >));

        typedef mpl::next<i2>::type i3;
        BOOST_MPL_ASSERT((boost::is_same<i3, mpl::string_iterator<s,2,0> >));

        typedef mpl::next<i3>::type i4;
        BOOST_MPL_ASSERT((boost::is_same<i4, mpl::string_iterator<s,2,1> >));

        typedef mpl::next<i4>::type i5;
        BOOST_MPL_ASSERT((boost::is_same<i5, mpl::string_iterator<s,2,2> >));

        typedef mpl::next<i5>::type i6;
        BOOST_MPL_ASSERT((boost::is_same<i6, mpl::string_iterator<s,3,0> >));

        typedef mpl::next<i6>::type i7;
        BOOST_MPL_ASSERT((boost::is_same<i7, mpl::string_iterator<s,3,1> >));

        typedef mpl::next<i7>::type i8;
        BOOST_MPL_ASSERT((boost::is_same<i8, mpl::string_iterator<s,3,2> >));

        typedef mpl::next<i8>::type i9;
        BOOST_MPL_ASSERT((boost::is_same<i9, mpl::string_iterator<s,3,3> >));

        typedef mpl::next<i9>::type i10;
        BOOST_MPL_ASSERT((boost::is_same<i10, mpl::string_iterator<s,4,0> >));

        BOOST_MPL_ASSERT((boost::is_same<i10, mpl::end<s>::type>));
    }

    // Test mpl::prior
    {
        typedef mpl::string<'a','bc','def','ghij'> s;

        typedef mpl::end<s>::type i10;
        BOOST_MPL_ASSERT((boost::is_same<i10, mpl::string_iterator<s,4,0> >));

        typedef mpl::prior<i10>::type i9;
        BOOST_MPL_ASSERT((boost::is_same<i9, mpl::string_iterator<s,3,3> >));

        typedef mpl::prior<i9>::type i8;
        BOOST_MPL_ASSERT((boost::is_same<i8, mpl::string_iterator<s,3,2> >));

        typedef mpl::prior<i8>::type i7;
        BOOST_MPL_ASSERT((boost::is_same<i7, mpl::string_iterator<s,3,1> >));

        typedef mpl::prior<i7>::type i6;
        BOOST_MPL_ASSERT((boost::is_same<i6, mpl::string_iterator<s,3,0> >));

        typedef mpl::prior<i6>::type i5;
        BOOST_MPL_ASSERT((boost::is_same<i5, mpl::string_iterator<s,2,2> >));

        typedef mpl::prior<i5>::type i4;
        BOOST_MPL_ASSERT((boost::is_same<i4, mpl::string_iterator<s,2,1> >));

        typedef mpl::prior<i4>::type i3;
        BOOST_MPL_ASSERT((boost::is_same<i3, mpl::string_iterator<s,2,0> >));

        typedef mpl::prior<i3>::type i2;
        BOOST_MPL_ASSERT((boost::is_same<i2, mpl::string_iterator<s,1,1> >));

        typedef mpl::prior<i2>::type i1;
        BOOST_MPL_ASSERT((boost::is_same<i1, mpl::string_iterator<s,1,0> >));

        typedef mpl::prior<i1>::type i0;
        BOOST_MPL_ASSERT((boost::is_same<i0, mpl::string_iterator<s,0,0> >));

        BOOST_MPL_ASSERT((boost::is_same<i0, mpl::begin<s>::type>));
    }

    // Test mpl::deref
    {
        typedef mpl::string<'a','bc','def','ghij'> s;

        typedef mpl::begin<s>::type i0;
        BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i0>::type, mpl::char_<'a'> >));

        typedef mpl::next<i0>::type i1;
        BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i1>::type, mpl::char_<'b'> >));

        typedef mpl::next<i1>::type i2;
        BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i2>::type, mpl::char_<'c'> >));

        typedef mpl::next<i2>::type i3;
        BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i3>::type, mpl::char_<'d'> >));

        typedef mpl::next<i3>::type i4;
        BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i4>::type, mpl::char_<'e'> >));

        typedef mpl::next<i4>::type i5;
        BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i5>::type, mpl::char_<'f'> >));

        typedef mpl::next<i5>::type i6;
        BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i6>::type, mpl::char_<'g'> >));

        typedef mpl::next<i6>::type i7;
        BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i7>::type, mpl::char_<'h'> >));

        typedef mpl::next<i7>::type i8;
        BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i8>::type, mpl::char_<'i'> >));

        typedef mpl::next<i8>::type i9;
        BOOST_MPL_ASSERT((boost::is_same<mpl::deref<i9>::type, mpl::char_<'j'> >));
    }

    // testing push_back
    {
        typedef mpl::push_back<mpl::string<>, mpl::char_<'a'> >::type t1;
        BOOST_MPL_ASSERT((boost::is_same<t1, mpl::string<'a'> >));

        typedef mpl::push_back<t1, mpl::char_<'b'> >::type t2;
        BOOST_MPL_ASSERT((boost::is_same<t2, mpl::string<'ab'> >));

        typedef mpl::push_back<t2, mpl::char_<'c'> >::type t3;
        BOOST_MPL_ASSERT((boost::is_same<t3, mpl::string<'abc'> >));

        typedef mpl::push_back<t3, mpl::char_<'d'> >::type t4;
        BOOST_MPL_ASSERT((boost::is_same<t4, mpl::string<'abcd'> >));

        typedef mpl::push_back<t4, mpl::char_<'e'> >::type t5;
        BOOST_MPL_ASSERT((boost::is_same<t5, mpl::string<'abcd','e'> >));

        typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full;
        typedef mpl::push_back<almost_full, mpl::char_<'X'> >::type t6;
        BOOST_MPL_ASSERT((boost::is_same<t6, mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaX'> >));

        typedef mpl::string<'a','a','a','a','a','a','a','aaaa'> must_repack;
        typedef mpl::push_back<must_repack, mpl::char_<'X'> >::type t7;
        BOOST_MPL_ASSERT((boost::is_same<t7, mpl::string<'aaaa','aaaa','aaaX'> >));
    }

    BOOST_MPL_ASSERT((mpl::empty<mpl::string<> >));
    BOOST_MPL_ASSERT_NOT((mpl::empty<mpl::string<'hi!'> >));

    // testing push_front
    {
        typedef mpl::push_front<mpl::string<>, mpl::char_<'a'> >::type t1;
        BOOST_MPL_ASSERT((boost::is_same<t1, mpl::string<'a'> >));

        typedef mpl::push_front<t1, mpl::char_<'b'> >::type t2;
        BOOST_MPL_ASSERT((boost::is_same<t2, mpl::string<'ba'> >));

        typedef mpl::push_front<t2, mpl::char_<'c'> >::type t3;
        BOOST_MPL_ASSERT((boost::is_same<t3, mpl::string<'cba'> >));

        typedef mpl::push_front<t3, mpl::char_<'d'> >::type t4;
        BOOST_MPL_ASSERT((boost::is_same<t4, mpl::string<'dcba'> >));

        typedef mpl::push_front<t4, mpl::char_<'e'> >::type t5;
        BOOST_MPL_ASSERT((boost::is_same<t5, mpl::string<'e','dcba'> >));

        typedef mpl::string<'aaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> almost_full;
        typedef mpl::push_front<almost_full, mpl::char_<'X'> >::type t6;
        BOOST_MPL_ASSERT((boost::is_same<t6, mpl::string<'Xaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> >));

        typedef mpl::string<'aaaa','a','a','a','a','a','a','a'> must_repack;
        typedef mpl::push_front<must_repack, mpl::char_<'X'> >::type t7;
        BOOST_MPL_ASSERT((boost::is_same<t7, mpl::string<'Xaaa','aaaa','aaaa'> >));
    }

    // Test c_str<>
    BOOST_TEST(0 == std::strcmp(
        mpl::c_str<mpl::string<> >::value
                             , ""
    ));

    BOOST_TEST(0 == std::strcmp(
        mpl::c_str<mpl::string<'Hell','o wo','rld!'> >::value
                             , "Hell" "o wo" "rld!"
    ));

    BOOST_TEST(0 == std::strcmp(
        mpl::c_str<mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaX'> >::value
                             , "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaX"
    ));

    // test using a string as a template parameter
    greeting<mpl::c_str<mpl::string<'Hell','o wo','rld!'> >::value> g;
    BOOST_TEST("Hello world!" == g.say_hello());

    std::string result;
    mpl::for_each<mpl::string<'Hell','o wo','rld!'> >(push_char(result));
    BOOST_TEST("Hello world!" == result);

    BOOST_TEST(('h' == mpl::front<mpl::string<'hi!'> >::type()));
    BOOST_TEST(('!' == mpl::back<mpl::string<'hi!'> >::type()));

    // back-inserter with copy
    typedef mpl::vector_c<char, 'a','b','c','d','e'> rgc;
    BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<rgc>::value));
    typedef mpl::copy<rgc, mpl::back_inserter<mpl::string<> > >::type str;
    BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<str>::value));

    // test insert_range and erase
    {
        typedef mpl::string<'Hell','o wo','rld!'> hello;
        typedef mpl::advance_c<mpl::begin<hello>::type, 5>::type where;
        typedef mpl::string<' cru','el'> cruel;
        typedef mpl::insert_range<hello, where, cruel>::type hello_cruel;
        BOOST_TEST(0 == std::strcmp("Hello cruel world!", mpl::c_str<hello_cruel>::value));

        typedef mpl::erase<hello, mpl::begin<hello>::type, where>::type erased1;
        BOOST_TEST(0 == std::strcmp(" world!", mpl::c_str<erased1>::value));
    }

    // test pop_front
    {
        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_front<mpl::string<'a'> >::type
              , mpl::string<>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_front<mpl::string<'ab'> >::type
              , mpl::string<'b'>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_front<mpl::string<'abc'> >::type
              , mpl::string<'bc'>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_front<mpl::string<'abcd'> >::type
              , mpl::string<'bcd'>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_front<mpl::string<'abcd','e'> >::type
              , mpl::string<'bcd','e'>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_front<mpl::string<'d','e'> >::type
              , mpl::string<'e'>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_front<mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> >::type
              , mpl::string<'aaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'>
            >
        ));
    }

    // test pop_back
    {
        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_back<mpl::string<'a'> >::type
              , mpl::string<>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_back<mpl::string<'ab'> >::type
              , mpl::string<'a'>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_back<mpl::string<'abc'> >::type
              , mpl::string<'ab'>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_back<mpl::string<'abcd'> >::type
              , mpl::string<'abc'>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_back<mpl::string<'abcd','e'> >::type
              , mpl::string<'abcd'>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_back<mpl::string<'d','e'> >::type
              , mpl::string<'d'>
            >
        ));

        BOOST_MPL_ASSERT((
            boost::is_same<
                mpl::pop_back<mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> >::type
              , mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'>
            >
        ));
    }

    {
        BOOST_TEST((
            mpl::at_c<
                mpl::string<'\x7f'>
              , 0
            >::type::value == (char)0x7f
        ));

        BOOST_TEST((
            mpl::at_c<
                mpl::string<'\x80'>
              , 0
            >::type::value == (char)0x80
        ));

        BOOST_TEST((
            mpl::at_c<
                mpl::string<
                    mpl::at_c<
                        mpl::string<'\x7f'>
                      , 0
                    >::type::value
                >
              , 0
            >::type::value == (char)0x7f
        ));

        BOOST_TEST((
            mpl::at_c<
                mpl::string<
                    mpl::at_c<
                        mpl::string<'\x80'>
                      , 0
                    >::type::value
                >
              , 0
            >::type::value == (char)0x80
        ));
    }

    return boost::report_errors();
}


text:
/**
 * Copyright (c) 2017 Melown Technologies SE
 *
 * 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.
 *
 * 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 HOLDER 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.
 */
/**
 * \file vts/tileset.hpp
 * \author Vaclav Blazek <vaclav.blazek@citationtech.net>
 *
 * Tile set access.
 */

#ifndef vtslibs_vts_tileset_detail_hpp_included_
#define vtslibs_vts_tileset_detail_hpp_included_

#include <boost/any.hpp>

#include "../tileset.hpp"
#include "../tileindex.hpp"
#include "driver.hpp"
#include "tilesetindex.hpp"
#include "metacache.hpp"
#include "extra.hpp"

namespace vtslibs { namespace vts {

typedef std::map<std::string, math::Extents2> SdsExtents;

class LoddedTexelSizeAggregator {
public:
    LoddedTexelSizeAggregator()
        : lr_(LodRange::emptyRange())
    {}

    TexelSizeAggregator& operator[](Lod lod) {
        if (lr_.empty()) {
            aggs_.emplace_back();
            lr_ = LodRange(lod);
        } else {
            while (lod < lr_.min) {
                aggs_.emplace(aggs_.begin());
                --lr_.min;
            }
            while (lod > lr_.max) {
                aggs_.emplace_back();
                ++lr_.max;
            }
        }

        return aggs_[lod - lr_.min];
    }

private:
    LodRange lr_;
    std::vector<TexelSizeAggregator> aggs_;
};

bool check(const SdsExtents &l, const SdsExtents &r);

struct TileNode {
    MetaTile::pointer metatile;
    const MetaNode *metanode;

    TileNode() : metatile(), metanode() {}
    TileNode(const MetaTile::pointer &metatile, const MetaNode *metanode)
        : metatile(metatile), metanode(metanode)
    {}

    void update(const TileId &tileId, const MetaNode &mn)
    {
        metatile->update(tileId, mn);
    }

    void set(const TileId &tileId, const MetaNode &mn)
    {
        metatile->set(tileId, mn);
    }

    operator bool() const { return metanode; }
};

/** Driver that implements physical aspects of tile set.
 */
struct TileSet::Detail
{
public:
    registry::ReferenceFrame referenceFrame;

private:
    mutable tileset::Index tsi_;
    tileset::Index *driverTsi_;

public:
    bool readOnly;

    Driver::pointer driver;

    Properties properties;       // current properties
    mutable bool propertiesChanged; // marks that properties have been changed
    mutable bool metadataChanged;   // marks that metadata have been changed
    bool changed() const { return metadataChanged || propertiesChanged; }

    mutable std::unique_ptr<MetaCache> metaTiles;

    tileset::Index &tsi;
    /** Index of existing tiles.
     */
    TileIndex &tileIndex;

    LodRange lodRange;

    SdsExtents sdsExtents;
    LoddedTexelSizeAggregator texelSizeAggregator;

    Detail(const Driver::pointer &driver);
    Detail(const Driver::pointer &driver
           , const TileSet::Properties &properties);
    ~Detail();

    void loadConfig();

    void saveConfig();

    void watch(utility::Runnable *runnable);

    void checkValidity() const;

    MetaTile::pointer findMetaTile(const TileId &tileId, bool addNew = false) const;
    TileNode findNode(const TileId &tileId, bool addNew = false) const;
    const MetaNode* findMetaNode(const TileId &tileId) const;

    int getMetaTileVersion(const TileId &tileId) const;

    void loadTileIndex();
    void saveTileIndex();

    void setTile(const TileId &tileId, const Tile &tile
                 , const NodeInfo *nodeInfo = nullptr);

    void setTile(const TileId &tileId, const TileSource &tile
                 , const NodeInfo *nodeInfo = nullptr);

    void setNavTile(const TileId &tileId, const NavTile &navtile);

    void setSurrogateValue(const TileId &tileId, float value);

    std::uint8_t metaOrder() const;
    TileId metaId(TileId tileId) const;

    void save(const OStream::pointer &os, const Mesh &mesh
              , const Atlas *atlas = nullptr) const;
    void save(const OStream::pointer &os, const Atlas &atlas) const;
    void save(const OStream::pointer &os, const NavTile &navtile) const;

    void load(const IStream::pointer &os, Mesh &mesh) const;
    void load(const IStream::pointer &os, Atlas &atlas) const;
    void load(const NavTile::HeightRange &heightRange
              , const IStream::pointer &os, NavTile &navtile) const;
    void load(const IStream::pointer &os, MeshMask &meshMask) const;

    MetaTile::pointer addNewMetaTile(const TileId &tileId) const;

    MetaTile::pointer loadMetaTileFor(const TileId &tileId) const;

    void updateNode(TileId tileId, const MetaNode &metanode
                    , TileIndex::Flag::value_type extraFlags = 0);

    bool exists(const TileId &tileId) const;
    Mesh getMesh(const TileId &tileId) const;
    MeshMask getMeshMask(const TileId &tileId, bool generate) const;
    void getAtlas(const TileId &tileId, Atlas &atlas) const;
    void getNavTile(const TileId &tileId, NavTile &navtile) const;

    /** Trusts that findMetaNode(tileId) yields the same value as node.
     */
    Mesh getMesh(const TileId &tileId, const MetaNode *node) const;
    MeshMask getMeshMask(const TileId &tileId, const MetaNode *node
                         , bool generate) const;
    void getAtlas(const TileId &tileId, Atlas &atlas
                  , const MetaNode *node) const;
    void getNavTile(const TileId &tileId, NavTile &navtile
                    , const MetaNode *node) const;

    /** Trusts that tileindex flags yield the same information.
     */
    Mesh getMesh(const TileId &tileId, TileIndex::Flag::value_type flags)
        const;
    void getAtlas(const TileId &tileId, Atlas &atlas
                  , TileIndex::Flag::value_type flags) const;

    TileSource getTileSource(const TileId &metaId) const;

    void flush();
    void saveMetadata();
    void emptyCache() const;

    MapConfig mapConfig(bool includeExtra) const;

    static MapConfig mapConfig(const Driver &driver, bool includeExtra);

    MeshTilesConfig meshTilesConfig(bool includeExtra) const;

    static MeshTilesConfig meshTilesConfig(const Driver &driver
                                           , bool includeExtra);

    ExtraTileSetProperties loadExtraConfig() const;
    static ExtraTileSetProperties loadExtraConfig(const Driver &driver);

    registry::RegistryBase loadRegistry() const;
    static registry::RegistryBase loadRegistry(const Driver &driver);

    bool fullyCovered(const TileId &tileId) const;

    TileIndex::Flag::value_type extraFlags(const TileId &tileId) const;

    void setPosition(const registry::Position &position);
    void addCredits(const registry::IdSet &credits);
    void addBoundLayers(const registry::IdSet &boundLayers);

    double texelSize() const;

    void markInfluencedTile(const TileId &tileId);

private:
    void updateProperties(Lod lod, const MetaNode &metanode
                          , const MetaNode &oldMetanode);
    void updateProperties(const NodeInfo &nodeInfo);
    void updateProperties(const Mesh &mesh);
};

inline void TileSet::Detail::checkValidity() const {
    if (!driver) {
        LOGTHROW(err2, storage::NoSuchTileSet)
            << "Tile set <" << properties.id << "> was removed.";
    }
}

inline std::uint8_t TileSet::Detail::metaOrder() const
{
    return referenceFrame.metaBinaryOrder;
}

inline TileId TileSet::Detail::metaId(TileId tileId) const
{
    tileId.x &= ~((1 << referenceFrame.metaBinaryOrder) - 1);
    tileId.y &= ~((1 << referenceFrame.metaBinaryOrder) - 1);
    return tileId;
}

inline const MetaNode* TileSet::Detail::findMetaNode(const TileId &tileId)
    const
{
    // metanode is nullptr if non-existent
    return findNode(tileId).metanode;
}

} } // namespace vtslibs::vts

#endif // vtslibs_vts_tileset_detail_hpp_included_

max_stars_repo_name: HanochZhu/vts-browser-unity-plugin

max_issues_repo_name: HanochZhu/vts-browser-unity-plugin

max_forks_repo_name: HanochZhu/vts-browser-unity-plugin


text:
/*

Copyright (c) 2007, 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.

*/

#ifndef TORRENT_BROADCAST_SOCKET_HPP_INCLUDED
#define TORRENT_BROADCAST_SOCKET_HPP_INCLUDED

#include "libtorrent/config.hpp"
#include "libtorrent/socket.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <list>

namespace libtorrent
{

	TORRENT_EXPORT bool is_local(address const& a);
	TORRENT_EXPORT bool is_loopback(address const& addr);
	TORRENT_EXPORT bool is_multicast(address const& addr);
	TORRENT_EXPORT bool is_any(address const& addr);
	TORRENT_EXPORT int cidr_distance(address const& a1, address const& a2);

	int common_bits(unsigned char const* b1
		, unsigned char const* b2, int n);

	TORRENT_EXPORT address guess_local_address(asio::io_service&);

	typedef boost::function<void(udp::endpoint const& from
		, char* buffer, int size)> receive_handler_t;

	class TORRENT_EXPORT broadcast_socket
	{
	public:
		broadcast_socket(asio::io_service& ios, udp::endpoint const& multicast_endpoint
			, receive_handler_t const& handler, bool loopback = true);
		~broadcast_socket() { close(); }

		void send(char const* buffer, int size, asio::error_code& ec);
		void close();

	private:

		struct socket_entry
		{
			socket_entry(boost::shared_ptr<datagram_socket> const& s): socket(s) {}
			boost::shared_ptr<datagram_socket> socket;
			char buffer[1024];
			udp::endpoint remote;
		};

		void on_receive(socket_entry* s, asio::error_code const& ec
			, std::size_t bytes_transferred);

		std::list<socket_entry> m_sockets;
		udp::endpoint m_multicast_endpoint;
		receive_handler_t m_on_receive;

	};
}

#endif

max_stars_repo_name: importlib/klib

max_issues_repo_name: isuhao/klib

max_forks_repo_name: isuhao/klib


text:
/*
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 *
 * Copyright (c) 2018 Andrey Semashev
 */
/*!
 * \file   atomic/detail/type_traits/is_trivially_default_constructible.hpp
 *
 * This header defines \c is_trivially_default_constructible type trait
 */

#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_

#include <boost/atomic/detail/config.hpp>
#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
#include <type_traits>
#else
#include <boost/type_traits/has_trivial_constructor.hpp>
#endif

#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif

namespace boost {
namespace atomics {
namespace detail {

#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
using std::is_trivially_default_constructible;
#elif !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template< typename T >
using is_trivially_default_constructible = boost::has_trivial_constructor< T >;
#else
template< typename T >
struct is_trivially_default_constructible : public boost::has_trivial_constructor< T > {};
#endif

} // namespace detail
} // namespace atomics
} // namespace boost

#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_

max_stars_repo_name: kindlychung/mediasoup-sfu-cpp

max_issues_repo_name: kindlychung/mediasoup-sfu-cpp

max_forks_repo_name: kindlychung/mediasoup-sfu-cpp


text:
//
// process_per_connection.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/asio/write.hpp>
#include <cstdlib>
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

using boost::asio::ip::tcp;

class server
{
public:
  server(boost::asio::io_context& io_context, unsigned short port)
    : io_context_(io_context),
      signal_(io_context, SIGCHLD),
      acceptor_(io_context, {tcp::v4(), port}),
      socket_(io_context)
  {
    wait_for_signal();
    accept();
  }

private:
  void wait_for_signal()
  {
    signal_.async_wait(
        [this](boost::system::error_code /*ec*/, int /*signo*/)
        {
          // Only the parent process should check for this signal. We can
          // determine whether we are in the parent by checking if the acceptor
          // is still open.
          if (acceptor_.is_open())
          {
            // Reap completed child processes so that we don't end up with
            // zombies.
            int status = 0;
            while (waitpid(-1, &status, WNOHANG) > 0) {}

            wait_for_signal();
          }
        });
  }

  void accept()
  {
    acceptor_.async_accept(
        [this](boost::system::error_code ec, tcp::socket new_socket)
        {
          if (!ec)
          {
            // Take ownership of the newly accepted socket.
            socket_ = std::move(new_socket);

            // Inform the io_context that we are about to fork. The io_context
            // cleans up any internal resources, such as threads, that may
            // interfere with forking.
            io_context_.notify_fork(boost::asio::io_context::fork_prepare);

            if (fork() == 0)
            {
              // Inform the io_context that the fork is finished and that this
              // is the child process. The io_context uses this opportunity to
              // create any internal file descriptors that must be private to
              // the new process.
              io_context_.notify_fork(boost::asio::io_context::fork_child);

              // The child won't be accepting new connections, so we can close
              // the acceptor. It remains open in the parent.
              acceptor_.close();

              // The child process is not interested in processing the SIGCHLD
              // signal.
              signal_.cancel();

              read();
            }
            else
            {

              // Inform the io_context that the fork is finished (or failed)
              // and that this is the parent process. The io_context uses this
              // opportunity to recreate any internal resources that were
              // cleaned up during preparation for the fork.
              io_context_.notify_fork(boost::asio::io_context::fork_parent);

              // The parent process can now close the newly accepted socket. It
              // remains open in the child.
              socket_.close();

              accept();
            }
          }
          else
          {
            std::cerr << "Accept error: " << ec.message() << std::endl;
            accept();
          }
        });
  }

  void read()
  {
    socket_.async_read_some(boost::asio::buffer(data_),
        [this](boost::system::error_code ec, std::size_t length)
        {
          if (!ec)
            write(length);
        });
  }

  void write(std::size_t length)
  {
    boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
        [this](boost::system::error_code ec, std::size_t /*length*/)
        {
          if (!ec)
            read();
        });
  }

  boost::asio::io_context& io_context_;
  boost::asio::signal_set signal_;
  tcp::acceptor acceptor_;
  tcp::socket socket_;
  std::array<char, 1024> data_;
};

int main(int argc, char* argv[])
{
  try
  {
    if (argc != 2)
    {
      std::cerr << "Usage: process_per_connection <port>\n";
      return 1;
    }

    boost::asio::io_context io_context;

    using namespace std; // For atoi.
    server s(io_context, atoi(argv[1]));

    io_context.run();
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << std::endl;
  }
}

max_issues_repo_name: qingkouwei/mediaones

max_forks_repo_name: qingkouwei/mediaones


text:
#ifndef PROTOC_JSON_IARCHIVE_HPP
#define PROTOC_JSON_IARCHIVE_HPP

///////////////////////////////////////////////////////////////////////////////
//
// http://protoc.sourceforge.net/
//
// Copyright (C) 2013 Bjorn Reese <breese@users.sourceforge.net>
//
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)
//
///////////////////////////////////////////////////////////////////////////////

#include <string>
#include <boost/optional.hpp>
#include <boost/archive/detail/common_iarchive.hpp>
#include <boost/archive/detail/register_archive.hpp>
#include <protoc/types.hpp>
#include <protoc/json/reader.hpp>

namespace protoc
{
namespace json
{

class iarchive
    : public boost::archive::detail::common_iarchive<iarchive>
{
    friend class boost::archive::load_access;

public:
    iarchive(const json::reader&);
    template <typename Iterator>
    iarchive(Iterator begin, Iterator end);

    template<typename value_type>
    void load_override(value_type& data, long /*version*/)
    {
        boost::archive::load(*this->This(), data);
    }

    void load();
    void load(bool&);
    void load(int&);
    void load(long long&);
    void load(float&);
    void load(double&);
    void load(std::string&);

    void load_record_begin();
    void load_record_end();

    boost::optional<std::size_t> load_array_begin();
    void load_array_end();
    bool at_array_end() const;

    boost::optional<std::size_t> load_map_begin();
    void load_map_end();
    bool at_map_end() const;

    protoc::token::value type() const;

    // Ignore these
    void load(boost::archive::version_type&) {}
    void load(boost::archive::object_id_type) {}
    void load(boost::archive::object_reference_type) {}
    void load(boost::archive::class_id_type) {}
    void load(boost::archive::class_id_optional_type) {}
    void load(boost::archive::class_id_reference_type) {}
    void load(boost::archive::tracking_type) {}
    void load(boost::archive::class_name_type&) {}

private:
    json::reader reader;
};

} // namespace json
} // namespace protoc

#include <boost/archive/detail/register_archive.hpp>

BOOST_SERIALIZATION_REGISTER_ARCHIVE(protoc::json::iarchive);

#include <protoc/exceptions.hpp>

namespace protoc
{
namespace json
{

inline iarchive::iarchive(const json::reader& reader)
    : reader(reader)
{
}

template <typename Iterator>
inline iarchive::iarchive(Iterator begin, Iterator end)
    : reader(begin, end)
{
}

inline void iarchive::load()
{
    if (reader.type() != protoc::token::token_null)
    {
        return; // FIXME: throw exception?
    }
    reader.next();
}

inline void iarchive::load(bool& value)
{
    value = reader.get_bool();
    reader.next();
}

inline void iarchive::load(int& value)
{
    value = reader.get_int();
    reader.next();
}

inline void iarchive::load(long long& value)
{
    value = reader.get_long_long();
    reader.next();
}

inline void iarchive::load(float& value)
{
    value = reader.get_double();
    reader.next();
}

inline void iarchive::load(double& value)
{
    value = reader.get_double();
    reader.next();
}

inline void iarchive::load(std::string& value)
{
    value = reader.get_string();
    reader.next();
}

inline void iarchive::load_record_begin()
{
    reader.next(protoc::token::token_array_begin);
}

inline void iarchive::load_record_end()
{
    reader.next(protoc::token::token_array_end);
}

inline boost::optional<std::size_t> iarchive::load_array_begin()
{
    reader.next(protoc::token::token_array_begin);
    return boost::optional<std::size_t>();
}

inline void iarchive::load_array_end()
{
    reader.next(protoc::token::token_array_end);
}

inline bool iarchive::at_array_end() const
{
    return (reader.type() == protoc::token::token_array_end);
}

inline boost::optional<std::size_t> iarchive::load_map_begin()
{
    reader.next(protoc::token::token_map_begin);
    return boost::optional<std::size_t>();
}

inline void iarchive::load_map_end()
{
    reader.next(protoc::token::token_map_end);
}

inline bool iarchive::at_map_end() const
{
    return (reader.type() == protoc::token::token_map_end);
}

inline protoc::token::value iarchive::type() const
{
    return reader.type();
}

} // namespace json
} // namespace protoc

#endif // PROTOC_JSON_IARCHIVE_HPP


text:
#pragma once

#include <boost/beast/core/buffers_to_string.hpp>
#include <boost/beast/core/multi_buffer.hpp>
#include <boost/utility/string_view.hpp>

#include <fmt/core.h>

namespace boost
{
fmt::string_view to_string_view(boost::string_view const& v);
}

namespace fmt
{
template <>
struct formatter<boost::beast::multi_buffer>
{
  template <typename ParseContext>
  constexpr auto parse(ParseContext& ctx)
  {
    return ctx.begin();
  }

  template <typename FormatContext>
  auto format(boost::beast::multi_buffer const& b, FormatContext& ctx)
      -> decltype(ctx.out());
};
extern template struct formatter<boost::beast::multi_buffer>;
}

max_stars_repo_name: TankerHQ/fetchpp

max_issues_repo_name: AlexandreBossard/fetchpp

max_forks_repo_name: AlexandreBossard/fetchpp


text:
/*
 * Copyright (c) 2007-2020 Texas A&M University System
 * 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 copyright holders 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 HOLDER 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 <iostream>
#include <string>
#include <signal.h>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <ibrdtn/api/Client.h>
#include <ibrdtn/api/FileBundle.h>
#include <ibrdtn/api/BLOBBundle.h>
#include <ibrcommon/net/tcpclient.h>
#include <ibrcommon/thread/Mutex.h>
#include <ibrcommon/thread/MutexLock.h>
#include <ibrcommon/data/BLOB.h>
#include <ibrcommon/Logger.h>

#include "../DistressNet.h"

using boost::asio::ip::udp;

class udp_server
{
public:
	udp_server( boost::asio::io_service& io_service ) :
		socket_( io_service, udp::endpoint( udp::v6(), 7200 ) )
	{
		//	DTN stuff
		string file_source = "delsargw";

		dtnapiconn_.open( "127.0.0.1", 4550 );
		dtnclient_ = new dtn::api::Client( file_source, dtnapiconn_, dtn::api::Client::MODE_SENDONLY );
		std::cout << "Created dtn client" << std::endl;
		dtnclient_->connect();

		std::cout << "Initialized" << std::endl;
		start_receive();

	}

	~udp_server()
	{
		cout<< "Signal caught..." << endl;
// 		dtnclient_->close();
// 		dtnapiconn_.close();
	}

private:

	void start_receive()
	{
		socket_.async_receive_from(
		    boost::asio::buffer( recv_buffer_ ),
		    remote_endpoint_,
		    boost::bind( &udp_server::handle_receive, this,
		                 boost::asio::placeholders::error,
		                 boost::asio::placeholders::bytes_transferred ) );
	}

	void handle_receive( const boost::system::error_code& error,
	                     std::size_t bytez )
	{
		/*
		 * 	ANYTHING RECEIVED ON FEC0::64 IS NOT COMPLIANT WITH IP
		 * 	IT IS LITTLE ENDIAN, BUT SHOULD BE BIG ENDIAN
		 *
		 *
		 */
		struct timeval now;
		::gettimeofday( &now, 0 );
		char hostname[1024];
		hostname[1023] = '\0';
		gethostname( hostname, 1023 );

		printf( "recvd %ld stuff\n", bytez );
		if ( !error || error == boost::asio::error::message_size )
		{

// 			for (int i = 0; i < bytez; i++)
// 				printf("%d ", recv_buffer_.at(i));
// 			std::cout << std::endl;

			radio_udp_msg_t d1;

			memcpy( &d1, &recv_buffer_, sizeof( radio_udp_msg_t ) );

			//DANGER: the below code is not needed, since i shall use htons on the mote
			//DANGER: always convert tinyos bytes to network convention
// 			t1.mote_id = SwapTwoBytes(t1.mote_id);
// 			t1.loc = swapf(t1.loc);
// 			printf("making tinyos bytes big endian\n");
			//DANGER ENDS

// 			btag.mote_id = ntohs(btag.mote_id);
// 			btag.living = ntohs(btag.living);
// 			btag.dead = ntohs(btag.dead);

			/*			printf("id %d\n", SwapTwoBytes(d1.id));
						printf("index %d\n", SwapTwoBytes(d1.index));
						printf("count %d\ndata: ", SwapTwoBytes(d1.count));*/

			float total = 0.0;
			for ( int i = 0; i < 32; i++ )
			{
// 				printf("%d:%d ", i, SwapTwoBytes(d1.data[i]));
				total += SwapTwoBytes( d1.data[i] );
			}
			std::cout << std::endl;

			float decision = total/32.0;
			printf( "decision: %f \n", decision );
			std::cout << "decision: " << decision << endl;

			//	now send the data over dtn also
			//	-----------------------------------------------
			ibrcommon::BLOB::Reference ref = ibrcommon::BLOB::create();
			stringstream data;

			data << "delsar: EVENT DETECTED ";
			data << "recvd:" << ( now.tv_sec - 946684800 ) << " ";
			data << "data:";
			data << SwapTwoBytes( d1.id ) << "---";
			data << SwapTwoBytes( d1.index ) << "---";
			data << SwapTwoBytes( d1.count ) << "---";

			for ( int i = 0; i < 32; i++ )
				data << SwapTwoBytes( d1.data[i] ) << "=";
			data << "---";

			std::cout << "recvd this: " << data.str() << endl;

			( *ref.iostream() ) << data.str();

			string file_destination = "dtn://router1.dtn/basestation";
			unsigned int lifetime = 9999;
			int priority = 1;

			dtn::api::BLOBBundle b( file_destination, ref );
			b.setLifetime( lifetime );
			b.setPriority( dtn::api::Bundle::BUNDLE_PRIORITY( priority ) );

			if ( decision > 1375 )
			{
				// send the bundle
				*dtnclient_ << b;
				dtnclient_->flush();
			}

			//	also to storage nodes
			string file_destination2 = "dtn://storagenode1.dtn/storageclient";
			dtn::api::BLOBBundle b1( file_destination2, ref );
			b1.setLifetime( lifetime );
			b1.setPriority( dtn::api::Bundle::BUNDLE_PRIORITY( priority ) );
			*dtnclient_ << b1;
			dtnclient_->flush();

			string file_destination3 = "dtn://storagenode2.dtn/storageclient";
			dtn::api::BLOBBundle b2( file_destination3, ref );
			b2.setLifetime( lifetime );
			b2.setPriority( dtn::api::Bundle::BUNDLE_PRIORITY( priority ) );
			*dtnclient_ << b2;
			dtnclient_->flush();

			//	-----------------------------------------------

//  			printf("memcpying %ld bytes\n", sizeof(btag_t));
// 			printf("id  : %d\n", btag.mote_id);
// 			printf("add1: %s\n", btag.address_line_1);
// 			printf("add2: %s\n", btag.address_line_2);
// 			printf("tfor: %s\n", btag.task_force);
// 			printf("livi: %d\n", btag.living);
// 			printf("dead: %d\n", btag.dead);
// 			printf("scom: %d\n", btag.search_complete);

			//	ALWAYS CONVERT TO NETWORK BYTE ORDER
// 			btag.mote_id = htons(btag.mote_id);
// 			btag.living = htons(btag.living);
// 			btag.dead = htons(btag.dead);

			start_receive();
		}
	}

	void handle_send( const boost::system::error_code& /*error*/, std::size_t bytez )
	{
		printf( "sent %ld stuff\n", bytez );
	}

	udp::socket socket_;
	udp::endpoint remote_endpoint_;
	boost::array<unsigned char, 1024> recv_buffer_;
	dtn::api::Client* dtnclient_;
	ibrcommon::tcpclient dtnapiconn_;

};

int main()
{
	std::cout << "starting delsar server" << std::endl;

	boost::asio::io_service io_service;
	udp_server myserver( io_service );
	io_service.run();

// 	// Wait for signal indicating time to shut down.
// 	sigset_t set;
// 	int sig;
// 	int *sigptr = &sig;
// 	int ret_val;
// 	sigemptyset(&set);
// 	sigaddset(&set, SIGINT);
// 	sigprocmask( SIG_BLOCK, &set, NULL );
//
// 	printf("Waiting for a SIGINT signal\n");
//
// 	ret_val = sigwait(&set,sigptr);
// 	if(ret_val == -1)
// 		perror("sigwait failed\n");
// 	else {
// 		if(*sigptr == 2)
// 		{
// 			printf("SIGINT was received\n");
// 			std::cout << "stopping server" << std::endl;
// 			io_service.stop();
// 		}
// 		else
// 			printf("sigwait returned with sig: %d\n", *sigptr);
// 	}

	return 0;
}

max_stars_repo_name: ZareenaSameer/distressnet

max_issues_repo_name: ZareenaSameer/distressnet

max_forks_repo_name: ZareenaSameer/distressnet


text:
// Copyright (c) 2016 Genoil <jw@meneer.net>
// Copyright (c) 2016 Jack Grigg <jack@z.cash>
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "StratumClient.h"
#include "version.h"
#include "streams.h"
//#include "util.h"

#include "utilstrencodings.h"

#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"

using boost::asio::ip::tcp;
using namespace json_spirit;

#include <boost/log/trivial.hpp>

#define BOOST_LOG_CUSTOM(sev) BOOST_LOG_TRIVIAL(sev) << "stratum | "

template <typename Miner, typename Job, typename Solution>
StratumClient<Miner, Job, Solution>::StratumClient(
		std::shared_ptr<boost::asio::io_service> io_s, Miner * m,
        string const & host, string const & port,
        string const & user, string const & pass,
        int const & retries, int const & worktimeout)
    : m_socket(*io_s)
{
	m_io_service = io_s;

    m_primary.host = host;
    m_primary.port = port;
    m_primary.user = user;
    m_primary.pass = pass;

    p_active = &m_primary;

    m_authorized = false;
    m_connected = false;
    m_maxRetries = retries;
    m_worktimeout = worktimeout;

    p_miner = m;
    p_current = nullptr;
    p_previous = nullptr;
    p_worktimer = nullptr;

    startWorking();
}

template <typename Miner, typename Job, typename Solution>
void StratumClient<Miner, Job, Solution>::setFailover(
        string const & host, string const & port)
{
    setFailover(host, port, p_active->user, p_active->pass);
}

template <typename Miner, typename Job, typename Solution>
void StratumClient<Miner, Job, Solution>::setFailover(
        string const & host, string const & port,
        string const & user, string const & pass)
{
    m_failover.host = host;
    m_failover.port = port;
    m_failover.user = user;
    m_failover.pass = pass;
}

template <typename Miner, typename Job, typename Solution>
void StratumClient<Miner, Job, Solution>::startWorking()
{
    m_work.reset(new std::thread([&]() {
        this->workLoop();
    }));
}

template <typename Miner, typename Job, typename Solution>
void StratumClient<Miner, Job, Solution>::workLoop()
{
	if (!p_miner->isMining()) {
		BOOST_LOG_CUSTOM(info) << "Starting miner";
		p_miner->start();
	}

    while (m_running) {
        try {
            if (!m_connected) {
                //m_io_service.run();
                //boost::thread t(boost::bind(&boost::asio::io_service::run, &m_io_service));
                connect();

            }
            read_until(m_socket, m_responseBuffer, "\n");
            std::istream is(&m_responseBuffer);
            std::string response;
            getline(is, response);

			BOOST_LOG_CUSTOM(trace) << "Received: " << response;

            if (!response.empty() && response.front() == '{' && response.back() == '}') {
                Value valResponse;
                if (read_string(response, valResponse) && valResponse.type() == obj_type) {
                    const Object& responseObject = valResponse.get_obj();
                    if (!responseObject.empty()) {
                        processReponse(responseObject);
                        m_response = response;
                    } else {
                        //LogS("[WARN] Response was empty\n");
                    }
                } else {
                    //LogS("[WARN] Parse response failed\n");
                }
            } else {
                //LogS("[WARN] Discarding incomplete response\n");
            }
        } catch (std::exception const& _e) {
			BOOST_LOG_CUSTOM(warning) << _e.what();
            reconnect();
        }
    }
}

template <typename Miner, typename Job, typename Solution>
void StratumClient<Miner, Job, Solution>::connect()
{
	BOOST_LOG_CUSTOM(info) << "Connecting to stratum server " << p_active->host << ":" << p_active->port;

    tcp::resolver r(*m_io_service);
    tcp::resolver::query q(p_active->host, p_active->port);
    tcp::resolver::iterator endpoint_iterator = r.resolve(q);
    tcp::resolver::iterator end;

    boost::system::error_code error = boost::asio::error::host_not_found;
    while (error && endpoint_iterator != end) {
        m_socket.close();
        m_socket.connect(*endpoint_iterator++, error);
    }
    if (error) {
		BOOST_LOG_CUSTOM(error) << "Could not connect to stratum server " <<
			p_active->host << ":" << p_active->port << ", " << error.message();
        reconnect();
    } else {
		BOOST_LOG_CUSTOM(info) << "Connected!";
        m_connected = true;
		std::stringstream ss;
		ss << "{\"id\":1,\"method\":\"mining.subscribe\",\"params\":[\""
			<< p_miner->userAgent() << "\", null,\""
			<< p_active->host << "\",\""
			<< p_active->port << "\"]}\n";
		std::string sss = ss.str();
        std::ostream os(&m_requestBuffer);
		os << sss;
		BOOST_LOG_CUSTOM(trace) << "Sending: " << sss;
        write(m_socket, m_requestBuffer);

		m_share_id = 4;
    }
}

template <typename Miner, typename Job, typename Solution>
void StratumClient<Miner, Job, Solution>::reconnect()
{
	/*if (p_miner->isMining()) {
		BOOST_LOG_CUSTOM(info) << "Stopping miner";
		p_miner->stop();
	}*/
	p_miner->setJob(nullptr);

    if (p_worktimer) {
        p_worktimer->cancel();
        p_worktimer = nullptr;
    }

    //m_io_service.reset();
    //m_socket.close(); // leads to crashes on Linux
    m_authorized = false;
    m_connected = false;

    if (!m_failover.host.empty()) {
        m_retries++;

        if (m_retries > m_maxRetries) {
            if (m_failover.host == "exit") {
                disconnect();
                return;
            } else if (p_active == &m_primary) {
                p_active = &m_failover;
            } else {
                p_active = &m_primary;
            }
            m_retries = 0;
        }
    }

	BOOST_LOG_CUSTOM(info) << "Reconnecting in 3 seconds...";
    boost::asio::deadline_timer timer(*m_io_service, boost::posix_time::seconds(3));
    timer.wait();
}

template <typename Miner, typename Job, typename Solution>
void StratumClient<Miner, Job, Solution>::disconnect()
{
    if (!m_connected) return;
	BOOST_LOG_CUSTOM(info) << "Disconnecting";
    m_connected = false;
    m_running = false;
    if (p_miner->isMining()) {
		BOOST_LOG_CUSTOM(info) << "Stopping miner";
        p_miner->stop();
    }
    m_socket.close();
    //m_io_service.stop();
    if (m_work) {
        m_work->join();
        m_work.reset();
    }
}

template <typename Miner, typename Job, typename Solution>
void StratumClient<Miner, Job, Solution>::processReponse(const Object& responseObject)
{
    const Value& valError = find_value(responseObject, "error");
    if (valError.type() == array_type) {
        const Array& error = valError.get_array();
        string msg;
        if (error.size() > 0 && error[1].type() == str_type) {
            msg = error[1].get_str();
        } else {
            msg = "Unknown error";
        }
        //LogS("%s\n", msg);
    }
    std::ostream os(&m_requestBuffer);
	std::stringstream ss;
    const Value& valId = find_value(responseObject, "id");
    int id = 0;
    if (valId.type() == int_type) {
        id = valId.get_int();
    }
    Value valRes;
    bool accepted = false;
    switch (id) {
	case 0:
	{
		const Value& valMethod = find_value(responseObject, "method");
		string method = "";
		if (valMethod.type() == str_type) {
			method = valMethod.get_str();
		}

		if (method == "mining.notify") {
			const Value& valParams = find_value(responseObject, "params");
			if (valParams.type() == array_type) {
				const Array& params = valParams.get_array();

				Job* workOrder = p_miner->parseJob(params);

				if (workOrder)
				{
					if (!workOrder->clean)
					{
						BOOST_LOG_CUSTOM(info) << CL_CYN "Ignoring non-clean job #" << workOrder->jobId() << CL_N;;
						break;
					}

					BOOST_LOG_CUSTOM(info) << CL_CYN "Received new job #" << workOrder->jobId() << CL_N;
					workOrder->setTarget(m_nextJobTarget);

					if (!(p_current && *workOrder == *p_current)) {
						//x_current.lock();
						//if (p_worktimer)
						//    p_worktimer->cancel();

						if (p_previous) {
							delete p_previous;
						}
						p_previous = p_current;
						p_current = workOrder;

						p_miner->setJob(p_current);
						//x_current.unlock();
						//p_worktimer = new boost::asio::deadline_timer(m_io_service, boost::posix_time::seconds(m_worktimeout));
						//p_worktimer->async_wait(boost::bind(&StratumClient::work_timeout_handler, this, boost::asio::placeholders::error));
					}
				}
			}
		}
		else if (method == "mining.set_target") {
			const Value& valParams = find_value(responseObject, "params");
			if (valParams.type() == array_type) {
				const Array& params = valParams.get_array();
				m_nextJobTarget = params[0].get_str();
				BOOST_LOG_CUSTOM(info) << CL_MAG "Target set to " << m_nextJobTarget << CL_N;
			}
		}
		else if (method == "mining.set_extranonce") {
			const Value& valParams = find_value(responseObject, "params");
			if (valParams.type() == array_type) {
				const Array& params = valParams.get_array();
				p_miner->setServerNonce(params[0].get_str());
			}
		}
		else if (method == "client.reconnect") {
			const Value& valParams = find_value(responseObject, "params");
			if (valParams.type() == array_type) {
				const Array& params = valParams.get_array();
				if (params.size() > 1) {
					p_active->host = params[0].get_str();
					p_active->port = params[1].get_str();
				}
				// TODO: Handle wait time
				BOOST_LOG_CUSTOM(info) << "Reconnection requested";
				reconnect();
			}
		}
		break;
	}
    case 1:
        valRes = find_value(responseObject, "result");
        if (valRes.type() == array_type) {
			BOOST_LOG_CUSTOM(info) << "Subscribed to stratum server";
			const Array& result = valRes.get_array();
            // Ignore session ID for now.
            p_miner->setServerNonce(result[1].get_str());
			ss << "{\"id\":2,\"method\":\"mining.authorize\",\"params\":[\""
			   << p_active->user << "\",\"" << p_active->pass << "\"]}\n";
			std::string sss = ss.str();
			os << sss;
			BOOST_LOG_CUSTOM(trace) << "Sending: " << sss;
            write(m_socket, m_requestBuffer);
        }
        break;
	case 2:
	{
		valRes = find_value(responseObject, "result");
		m_authorized = false;
		if (valRes.type() == bool_type) {
			m_authorized = valRes.get_bool();
		}
		if (!m_authorized) {
			BOOST_LOG_CUSTOM(error) << "Worker not authorized: " << p_active->user;
			disconnect();
			return;
		}
		BOOST_LOG_CUSTOM(info) << "Authorized worker " << p_active->user;

		ss << "{\"id\":3,\"method\":\"mining.extranonce.subscribe\",\"params\":[]}\n";
		std::string sss = ss.str();
		os << sss;
		BOOST_LOG_CUSTOM(trace) << "Sending: " << sss;
		write(m_socket, m_requestBuffer);

		break;
	}
    case 3:
        // nothing to do...
        break;
    default:
        valRes = find_value(responseObject, "result");
        if (valRes.type() == bool_type) {
            accepted = valRes.get_bool();
        }
        if (accepted) {
			BOOST_LOG_CUSTOM(info) << CL_GRN "Accepted share #" << id << CL_N;
            p_miner->acceptedSolution(m_stale);
        } else {
			valRes = find_value(responseObject, "error");
			std::string reason = "unknown";
			if (valRes.type() == array_type)
			{
				const Array& params = valRes.get_array();
				if (params.size() > 1 && params[1].type() == str_type)
					reason = params[1].get_str();
			}
			BOOST_LOG_CUSTOM(warning) << CL_RED "Rejected share #" << id << CL_N " (" << reason << ")";
            p_miner->rejectedSolution(m_stale);
        }
        break;

    }
}

template <typename Miner, typename Job, typename Solution>
void StratumClient<Miner, Job, Solution>::work_timeout_handler(
        const boost::system::error_code& ec)
{
    if (!ec) {
        //LogS("No new work received in %d seconds.\n", m_worktimeout);
        reconnect();
    }
}

template <typename Miner, typename Job, typename Solution>
bool StratumClient<Miner, Job, Solution>::submit(const Solution* solution, const std::string& jobid)
{
	int id = std::atomic_fetch_add(&m_share_id, 1);
	BOOST_LOG_CUSTOM(info) << "Submitting share #" << id << ", nonce " << solution->toString().substr(0, 64 - solution->nonce1size);

	CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
	ss << solution->nonce;
	ss << solution->solution;
	std::string strHex = HexStr(ss.begin(), ss.end());

	std::stringstream stream;
	stream << "{\"id\":" << id << ",\"method\":\"mining.submit\",\"params\":[\"";
	stream << p_active->user;
	stream << "\",\"" << jobid;
	stream << "\",\"" << solution->time;
	stream << "\",\"" << strHex.substr(solution->nonce1size, 64 - solution->nonce1size);
	stream << "\",\"" << strHex.substr(64);
	stream << "\"]}\n";
	std::string json = stream.str();
	std::ostream os(&m_requestBuffer);
	os << json;
	BOOST_LOG_CUSTOM(trace) << "Sending: " << json;
	write(m_socket, m_requestBuffer);

	return true;
}

// create StratumClient class
template class StratumClient<ZcashMiner, ZcashJob, EquihashSolution>;

max_stars_repo_name: bitcoinpostquantum/nheqminer

max_issues_repo_name: bitcoinpostquantum/nheqminer

max_forks_repo_name: bitcoinpostquantum/nheqminer


text:
/*
 * Copyright (c) 2017-2018 Nicholas Corgan (n.corgan@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */

#include <pkmntest/util.hpp>

#include <pkmn/database/item_entry.hpp>

#include <boost/format.hpp>

#include <gtest/gtest.h>

#include <iostream>
#include <string>

class item_entry_none_test: public ::testing::TestWithParam<pkmn::e_game> {};

TEST_P(item_entry_none_test, item_entry_none_test)
{
    pkmn::database::item_entry none_entry(pkmn::e_item::NONE, GetParam());

    EXPECT_EQ(pkmn::e_item::NONE, none_entry.get_item());
    EXPECT_EQ("None", none_entry.get_name());
    EXPECT_EQ("None", none_entry.get_category());
    EXPECT_EQ("None", none_entry.get_pocket());
    EXPECT_EQ("None", none_entry.get_description());
    EXPECT_EQ(-1, none_entry.get_cost());
    EXPECT_FALSE(none_entry.holdable());
    EXPECT_EQ(-1, none_entry.get_fling_power());
    EXPECT_EQ("None", none_entry.get_fling_effect());
    EXPECT_EQ(0, none_entry.get_item_id());
    EXPECT_EQ(0, none_entry.get_item_index());
    EXPECT_EQ(0, none_entry.get_item_list_id());
}

INSTANTIATE_TEST_CASE_P(
    cpp_item_entry_none_test,
    item_entry_none_test,
    ::testing::ValuesIn(pkmntest::ALL_GAMES)
);

class item_entry_test: public ::testing::Test
{
    public:
        static void SetUpTestCase()
        {
            byindex_gen1 = pkmn::database::item_entry(20, 1);
            byindex_gen2 = pkmn::database::item_entry(104, 5);
            byindex_gba  = pkmn::database::item_entry(148, 9);
            byindex_gcn  = pkmn::database::item_entry(536, 20);
            byindex_gen4 = pkmn::database::item_entry(492, 16);
            byindex_gen5 = pkmn::database::item_entry(638, 21);
            byindex_gen6 = pkmn::database::item_entry(769, 25);
            byname_gen1  = pkmn::database::item_entry(pkmn::e_item::POTION, pkmn::e_game::RED);
            byname_gen2  = pkmn::database::item_entry(pkmn::e_item::PINK_BOW, pkmn::e_game::SILVER);
            byname_gba   = pkmn::database::item_entry(pkmn::e_item::RAZZ_BERRY, pkmn::e_game::EMERALD);
            byname_gcn   = pkmn::database::item_entry(pkmn::e_item::BATTLE_CD_03, pkmn::e_game::XD);
            byname_gen4  = pkmn::database::item_entry(pkmn::e_item::FAST_BALL, pkmn::e_game::SOULSILVER);
            byname_gen5  = pkmn::database::item_entry(pkmn::e_item::REVEAL_GLASS, pkmn::e_game::BLACK2);
            byname_gen6  = pkmn::database::item_entry(pkmn::e_item::SALAMENCITE, pkmn::e_game::OMEGA_RUBY);
        }

        static pkmn::database::item_entry byindex_gen1, byname_gen1;
        static pkmn::database::item_entry byindex_gen2, byname_gen2;
        static pkmn::database::item_entry byindex_gba,  byname_gba;
        static pkmn::database::item_entry byindex_gcn,  byname_gcn;
        static pkmn::database::item_entry byindex_gen4, byname_gen4;
        static pkmn::database::item_entry byindex_gen5, byname_gen5;
        static pkmn::database::item_entry byindex_gen6, byname_gen6;
};

pkmn::database::item_entry item_entry_test::byindex_gen1;
pkmn::database::item_entry item_entry_test::byindex_gen2;
pkmn::database::item_entry item_entry_test::byindex_gba;
pkmn::database::item_entry item_entry_test::byindex_gcn;
pkmn::database::item_entry item_entry_test::byindex_gen4;
pkmn::database::item_entry item_entry_test::byindex_gen5;
pkmn::database::item_entry item_entry_test::byindex_gen6;
pkmn::database::item_entry item_entry_test::byname_gen1;
pkmn::database::item_entry item_entry_test::byname_gen2;
pkmn::database::item_entry item_entry_test::byname_gba;
pkmn::database::item_entry item_entry_test::byname_gcn;
pkmn::database::item_entry item_entry_test::byname_gen4;
pkmn::database::item_entry item_entry_test::byname_gen5;
pkmn::database::item_entry item_entry_test::byname_gen6;

/*
 * Make sure item entries can't be instantiated for games that didn't
 * have the given item.
 */
TEST_F(item_entry_test, wrong_game_test)
{
    // Items from later generations
    EXPECT_THROW(
        pkmn::database::item_entry(
            pkmn::e_item::PINK_BOW, pkmn::e_game::RED
        );
    , std::invalid_argument);
    EXPECT_THROW(
        pkmn::database::item_entry(
            pkmn::e_item::RAZZ_BERRY, pkmn::e_game::SILVER
        );
    , std::invalid_argument);
    EXPECT_THROW(
        pkmn::database::item_entry(
            pkmn::e_item::FLAME_PLATE, pkmn::e_game::EMERALD
        );
    , std::invalid_argument);
    EXPECT_THROW(
        pkmn::database::item_entry(
            pkmn::e_item::DNA_SPLICERS, pkmn::e_game::PEARL
        )
    , std::invalid_argument);
    EXPECT_THROW(
        pkmn::database::item_entry(
            pkmn::e_item::MEGA_RING, pkmn::e_game::WHITE
        )
    , std::invalid_argument);

    // Items that were only in certain games within a generation
    EXPECT_THROW(
        pkmn::database::item_entry(
            pkmn::e_item::GS_BALL, pkmn::e_game::GOLD
        )
    , std::invalid_argument);
    pkmn::database::item_entry(
        pkmn::e_item::GS_BALL, pkmn::e_game::CRYSTAL
    );

    EXPECT_THROW(
        pkmn::database::item_entry(
            pkmn::e_item::F_DISK, pkmn::e_game::RUBY
        )
    , std::invalid_argument);
    pkmn::database::item_entry(
        pkmn::e_item::F_DISK, pkmn::e_game::COLOSSEUM
    );
    EXPECT_THROW(
        pkmn::database::item_entry(
            pkmn::e_item::HM01, pkmn::e_game::COLOSSEUM
        )
    , std::invalid_argument);
    pkmn::database::item_entry(
        pkmn::e_item::HM01, pkmn::e_game::RUBY
    );
    EXPECT_THROW(
        pkmn::database::item_entry(
            pkmn::e_item::CLAW_FOSSIL, pkmn::e_game::COLOSSEUM
        )
    , std::invalid_argument);
    pkmn::database::item_entry(
        pkmn::e_item::CLAW_FOSSIL, pkmn::e_game::RUBY
    );

    // Items that didn't make it into later generations
    pkmn::database::item_entry(
        pkmn::e_item::PINK_BOW, pkmn::e_game::SILVER
    );
    EXPECT_THROW(
        pkmn::database::item_entry(
            pkmn::e_item::PINK_BOW, pkmn::e_game::RUBY
        )
    , std::invalid_argument);
}

/*
 * Make sure the name returned from item entries reflects its name
 * from the given game.
 */
TEST_F(item_entry_test, different_name_test)
{
    /*
     * Test an item that changed only once.
     */
    pkmn::database::item_entry elixir1(
        pkmn::e_item::ELIXIR,
        pkmn::e_game::RED
    );
    EXPECT_EQ("Elixer", elixir1.get_name());
    pkmn::database::item_entry elixir2(
        pkmn::e_item::ELIXIR,
        pkmn::e_game::X
    );
    EXPECT_EQ("Elixir", elixir2.get_name());

    /*
     * Test an item that changed twice.
     */
    pkmn::database::item_entry dowsing_machine1(
        pkmn::e_item::DOWSING_MACHINE,
        pkmn::e_game::RED
    );
    EXPECT_EQ("Itemfinder", dowsing_machine1.get_name());
    pkmn::database::item_entry dowsing_machine2(
        pkmn::e_item::DOWSING_MACHINE,
        pkmn::e_game::HEARTGOLD
    );
    EXPECT_EQ("Dowsing MCHN", dowsing_machine2.get_name());
    pkmn::database::item_entry dowsing_machine3(
        pkmn::e_item::DOWSING_MACHINE,
        pkmn::e_game::X
    );
    EXPECT_EQ("Dowsing Machine", dowsing_machine3.get_name());
}

static void invalid_index_test(
    const pkmn::database::item_entry& entry
)
{
    EXPECT_EQ(pkmn::e_item::INVALID, entry.get_item());
    EXPECT_EQ("Invalid (0x258)", entry.get_name());
    EXPECT_EQ("Unknown", entry.get_category());
    EXPECT_EQ("Unknown", entry.get_pocket());
    EXPECT_EQ("Invalid (0x258)", entry.get_description());
    EXPECT_EQ(-1, entry.get_cost());
    EXPECT_FALSE(entry.holdable());
    EXPECT_EQ(-1, entry.get_fling_power());
    EXPECT_EQ((entry.get_game_id() == 20 ? "None" : "Unknown"), entry.get_fling_effect());
}

/*
 * Make sure item entries created from invalid item slots don't
 * try to query the database for information that doesn't
 * exist.
 */
TEST_F(item_entry_test, invalid_index_test)
{
    pkmn::database::item_entry invalid(600, 15);
    pkmn::database::item_entry invalid_gcn(600, 20);
    invalid_index_test(invalid);
    invalid_index_test(invalid_gcn);
}

static void tmhm_entry_check_move(
    const pkmn::database::item_entry& tmhm_entry,
    const std::string& move
)
{
    static boost::format tmhm_desc("Teaches the move %s.");
    EXPECT_EQ(str(tmhm_desc % move.c_str()), tmhm_entry.get_description());
}

/*
 * Make sure TM/HM item entries place the correct corresponding
 * move in the description, even if the item name is the same.
 */
TEST_F(item_entry_test, tmhm_test)
{
    pkmn::database::item_entry tm16_gen1(
        pkmn::e_item::TM16, pkmn::e_game::RED
    );
    pkmn::database::item_entry tm16_gen2(
        pkmn::e_item::TM16, pkmn::e_game::SILVER
    );
    pkmn::database::item_entry tm16_gen3(
        pkmn::e_item::TM16, pkmn::e_game::XD
    );
    tmhm_entry_check_move(tm16_gen1, "Pay Day");
    tmhm_entry_check_move(tm16_gen2, "Icy Wind");
    tmhm_entry_check_move(tm16_gen3, "Light Screen");

    pkmn::database::item_entry tm83_gen4(
        pkmn::e_item::TM83, pkmn::e_game::PLATINUM
    );
    pkmn::database::item_entry tm83_gen5(
        pkmn::e_item::TM83, pkmn::e_game::WHITE
    );
    pkmn::database::item_entry tm83_gen6(
        pkmn::e_item::TM83, pkmn::e_game::OMEGA_RUBY
    );
    tmhm_entry_check_move(tm83_gen4, "Natural Gift");
    tmhm_entry_check_move(tm83_gen5, "Work Up");
    tmhm_entry_check_move(tm83_gen6, "Infestation");

    pkmn::database::item_entry tm83_xy(
        pkmn::e_item::TM94, pkmn::e_game::Y
    );
    pkmn::database::item_entry tm83_oras(
        pkmn::e_item::TM94, pkmn::e_game::ALPHA_SAPPHIRE
    );
    tmhm_entry_check_move(tm83_xy, "Rock Smash");
    tmhm_entry_check_move(tm83_oras, "Secret Power");

    pkmn::database::item_entry hm05_gen3(
        pkmn::e_item::HM05, pkmn::e_game::EMERALD
    );
    pkmn::database::item_entry hm05_dppt(
        pkmn::e_item::HM05, pkmn::e_game::DIAMOND
    );
    pkmn::database::item_entry hm05_hgss(
        pkmn::e_item::HM05, pkmn::e_game::SOULSILVER
    );
    pkmn::database::item_entry hm05_gen5(
        pkmn::e_item::HM05, pkmn::e_game::BLACK
    );
    tmhm_entry_check_move(hm05_gen3, "Flash");
    tmhm_entry_check_move(hm05_dppt, "Defog");
    tmhm_entry_check_move(hm05_hgss, "Whirlpool");
    tmhm_entry_check_move(hm05_gen5, "Waterfall");

    // Gamecube games have no HMs
    EXPECT_THROW(
        pkmn::database::item_entry hm01_gcn(
            pkmn::e_item::HM01, pkmn::e_game::COLOSSEUM
        )
    , std::invalid_argument);
    EXPECT_THROW(
        pkmn::database::item_entry hm01_gcn(
            pkmn::e_item::HM01, pkmn::e_game::XD
        )
    , std::invalid_argument);
}

TEST_F(item_entry_test, equality_test)
{
    EXPECT_TRUE(byindex_gen1 == byname_gen1);
    EXPECT_TRUE(byindex_gen2 == byname_gen2);
    EXPECT_TRUE(byindex_gba  == byname_gba);
    EXPECT_TRUE(byindex_gcn  == byname_gcn);
    EXPECT_TRUE(byindex_gen4 == byname_gen4);
    EXPECT_TRUE(byindex_gen5 == byname_gen5);
    EXPECT_TRUE(byindex_gen6 == byname_gen6);

    EXPECT_TRUE(byindex_gen1 != byname_gen2);
    EXPECT_TRUE(byindex_gen2 != byname_gba);
    EXPECT_TRUE(byindex_gba  != byname_gcn);
    EXPECT_TRUE(byindex_gcn  != byname_gen4);
    EXPECT_TRUE(byindex_gen4 != byname_gen5);
    EXPECT_TRUE(byindex_gen5 != byname_gen6);
}

static void _item_entry_test(
    const pkmn::database::item_entry& item_entry_gen1,
    const pkmn::database::item_entry& item_entry_gen2,
    const pkmn::database::item_entry& item_entry_gba,
    const pkmn::database::item_entry& item_entry_gcn,
    const pkmn::database::item_entry& item_entry_gen4,
    const pkmn::database::item_entry& item_entry_gen5,
    const pkmn::database::item_entry& item_entry_gen6
)
{
    /*
     * For descriptions, just make sure it doesn't fail. If
     * there is no description in the database for the corresponding
     * game, it should fallback onto the X/Y description.
     */

    // Generation I entry
    EXPECT_EQ(pkmn::e_item::POTION, item_entry_gen1.get_item());
    EXPECT_EQ("Potion", item_entry_gen1.get_name());
    EXPECT_EQ(pkmn::e_game::RED, item_entry_gen1.get_game());
    EXPECT_EQ("Healing", item_entry_gen1.get_category());
    EXPECT_EQ("Items", item_entry_gen1.get_pocket());
    (void)item_entry_gen1.get_description();
    EXPECT_EQ(300, item_entry_gen1.get_cost());
    EXPECT_FALSE(item_entry_gen1.holdable());
    EXPECT_EQ(-1, item_entry_gen1.get_fling_power());
    EXPECT_EQ("None", item_entry_gen1.get_fling_effect());

    // Generation II entry
    EXPECT_EQ(pkmn::e_item::PINK_BOW, item_entry_gen2.get_item());
    EXPECT_EQ("Pink Bow", item_entry_gen2.get_name());
    EXPECT_EQ(pkmn::e_game::SILVER, item_entry_gen2.get_game());
    EXPECT_EQ("Stat boosts", item_entry_gen2.get_category());
    EXPECT_EQ("Items", item_entry_gen2.get_pocket());
    (void)item_entry_gen2.get_description();
    EXPECT_EQ(50, item_entry_gen2.get_cost());
    EXPECT_TRUE(item_entry_gen2.holdable());
    EXPECT_EQ(-1, item_entry_gen2.get_fling_power());
    EXPECT_EQ("None", item_entry_gen2.get_fling_effect());

    // GBA entry
    EXPECT_EQ(pkmn::e_item::RAZZ_BERRY, item_entry_gba.get_item());
    EXPECT_EQ("Razz Berry", item_entry_gba.get_name());
    EXPECT_EQ(pkmn::e_game::EMERALD, item_entry_gba.get_game());
    EXPECT_EQ("Baking only", item_entry_gba.get_category());
    EXPECT_EQ("Berries", item_entry_gba.get_pocket());
    (void)item_entry_gba.get_description();
    EXPECT_EQ(20, item_entry_gba.get_cost());
    EXPECT_TRUE(item_entry_gba.holdable());
    EXPECT_EQ(-1, item_entry_gba.get_fling_power());
    EXPECT_EQ("None", item_entry_gba.get_fling_effect());

    // Gamecube entry
    EXPECT_EQ(pkmn::e_item::BATTLE_CD_03, item_entry_gcn.get_item());
    EXPECT_EQ("Battle CD 03", item_entry_gcn.get_name());
    EXPECT_EQ(pkmn::e_game::XD, item_entry_gcn.get_game());
    EXPECT_EQ("Battle CDs", item_entry_gcn.get_category());
    EXPECT_EQ("Battle CDs", item_entry_gcn.get_pocket());
    (void)item_entry_gcn.get_description();
    EXPECT_EQ(0, item_entry_gcn.get_cost());
    EXPECT_FALSE(item_entry_gcn.holdable());
    EXPECT_EQ(-1, item_entry_gcn.get_fling_power());
    EXPECT_EQ("None", item_entry_gcn.get_fling_effect());

    // Generation IV entry
    EXPECT_EQ(pkmn::e_item::FAST_BALL, item_entry_gen4.get_item());
    EXPECT_EQ("Fast Ball", item_entry_gen4.get_name());
    EXPECT_EQ(pkmn::e_game::SOULSILVER, item_entry_gen4.get_game());
    EXPECT_EQ("Apricorn balls", item_entry_gen4.get_category());
    EXPECT_EQ("Poké Balls", item_entry_gen4.get_pocket());
    (void)item_entry_gen4.get_description();
    EXPECT_EQ(300, item_entry_gen4.get_cost());
    EXPECT_TRUE(item_entry_gen4.holdable());
    EXPECT_EQ(0, item_entry_gen4.get_fling_power());
    EXPECT_EQ("None", item_entry_gen4.get_fling_effect());

    // Generation V entry
    EXPECT_EQ(pkmn::e_item::REVEAL_GLASS, item_entry_gen5.get_item());
    EXPECT_EQ("Reveal Glass", item_entry_gen5.get_name());
    EXPECT_EQ(pkmn::e_game::BLACK2, item_entry_gen5.get_game());
    EXPECT_EQ("Gameplay", item_entry_gen5.get_category());
    EXPECT_EQ("Key Items", item_entry_gen5.get_pocket());
    (void)item_entry_gen5.get_description();
    EXPECT_EQ(0, item_entry_gen5.get_cost());
    EXPECT_FALSE(item_entry_gen5.holdable());
    EXPECT_EQ(0, item_entry_gen5.get_fling_power());
    EXPECT_EQ("None", item_entry_gen5.get_fling_effect());

    // Generation VI entry
    EXPECT_EQ(pkmn::e_item::SALAMENCITE, item_entry_gen6.get_item());
    EXPECT_EQ("Salamencite", item_entry_gen6.get_name());
    EXPECT_EQ(pkmn::e_game::OMEGA_RUBY, item_entry_gen6.get_game());
    EXPECT_EQ("Mega Stones", item_entry_gen6.get_category());
    EXPECT_EQ("Items", item_entry_gen6.get_pocket());
    (void)item_entry_gen6.get_description();
    EXPECT_EQ(0, item_entry_gen6.get_cost());
    EXPECT_TRUE(item_entry_gen6.holdable());
    EXPECT_EQ(0, item_entry_gen6.get_fling_power());
    EXPECT_EQ("None", item_entry_gen6.get_fling_effect());
}

TEST_F(item_entry_test, by_index_test)
{
    _item_entry_test(
        byindex_gen1, byindex_gen2, byindex_gba,
        byindex_gcn, byindex_gen4, byindex_gen5,
        byindex_gen6
    );
}

TEST_F(item_entry_test, by_name_test)
{
    _item_entry_test(
        byname_gen1, byname_gen2, byname_gba,
        byname_gcn, byname_gen4, byname_gen5,
        byname_gen6
    );
}

max_stars_repo_name: ncorgan/libpkmn

max_issues_repo_name: PMArkive/libpkmn

max_forks_repo_name: PMArkive/libpkmn


text:
// Copyright (c) 2013-2020 Vittorio Romeo
// License: Academic Free License ("AFL") v. 3.0
// AFL License page: https://opensource.org/licenses/AFL-3.0

#pragma once

#include <algorithm>
#include <array>
#include <atomic>
#include <bitset>
#include <cctype>
#include <chrono>
#include <cmath>
#include <csignal>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <deque>
#include <exception>
#include <filesystem>
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <optional>
#include <random>
#include <set>
#include <sstream>
#include <stdexcept>
#include <string_view>
#include <string>
#include <thread>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <variant>
#include <vector>

#include <boost/pfr.hpp>

#include <sodium.h>

#include <imgui.h>
#include <imgui-SFML.h>
#include <misc/cpp/imgui_stdlib.h>

#include <sqlite3.h>
#include <sqlite_orm.h>

#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>

#include <vrm/pp.hpp>

#include <SSVUtils/Core/Detection/Detection.hpp>
#include <SSVUtils/Core/Common/Common.hpp>

#include <SSVUtils/Core/Common/Frametime.hpp>
#include <SSVUtils/Core/Common/LikelyUnlikely.hpp>
#include <SSVUtils/Core/FileSystem/FileSystem.hpp>
#include <SSVUtils/Core/Log/Log.hpp>
#include <SSVUtils/Core/Utils/Containers.hpp>
#include <SSVUtils/Core/Utils/Math.hpp>
#include <SSVUtils/Core/Utils/Rnd.hpp>
#include <SSVUtils/Internal/PCG/PCG.hpp>
#include <SSVUtils/Timeline/Timeline.hpp>

#include <SSVStart/Camera/Camera.hpp>
#include <SSVStart/GameSystem/GameSystem.hpp>
#include <SSVStart/GameSystem/GameWindow.hpp>
#include <SSVStart/Input/Trigger.hpp>
#include <SSVStart/Utils/Input.hpp>
#include <SSVStart/Utils/SFML.hpp>
#include <SSVStart/Utils/Vector2.hpp>
#include <SSVStart/VertexVector/VertexVector.hpp>

#include <SSVMenuSystem/SSVMenuSystem.hpp>

#include "SSVOpenHexagon/Global/Assert.hpp"
#include "SSVOpenHexagon/Utils/Concat.hpp"

#include "SSVOpenHexagon/SSVUtilsJson/SSVUtilsJson.hpp"
#include "SSVOpenHexagon/Global/UtilsJson.hpp"