<commit_before>
#include "config.h"

// system
#include <iostream>

// boost
#include <boost/filesystem.hpp>

// dune-common
#include <dune/common/exceptions.hh>
#include <dune/common/mpihelper.hh>
#include <dune/common/timer.hh>

// dune-stuff
#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/filesystem.hh>
#include <dune/stuff/common/string.hh>

// dune-grid-multiscale
#include <dune/grid/multiscale/provider/cube.hh>

const std::string id = "provider.cube";

/**
  \brief      Creates a parameter file if it does not exist.

              Nothing is done if the file already exists. If not, a parameter file will be created with all neccessary
              keys and values.
  \param[in]  filename
              (Relative) path to the file.
  **/
void ensureParamFile(std::string filename)
{
  Dune::Stuff::Common::testCreateDirectory(filename);
  if (!boost::filesystem::exists(filename)) {
    std::ofstream file;
    file.open(filename);
    file << "[grid.multiscale.provider.cube]" << std::endl;
    file << "numElements.0 = 2" << std::endl;
    file << "numElements.1 = 2" << std::endl;
    file << "numElements.2 = 2" << std::endl;
    file << "boundaryId = 7" << std::endl;                  // a cube from the factory gets the boundary ids 1 to 4 ind 2d and 1 to 6 in 3d?
    file << "filename = " << id << ".grid" << std::endl;
    file << "partitions.0 = 2" << std::endl;
    file << "partitions.1 = 2" << std::endl;
    file << "partitions.2 = 2" << std::endl;
    file.close();
  } // only write param file if there is none
} // void ensureParamFile()

template< class GridPartType >
void measureTiming(const GridPartType& gridPart, Dune::Stuff::Common::LogStream& out, const std::string name = "")
{
  out << "  walking " << name << " grid part... " << std::flush;
  Dune::Timer timer;
  unsigned int elements = 0;
  for (typename GridPartType::template Codim< 0 >::IteratorType it = gridPart.template begin< 0 >();
       it != gridPart.template end< 0 >();
       ++it)
    ++elements;
  out << " done (has " << elements << " elements, took " << timer.elapsed() << " sek)" << std::endl;
} // void measureTiming()

template< class GlobalGridPartType, class CouplingGridPartType >
void testCoupling(const GlobalGridPartType& globalGridPart, const CouplingGridPartType& couplingGridPart, Dune::Stuff::Common::LogStream& out)
{
  // walk the grid part
  for (typename CouplingGridPartType::template Codim< 0 >::IteratorType entityIterator = couplingGridPart.template begin< 0 >();
       entityIterator != couplingGridPart.template end< 0 >();
       ++entityIterator) {
    const typename CouplingGridPartType::template Codim< 0 >::EntityType& entity = *entityIterator;
    const unsigned int entityIndex = globalGridPart.indexSet().index(entity);
    out << "entity " << entityIndex << ", neighbors " << std::flush;
    // walk the intersections
    for (typename CouplingGridPartType::IntersectionIteratorType intersectionIterator = couplingGridPart.ibegin(entity);
         intersectionIterator != couplingGridPart.iend(entity);
         ++intersectionIterator) {
      const typename CouplingGridPartType::IntersectionIteratorType::Intersection& intersection = *intersectionIterator;
      const typename CouplingGridPartType::IntersectionIteratorType::Intersection::EntityPointer neighborPtr = intersection.outside();
      const typename CouplingGridPartType::template Codim< 0 >::EntityType& neighbor = *neighborPtr;
      const unsigned int neighborIndex = globalGridPart.indexSet().index(neighbor);
      out << neighborIndex << " ";
    } // walk the intersections
    out << std::endl;
  } // walk the grid part
} // void testCoupling()

template< class GlobalGridPartType, class LocalGridPartType, class OutStreamType >
struct Inspect
{
  template< int dim, int codim >
  struct Codim
  {
    static void entities(const GlobalGridPartType& globalGridPart, const LocalGridPartType& localGridPart, const std::string prefix, OutStreamType& out)
    {
      // walk all codim entitites
      for (auto entityIt = localGridPart.template begin< codim >(); entityIt != localGridPart.template end< codim >(); ++entityIt) {
        const auto& entity = *entityIt;
        const auto& geometryType = entity.type();
        const auto globalIndex = globalGridPart.indexSet().index(entity);
        const auto localIndex = localGridPart.indexSet().index(entity);
        out << prefix << geometryType << ", global index " << globalIndex << ", local index " << localIndex << std::endl;
        out << prefix << "  corners: ";
        auto geometry = entity.geometry();
        for (int i = 0; i < (geometry.corners() - 1); ++i)
          out << "(" << geometry.corner(i) << "), ";
        out << "(" << geometry.corner(geometry.corners() - 1) << ")" << std::endl;
      } // walk all codim entitites
      // increase Codim
      Inspect< GlobalGridPartType, LocalGridPartType, OutStreamType >::Codim< dim, codim + 1 >::entities(globalGridPart, localGridPart, prefix, out);
    }
  }; // struct Codim
}; // struct Inspect

template< class GlobalGridPartType, class LocalGridPartType, class OutStreamType >
template< int codim >
struct Inspect< GlobalGridPartType, LocalGridPartType, OutStreamType >::Codim< codim, codim >
{
  static void entities(const GlobalGridPartType& globalGridPart, const LocalGridPartType& localGridPart, const std::string prefix, OutStreamType& out)
  {
    // walk all codim entitites
    for (auto entityIt = localGridPart.template begin< codim >(); entityIt != localGridPart.template end< codim >(); ++entityIt) {
      const auto& entity = *entityIt;
      const auto& geometryType = entity.type();
      const auto globalIndex = globalGridPart.indexSet().index(entity);
      const auto localIndex = localGridPart.indexSet().index(entity);
      out << prefix << geometryType << ", global index " << globalIndex << ", local index " << localIndex << std::endl;
      out << prefix << "  corners: (" << entity.geometry().center() << ")" << std::endl;
    } // walk all codim entitites
  }
};

int main(int argc, char** argv)
{
  try {
    // mpi
    Dune::MPIHelper::instance(argc, argv);

    // parameter
    const std::string filename = id + ".param";
    ensureParamFile(filename);
    Dune::Stuff::Common::ExtendedParameterTree paramTree(argc, argv, filename);

    // logger
    Dune::Stuff::Common::Logger().create(Dune::Stuff::Common::LOG_INFO |
                                         Dune::Stuff::Common::LOG_CONSOLE |
                                         Dune::Stuff::Common::LOG_DEBUG);
    Dune::Stuff::Common::LogStream& info = Dune::Stuff::Common::Logger().debug();
    Dune::Stuff::Common::LogStream& debug = Dune::Stuff::Common::Logger().debug();

    // timer
    Dune::Timer timer;

    // grid
    info << "setting up grid";
//    info << ":" << std::endl;
    info << "... " << std::flush;
    debug.suspend();
    typedef Dune::grid::Multiscale::Provider::Cube<> GridProviderType;
    paramTree.assertSub(GridProviderType::id(), id);
    GridProviderType gridProvider(paramTree.sub(GridProviderType::id()));
    typedef GridProviderType::MsGridType MsGridType;
    const MsGridType& msGrid = gridProvider.msGrid();
    info << "  took " << timer.elapsed()
         << " sec (has " << msGrid.globalGridPart()->grid().size(0) << " elements, "
         << msGrid.size() << " subdomains)" << std::endl;
    debug.resume();

    info << "visualizing... " << std::flush;
    debug.suspend();
    timer.reset();
    msGrid.visualize();
    info << " done (took " << timer.elapsed() << " sek)" << std::endl;
    debug.resume();

    info << "inspecting global grid part:" << std::endl;
    const auto& globalGridPart = *(msGrid.globalGridPart());
    Inspect< MsGridType::GlobalGridPartType, MsGridType::GlobalGridPartType, Dune::Stuff::Common::LogStream >
        ::Codim< GridProviderType::dim, 0 >
        ::entities(globalGridPart, globalGridPart, "  ", debug);

    info << "inspecting local grid parts:" << std::endl;
    for (unsigned int subdomain = 0; subdomain < msGrid.size(); ++subdomain) {
      info << "subdomain " << subdomain << std::endl;
      const auto& localGridPart = *(msGrid.localGridPart(subdomain));
      Inspect< MsGridType::GlobalGridPartType, MsGridType::LocalGridPartType, Dune::Stuff::Common::LogStream >
          ::Codim< GridProviderType::dim, 0 >
          ::entities(globalGridPart, localGridPart, "  ", debug);
    }

    info << "inspecting boundary grid parts:" << std::endl;
    for (unsigned int subdomain = 0; subdomain < msGrid.size(); ++subdomain) {
      if (msGrid.boundary(subdomain)) {
        info << "subdomain " << subdomain << std::endl;
        const auto& boundaryGridPart = *(msGrid.boundaryGridPart(subdomain));
        Inspect< MsGridType::GlobalGridPartType, MsGridType::BoundaryGridPartType, Dune::Stuff::Common::LogStream >
            ::Codim< GridProviderType::dim, 0 >
            ::entities(globalGridPart, boundaryGridPart, "  ", debug);
      }
    }

//    // time grid parts
//    info << "timing grid parts:" << std::endl;
//    typedef MsGridType::GlobalGridPartType GlobalGridPartType;
//    const Dune::shared_ptr< const GlobalGridPartType > globalGridPart = msGrid.globalGridPart();
//    measureTiming(*globalGridPart, info, "global");
//    typedef MsGridType::CouplingGridPartType CouplingGridPartType;
//    const unsigned int neighbor = *(msGrid.neighborsOf(0)->begin());
//    const Dune::shared_ptr< const CouplingGridPartType > couplingGridPart = msGrid.couplingGridPart(0, neighbor);
//    measureTiming(*couplingGridPart, info, "coupling (subdomain 0 with " + Dune::Stuff::Common::String::convertTo(neighbor) + ")");
//    typedef MsGridType::LocalGridPartType LocalGridPartType;
//    const Dune::shared_ptr< const LocalGridPartType > firstLocalGridPart = msGrid.localGridPart(0);
//    measureTiming(*firstLocalGridPart, info, "local (subdomain 0)");
//    for (unsigned int subdomain = 1; subdomain < msGrid.size(); ++subdomain) {
//      const Dune::shared_ptr< const LocalGridPartType > localGridPart = msGrid.localGridPart(subdomain);
//      measureTiming(*localGridPart, debug, "local (subdomain " + Dune::Stuff::Common::String::convertTo(subdomain) + ")");
//    }

//    // test coupling grid part
//    info << "testing coupling grid part:" << std::endl;
//    testCoupling(*globalGridPart, *couplingGridPart, info);

    // if we came that far we can as well be happy about it
    return 0;
  } catch(Dune::Exception& e) {
    std::cerr << "Dune reported error: " << e.what() << std::endl;
  } catch(std::exception& e) {
    std::cerr << e.what() << std::endl;
  } catch(...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
  } // try
} // main
<commit_msg>[examples.provider.cube] update<commit_after>
#include "config.h"

// system
#include <iostream>

// boost
#include <boost/filesystem.hpp>

// dune-common
#include <dune/common/exceptions.hh>
#include <dune/common/mpihelper.hh>
#include <dune/common/timer.hh>

// dune-stuff
#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/filesystem.hh>
#include <dune/stuff/common/string.hh>

// dune-grid-multiscale
#include <dune/grid/multiscale/provider/cube.hh>

const std::string id = "provider.cube";

/**
  \brief      Creates a parameter file if it does not exist.

              Nothing is done if the file already exists. If not, a parameter file will be created with all neccessary
              keys and values.
  \param[in]  filename
              (Relative) path to the file.
  **/
void ensureParamFile(std::string filename)
{
  Dune::Stuff::Common::testCreateDirectory(filename);
  if (!boost::filesystem::exists(filename)) {
    std::ofstream file;
    file.open(filename);
    file << "[" << id << "]" << std::endl;
    file << "filename = " << id << ".grid" << std::endl;
    file << "[grid.multiscale.provider.cube]" << std::endl;
    file << "numElements = [4; 4; 4]" << std::endl;
    file << "partitions = [2; 2; 2]" << std::endl;
    file << "boundaryId = 7" << std::endl; // a cube from the factory gets the boundary ids 1 to 4 ind 2d and 1 to 6 in 3d?
    file.close();
  } // only write param file if there is none
} // void ensureParamFile()

template< class GridPartType >
void measureTiming(const GridPartType& gridPart, Dune::Stuff::Common::LogStream& out, const std::string name = "")
{
  out << "  walking " << name << " grid part... " << std::flush;
  Dune::Timer timer;
  unsigned int elements = 0;
  for (typename GridPartType::template Codim< 0 >::IteratorType it = gridPart.template begin< 0 >();
       it != gridPart.template end< 0 >();
       ++it)
    ++elements;
  out << " done (has " << elements << " elements, took " << timer.elapsed() << " sek)" << std::endl;
} // void measureTiming()

template< class GlobalGridPartType, class CouplingGridPartType >
void testCoupling(const GlobalGridPartType& globalGridPart, const CouplingGridPartType& couplingGridPart, Dune::Stuff::Common::LogStream& out)
{
  // walk the grid part
  for (typename CouplingGridPartType::template Codim< 0 >::IteratorType entityIterator = couplingGridPart.template begin< 0 >();
       entityIterator != couplingGridPart.template end< 0 >();
       ++entityIterator) {
    const typename CouplingGridPartType::template Codim< 0 >::EntityType& entity = *entityIterator;
    const unsigned int entityIndex = globalGridPart.indexSet().index(entity);
    out << "entity " << entityIndex << ", neighbors " << std::flush;
    // walk the intersections
    for (typename CouplingGridPartType::IntersectionIteratorType intersectionIterator = couplingGridPart.ibegin(entity);
         intersectionIterator != couplingGridPart.iend(entity);
         ++intersectionIterator) {
      const typename CouplingGridPartType::IntersectionIteratorType::Intersection& intersection = *intersectionIterator;
      const typename CouplingGridPartType::IntersectionIteratorType::Intersection::EntityPointer neighborPtr = intersection.outside();
      const typename CouplingGridPartType::template Codim< 0 >::EntityType& neighbor = *neighborPtr;
      const unsigned int neighborIndex = globalGridPart.indexSet().index(neighbor);
      out << neighborIndex << " ";
    } // walk the intersections
    out << std::endl;
  } // walk the grid part
} // void testCoupling()

template< class GlobalGridPartType, class LocalGridPartType, class OutStreamType >
struct Inspect
{
  template< int dim, int codim >
  struct Codim
  {
    static void entities(const GlobalGridPartType& globalGridPart, const LocalGridPartType& localGridPart, const std::string prefix, OutStreamType& out)
    {
      // walk all codim entitites
      for (auto entityIt = localGridPart.template begin< codim >(); entityIt != localGridPart.template end< codim >(); ++entityIt) {
        const auto& entity = *entityIt;
        const auto& geometryType = entity.type();
        const auto globalIndex = globalGridPart.indexSet().index(entity);
        const auto localIndex = localGridPart.indexSet().index(entity);
        out << prefix << geometryType << ", global index " << globalIndex << ", local index " << localIndex << std::endl;
        out << prefix << "  corners: ";
        auto geometry = entity.geometry();
        for (int i = 0; i < (geometry.corners() - 1); ++i)
          out << "(" << geometry.corner(i) << "), ";
        out << "(" << geometry.corner(geometry.corners() - 1) << ")" << std::endl;
      } // walk all codim entitites
      // increase Codim
      Inspect< GlobalGridPartType, LocalGridPartType, OutStreamType >::Codim< dim, codim + 1 >::entities(globalGridPart, localGridPart, prefix, out);
    }
  }; // struct Codim
}; // struct Inspect

template< class GlobalGridPartType, class LocalGridPartType, class OutStreamType >
template< int codim >
struct Inspect< GlobalGridPartType, LocalGridPartType, OutStreamType >::Codim< codim, codim >
{
  static void entities(const GlobalGridPartType& globalGridPart, const LocalGridPartType& localGridPart, const std::string prefix, OutStreamType& out)
  {
    // walk all codim entitites
    for (auto entityIt = localGridPart.template begin< codim >(); entityIt != localGridPart.template end< codim >(); ++entityIt) {
      const auto& entity = *entityIt;
      const auto& geometryType = entity.type();
      const auto globalIndex = globalGridPart.indexSet().index(entity);
      const auto localIndex = localGridPart.indexSet().index(entity);
      out << prefix << geometryType << ", global index " << globalIndex << ", local index " << localIndex << std::endl;
      out << prefix << "  corners: (" << entity.geometry().center() << ")" << std::endl;
    } // walk all codim entitites
  }
};

int main(int argc, char** argv)
{
  try {
    // mpi
    Dune::MPIHelper::instance(argc, argv);

    // parameter
    const std::string filename = id + ".param";
    ensureParamFile(filename);
    Dune::Stuff::Common::ExtendedParameterTree paramTree(argc, argv, filename);

    // logger
    Dune::Stuff::Common::Logger().create(Dune::Stuff::Common::LOG_INFO |
                                         Dune::Stuff::Common::LOG_CONSOLE |
                                         Dune::Stuff::Common::LOG_DEBUG);
    Dune::Stuff::Common::LogStream& info = Dune::Stuff::Common::Logger().debug();
    Dune::Stuff::Common::LogStream& debug = Dune::Stuff::Common::Logger().debug();

    // timer
    Dune::Timer timer;

    // grid
    info << "setting up grid";
//    info << ":" << std::endl;
    info << "... " << std::flush;
    debug.suspend();
    typedef Dune::grid::Multiscale::Provider::Cube<> GridProviderType;
    GridProviderType gridProvider = GridProviderType::createFromParamTree(paramTree);
    typedef GridProviderType::MsGridType MsGridType;
    const Dune::shared_ptr< const MsGridType > msGrid = gridProvider.msGrid();
    info << "  took " << timer.elapsed()
         << " sec (has " << msGrid->globalGridPart()->grid().size(0) << " elements, "
         << msGrid->size() << " subdomains)" << std::endl;
    debug.resume();

    info << "visualizing... " << std::flush;
    debug.suspend();
    timer.reset();
    msGrid->visualize();
    info << " done (took " << timer.elapsed() << " sek)" << std::endl;
    debug.resume();

    info << "inspecting global grid part:" << std::endl;
    const auto& globalGridPart = *(msGrid->globalGridPart());
    Inspect< MsGridType::GlobalGridPartType, MsGridType::GlobalGridPartType, Dune::Stuff::Common::LogStream >
        ::Codim< GridProviderType::dim, 0 >
        ::entities(globalGridPart, globalGridPart, "  ", debug);

    info << "inspecting local grid parts:" << std::endl;
    for (unsigned int subdomain = 0; subdomain < msGrid->size(); ++subdomain) {
      info << "subdomain " << subdomain << std::endl;
      const auto& localGridPart = *(msGrid->localGridPart(subdomain));
      Inspect< MsGridType::GlobalGridPartType, MsGridType::LocalGridPartType, Dune::Stuff::Common::LogStream >
          ::Codim< GridProviderType::dim, 0 >
          ::entities(globalGridPart, localGridPart, "  ", debug);
    }

    info << "inspecting boundary grid parts:" << std::endl;
    for (unsigned int subdomain = 0; subdomain < msGrid->size(); ++subdomain) {
      if (msGrid->boundary(subdomain)) {
        info << "subdomain " << subdomain << std::endl;
        const auto& boundaryGridPart = *(msGrid->boundaryGridPart(subdomain));
        Inspect< MsGridType::GlobalGridPartType, MsGridType::BoundaryGridPartType, Dune::Stuff::Common::LogStream >
            ::Codim< GridProviderType::dim, 0 >
            ::entities(globalGridPart, boundaryGridPart, "  ", debug);
      }
    }

//    // time grid parts
//    info << "timing grid parts:" << std::endl;
//    typedef MsGridType::GlobalGridPartType GlobalGridPartType;
//    const Dune::shared_ptr< const GlobalGridPartType > globalGridPart = msGrid->globalGridPart();
//    measureTiming(*globalGridPart, info, "global");
//    typedef MsGridType::CouplingGridPartType CouplingGridPartType;
//    const unsigned int neighbor = *(msGrid->neighborsOf(0)->begin());
//    const Dune::shared_ptr< const CouplingGridPartType > couplingGridPart = msGrid->couplingGridPart(0, neighbor);
//    measureTiming(*couplingGridPart, info, "coupling (subdomain 0 with " + Dune::Stuff::Common::String::convertTo(neighbor) + ")");
//    typedef MsGridType::LocalGridPartType LocalGridPartType;
//    const Dune::shared_ptr< const LocalGridPartType > firstLocalGridPart = msGrid->localGridPart(0);
//    measureTiming(*firstLocalGridPart, info, "local (subdomain 0)");
//    for (unsigned int subdomain = 1; subdomain < msGrid->size(); ++subdomain) {
//      const Dune::shared_ptr< const LocalGridPartType > localGridPart = msGrid->localGridPart(subdomain);
//      measureTiming(*localGridPart, debug, "local (subdomain " + Dune::Stuff::Common::String::convertTo(subdomain) + ")");
//    }

//    // test coupling grid part
//    info << "testing coupling grid part:" << std::endl;
//    testCoupling(*globalGridPart, *couplingGridPart, info);

    // if we came that far we can as well be happy about it
    return 0;
  } catch(Dune::Exception& e) {
    std::cerr << "Dune reported error: " << e.what() << std::endl;
  } catch(std::exception& e) {
    std::cerr << e.what() << std::endl;
  } catch(...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
  } // try
} // main
<|endoftext|>


<commit_before>/*

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_TIME_HPP_INCLUDED
#define TORRENT_TIME_HPP_INCLUDED

#include <ctime>

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

namespace libtorrent
{
	inline char const* time_now_string()
	{
		time_t t = std::time(0);
		return std::ctime(&t);
	}
}

#if (!defined (__MACH__) && !defined (_WIN32) && !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0) || defined (TORRENT_USE_BOOST_DATE_TIME)

#include <boost/date_time/posix_time/posix_time_types.hpp>

namespace libtorrent
{
	typedef boost::posix_time::ptime ptime;
	typedef boost::posix_time::time_duration time_duration;
	inline ptime time_now()
	{ return boost::posix_time::microsec_clock::universal_time(); }
	inline ptime min_time()
	{ return boost::posix_time::ptime(boost::posix_time::min_date_time); }
	inline ptime max_time()
	{ return boost::posix_time::ptime(boost::posix_time::max_date_time); }
	inline time_duration seconds(int s) { return boost::posix_time::seconds(s); }
	inline time_duration milliseconds(int s) { return boost::posix_time::milliseconds(s); }
	inline time_duration microsec(int s) { return boost::posix_time::microsec(s); }
	inline time_duration minutes(int s) { return boost::posix_time::minutes(s); }
	inline time_duration hours(int s) { return boost::posix_time::hours(s); }

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

}

#else

#include <asio/time_traits.hpp>
#include <boost/cstdint.hpp>

namespace libtorrent
{
	// libtorrent time_duration type
	struct time_duration
	{
		time_duration() {}
		explicit time_duration(boost::int64_t d) : diff(d) {}
		boost::int64_t diff;
	};

	inline bool is_negative(time_duration dt) { return dt.diff < 0; }
	inline bool operator<(time_duration lhs, time_duration rhs)
	{ return lhs.diff < rhs.diff; }
	inline bool operator>(time_duration lhs, time_duration rhs)
	{ return lhs.diff > rhs.diff; }

	// libtorrent time type
	struct ptime
	{
		ptime() {}
		explicit ptime(boost::int64_t t): time(t) {}
		boost::int64_t time;
	};

	inline bool operator>(ptime lhs, ptime rhs)
	{ return lhs.time > rhs.time; }
	inline bool operator>=(ptime lhs, ptime rhs)
	{ return lhs.time >= rhs.time; }
	inline bool operator<=(ptime lhs, ptime rhs)
	{ return lhs.time <= rhs.time; }
	inline bool operator<(ptime lhs, ptime rhs)
	{ return lhs.time < rhs.time; }
	inline bool operator!=(ptime lhs, ptime rhs)
	{ return lhs.time != rhs.time;}
	inline bool operator==(ptime lhs, ptime rhs)
	{ return lhs.time == rhs.time;}
	inline time_duration operator-(ptime lhs, ptime rhs)
	{ return time_duration(lhs.time - rhs.time); }
	inline ptime operator+(ptime lhs, time_duration rhs)
	{ return ptime(lhs.time + rhs.diff); }
	inline ptime operator+(time_duration lhs, ptime rhs)
	{ return ptime(rhs.time + lhs.diff); }
	inline ptime operator-(ptime lhs, time_duration rhs)
	{ return ptime(lhs.time - rhs.diff); }

	ptime time_now();
	inline ptime min_time() { return ptime(0); }
	inline ptime max_time() { return ptime((std::numeric_limits<boost::int64_t>::max)()); }
	int total_seconds(time_duration td);
	int total_milliseconds(time_duration td);
	boost::int64_t total_microseconds(time_duration td);
}

// asio time_traits
namespace asio
{
	template<>
	struct time_traits<libtorrent::ptime>
	{
		typedef libtorrent::ptime time_type;
		typedef libtorrent::time_duration duration_type;
		static time_type now()
		{ return time_type(libtorrent::time_now()); }
		static time_type add(time_type t, duration_type d)
		{ return time_type(t.time + d.diff);}
		static duration_type subtract(time_type t1, time_type t2)
		{ return duration_type(t1 - t2); }
		static bool less_than(time_type t1, time_type t2)
		{ return t1 < t2; }
		static boost::posix_time::time_duration to_posix_duration(
			duration_type d)
		{ return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); }
	};
}

#if defined(__MACH__)

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

// high precision timer for darwin intel and ppc

namespace libtorrent
{
	namespace aux
	{
		inline boost::int64_t absolutetime_to_microseconds(boost::int64_t at)
		{
			static mach_timebase_info_data_t timebase_info = {0,0};
			if (timebase_info.denom == 0)
				mach_timebase_info(&timebase_info);
			// make sure we don't overflow
			assert((at >= 0 && at >= at / 1000 * timebase_info.numer / timebase_info.denom)
				|| (at < 0 && at < at / 1000 * timebase_info.numer / timebase_info.denom));
			return at / 1000 * timebase_info.numer / timebase_info.denom;
		}

		inline boost::int64_t microseconds_to_absolutetime(boost::int64_t ms)
		{
			static mach_timebase_info_data_t timebase_info = {0,0};
			if (timebase_info.denom == 0)
			{
				mach_timebase_info(&timebase_info);
				assert(timebase_info.numer > 0);
				assert(timebase_info.denom > 0);
			}
			// make sure we don't overflow
			assert((ms >= 0 && ms <= ms * timebase_info.denom / timebase_info.numer * 1000)
				|| (ms < 0 && ms > ms * timebase_info.denom / timebase_info.numer * 1000));
			return ms * timebase_info.denom / timebase_info.numer * 1000;
		}
	}

	inline int total_seconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff)
			/ 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff)
			/ 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff);
	}

	inline ptime time_now() { return ptime(mach_absolute_time()); }

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s));
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000));
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000));
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60));
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60 * 60));
	}

}
#elif defined(_WIN32)

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>

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

			return pc * 1000000 / performace_counter_frequency.QuadPart;
		}

		inline boost::int64_t microseconds_to_performance_counter(boost::int64_t ms)
		{
			static LARGE_INTEGER performace_counter_frequency = {0,0};
			if (performace_counter_frequency.QuadPart == 0)
				QueryPerformanceFrequency(&performace_counter_frequency);
			return ms * performace_counter_frequency.QuadPart / 1000000;
		}
	}

	inline int total_seconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff)
			/ 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff)
			/ 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff);
	}

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

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(s));
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000));
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000));
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000 * 60));
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000 * 60 * 60));
	}

}

#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0

#include <time.h>

namespace libtorrent
{
	inline int total_seconds(time_duration td)
	{
		return td.diff / 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return td.diff / 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return td.diff;
	}

	inline ptime time_now()
	{
		timespec ts;
		clock_gettime(CLOCK_MONOTONIC, &ts);
		return ptime(boost::int64_t(ts.tv_sec) + ts.tv_nsec / 1000);
	}

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(s);
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(s * 1000);
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(s * 1000000);
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(s * 1000000 * 60);
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(s * 1000000 * 60 * 60);
	}

}

#endif

#endif
#endif

<commit_msg>fixed timer on linux<commit_after>/*

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_TIME_HPP_INCLUDED
#define TORRENT_TIME_HPP_INCLUDED

#include <ctime>

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

namespace libtorrent
{
	inline char const* time_now_string()
	{
		time_t t = std::time(0);
		return std::ctime(&t);
	}
}

#if (!defined (__MACH__) && !defined (_WIN32) && !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0) || defined (TORRENT_USE_BOOST_DATE_TIME)

#include <boost/date_time/posix_time/posix_time_types.hpp>

namespace libtorrent
{
	typedef boost::posix_time::ptime ptime;
	typedef boost::posix_time::time_duration time_duration;
	inline ptime time_now()
	{ return boost::posix_time::microsec_clock::universal_time(); }
	inline ptime min_time()
	{ return boost::posix_time::ptime(boost::posix_time::min_date_time); }
	inline ptime max_time()
	{ return boost::posix_time::ptime(boost::posix_time::max_date_time); }
	inline time_duration seconds(int s) { return boost::posix_time::seconds(s); }
	inline time_duration milliseconds(int s) { return boost::posix_time::milliseconds(s); }
	inline time_duration microsec(int s) { return boost::posix_time::microsec(s); }
	inline time_duration minutes(int s) { return boost::posix_time::minutes(s); }
	inline time_duration hours(int s) { return boost::posix_time::hours(s); }

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

}

#else

#include <asio/time_traits.hpp>
#include <boost/cstdint.hpp>

namespace libtorrent
{
	// libtorrent time_duration type
	struct time_duration
	{
		time_duration() {}
		explicit time_duration(boost::int64_t d) : diff(d) {}
		boost::int64_t diff;
	};

	inline bool is_negative(time_duration dt) { return dt.diff < 0; }
	inline bool operator<(time_duration lhs, time_duration rhs)
	{ return lhs.diff < rhs.diff; }
	inline bool operator>(time_duration lhs, time_duration rhs)
	{ return lhs.diff > rhs.diff; }

	// libtorrent time type
	struct ptime
	{
		ptime() {}
		explicit ptime(boost::int64_t t): time(t) {}
		boost::int64_t time;
	};

	inline bool operator>(ptime lhs, ptime rhs)
	{ return lhs.time > rhs.time; }
	inline bool operator>=(ptime lhs, ptime rhs)
	{ return lhs.time >= rhs.time; }
	inline bool operator<=(ptime lhs, ptime rhs)
	{ return lhs.time <= rhs.time; }
	inline bool operator<(ptime lhs, ptime rhs)
	{ return lhs.time < rhs.time; }
	inline bool operator!=(ptime lhs, ptime rhs)
	{ return lhs.time != rhs.time;}
	inline bool operator==(ptime lhs, ptime rhs)
	{ return lhs.time == rhs.time;}
	inline time_duration operator-(ptime lhs, ptime rhs)
	{ return time_duration(lhs.time - rhs.time); }
	inline ptime operator+(ptime lhs, time_duration rhs)
	{ return ptime(lhs.time + rhs.diff); }
	inline ptime operator+(time_duration lhs, ptime rhs)
	{ return ptime(rhs.time + lhs.diff); }
	inline ptime operator-(ptime lhs, time_duration rhs)
	{ return ptime(lhs.time - rhs.diff); }

	ptime time_now();
	inline ptime min_time() { return ptime(0); }
	inline ptime max_time() { return ptime((std::numeric_limits<boost::int64_t>::max)()); }
	int total_seconds(time_duration td);
	int total_milliseconds(time_duration td);
	boost::int64_t total_microseconds(time_duration td);
}

// asio time_traits
namespace asio
{
	template<>
	struct time_traits<libtorrent::ptime>
	{
		typedef libtorrent::ptime time_type;
		typedef libtorrent::time_duration duration_type;
		static time_type now()
		{ return time_type(libtorrent::time_now()); }
		static time_type add(time_type t, duration_type d)
		{ return time_type(t.time + d.diff);}
		static duration_type subtract(time_type t1, time_type t2)
		{ return duration_type(t1 - t2); }
		static bool less_than(time_type t1, time_type t2)
		{ return t1 < t2; }
		static boost::posix_time::time_duration to_posix_duration(
			duration_type d)
		{ return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); }
	};
}

#if defined(__MACH__)

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

// high precision timer for darwin intel and ppc

namespace libtorrent
{
	namespace aux
	{
		inline boost::int64_t absolutetime_to_microseconds(boost::int64_t at)
		{
			static mach_timebase_info_data_t timebase_info = {0,0};
			if (timebase_info.denom == 0)
				mach_timebase_info(&timebase_info);
			// make sure we don't overflow
			assert((at >= 0 && at >= at / 1000 * timebase_info.numer / timebase_info.denom)
				|| (at < 0 && at < at / 1000 * timebase_info.numer / timebase_info.denom));
			return at / 1000 * timebase_info.numer / timebase_info.denom;
		}

		inline boost::int64_t microseconds_to_absolutetime(boost::int64_t ms)
		{
			static mach_timebase_info_data_t timebase_info = {0,0};
			if (timebase_info.denom == 0)
			{
				mach_timebase_info(&timebase_info);
				assert(timebase_info.numer > 0);
				assert(timebase_info.denom > 0);
			}
			// make sure we don't overflow
			assert((ms >= 0 && ms <= ms * timebase_info.denom / timebase_info.numer * 1000)
				|| (ms < 0 && ms > ms * timebase_info.denom / timebase_info.numer * 1000));
			return ms * timebase_info.denom / timebase_info.numer * 1000;
		}
	}

	inline int total_seconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff)
			/ 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff)
			/ 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff);
	}

	inline ptime time_now() { return ptime(mach_absolute_time()); }

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s));
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000));
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000));
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60));
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60 * 60));
	}

}
#elif defined(_WIN32)

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>

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

			return pc * 1000000 / performace_counter_frequency.QuadPart;
		}

		inline boost::int64_t microseconds_to_performance_counter(boost::int64_t ms)
		{
			static LARGE_INTEGER performace_counter_frequency = {0,0};
			if (performace_counter_frequency.QuadPart == 0)
				QueryPerformanceFrequency(&performace_counter_frequency);
			return ms * performace_counter_frequency.QuadPart / 1000000;
		}
	}

	inline int total_seconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff)
			/ 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff)
			/ 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff);
	}

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

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(s));
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000));
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000));
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000 * 60));
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000 * 60 * 60));
	}

}

#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0

#include <time.h>

namespace libtorrent
{
	inline int total_seconds(time_duration td)
	{
		return td.diff / 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return td.diff / 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return td.diff;
	}

	inline ptime time_now()
	{
		timespec ts;
		clock_gettime(CLOCK_MONOTONIC, &ts);
		return ptime(boost::int64_t(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000);
	}

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(s);
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(s * 1000);
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(s * 1000000);
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(s * 1000000 * 60);
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(s * 1000000 * 60 * 60);
	}

}

#endif

#endif
#endif

<|endoftext|>


<commit_before>/*

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_UPNP_HPP
#define TORRENT_UPNP_HPP

#include "libtorrent/socket.hpp"
#include "libtorrent/http_connection.hpp"

#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <set>

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
#include <fstream>
#endif

namespace libtorrent
{

// int: external tcp port
// int: external udp port
// std::string: error message
typedef boost::function<void(int, int, std::string const&)> portmap_callback_t;

class upnp : boost::noncopyable
{
public:
	upnp(io_service& ios, address const& listen_interface
		, std::string const& user_agent, portmap_callback_t const& cb);
	~upnp();

	void rebind(address const& listen_interface);

	// maps the ports, if a port is set to 0
	// it will not be mapped
	void set_mappings(int tcp, int udp);

	void close();

private:

	static address_v4 upnp_multicast_address;
	static udp::endpoint upnp_multicast_endpoint;

	enum { num_mappings = 2 };
	enum { default_lease_time = 3600 };

	void update_mapping(int i, int port);
	void resend_request(asio::error_code const& e);
	void on_reply(asio::error_code const& e
		, std::size_t bytes_transferred);
	void discover_device();

	struct rootdevice;

	void on_upnp_xml(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d);
	void on_upnp_map_response(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d
		, int mapping);
	void on_upnp_unmap_response(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d
		, int mapping);
	void on_expire(asio::error_code const& e);

	void post(rootdevice& d, std::stringstream const& s
		, std::string const& soap_action);
	void map_port(rootdevice& d, int i);
	void unmap_port(rootdevice& d, int i);

	struct mapping_t
	{
		mapping_t()
			: need_update(false)
			, local_port(0)
			, external_port(0)
			, protocol(1)
		{}

		// the time the port mapping will expire
		ptime expires;

		bool need_update;

		// the local port for this mapping. If this is set
		// to 0, the mapping is not in use
		int local_port;

		// the external (on the NAT router) port
		// for the mapping. This is the port we
		// should announce to others
		int external_port;

		// 1 = udp, 0 = tcp
		int protocol;
	};

	struct rootdevice
	{
		rootdevice(): lease_duration(default_lease_time)
			, supports_specific_external(true)
		{
			mapping[0].protocol = 0;
			mapping[1].protocol = 1;
		}

		// the interface url, through which the list of
		// supported interfaces are fetched
		std::string url;

		// the url to the WANIP or WANPPP interface
		std::string control_url;
		// either the WANIP namespace or the WANPPP namespace
		std::string service_namespace;

		mapping_t mapping[num_mappings];

		std::string hostname;
		int port;
		std::string path;

		int lease_duration;
		// true if the device supports specifying a
		// specific external port, false if it doesn't
		bool supports_specific_external;

		boost::shared_ptr<http_connection> upnp_connection;

		void close() const { if (upnp_connection) upnp_connection->close(); }

		bool operator<(rootdevice const& rhs) const
		{ return url < rhs.url; }
	};

	int m_udp_local_port;
	int m_tcp_local_port;

	std::string const& m_user_agent;

	// the set of devices we've found
	std::set<rootdevice> m_devices;

	portmap_callback_t m_callback;

	// current retry count
	int m_retry_count;

	// used to receive responses in
	char m_receive_buffer[1024];

	// the endpoint we received the message from
	udp::endpoint m_remote;

	// the local address we're listening on
	address_v4 m_local_ip;

	// the udp socket used to send and receive
	// multicast messages on the network
	datagram_socket m_socket;

	// used to resend udp packets in case
	// they time out
	deadline_timer m_broadcast_timer;

	// timer used to refresh mappings
	deadline_timer m_refresh_timer;

	asio::strand m_strand;

	bool m_disabled;
	bool m_closing;

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	std::ofstream m_log;
#endif
};

}

#endif

<commit_msg>fixed upnp header define<commit_after>/*

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_UPNP_HPP
#define TORRENT_UPNP_HPP

#include "libtorrent/socket.hpp"
#include "libtorrent/http_connection.hpp"

#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <set>

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
#include <fstream>
#endif

namespace libtorrent
{

// int: external tcp port
// int: external udp port
// std::string: error message
typedef boost::function<void(int, int, std::string const&)> portmap_callback_t;

class upnp : boost::noncopyable
{
public:
	upnp(io_service& ios, address const& listen_interface
		, std::string const& user_agent, portmap_callback_t const& cb);
	~upnp();

	void rebind(address const& listen_interface);

	// maps the ports, if a port is set to 0
	// it will not be mapped
	void set_mappings(int tcp, int udp);

	void close();

private:

	static address_v4 upnp_multicast_address;
	static udp::endpoint upnp_multicast_endpoint;

	enum { num_mappings = 2 };
	enum { default_lease_time = 3600 };

	void update_mapping(int i, int port);
	void resend_request(asio::error_code const& e);
	void on_reply(asio::error_code const& e
		, std::size_t bytes_transferred);
	void discover_device();

	struct rootdevice;

	void on_upnp_xml(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d);
	void on_upnp_map_response(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d
		, int mapping);
	void on_upnp_unmap_response(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d
		, int mapping);
	void on_expire(asio::error_code const& e);

	void post(rootdevice& d, std::stringstream const& s
		, std::string const& soap_action);
	void map_port(rootdevice& d, int i);
	void unmap_port(rootdevice& d, int i);

	struct mapping_t
	{
		mapping_t()
			: need_update(false)
			, local_port(0)
			, external_port(0)
			, protocol(1)
		{}

		// the time the port mapping will expire
		ptime expires;

		bool need_update;

		// the local port for this mapping. If this is set
		// to 0, the mapping is not in use
		int local_port;

		// the external (on the NAT router) port
		// for the mapping. This is the port we
		// should announce to others
		int external_port;

		// 1 = udp, 0 = tcp
		int protocol;
	};

	struct rootdevice
	{
		rootdevice(): lease_duration(default_lease_time)
			, supports_specific_external(true)
		{
			mapping[0].protocol = 0;
			mapping[1].protocol = 1;
		}

		// the interface url, through which the list of
		// supported interfaces are fetched
		std::string url;

		// the url to the WANIP or WANPPP interface
		std::string control_url;
		// either the WANIP namespace or the WANPPP namespace
		std::string service_namespace;

		mapping_t mapping[num_mappings];

		std::string hostname;
		int port;
		std::string path;

		int lease_duration;
		// true if the device supports specifying a
		// specific external port, false if it doesn't
		bool supports_specific_external;

		boost::shared_ptr<http_connection> upnp_connection;

		void close() const { if (upnp_connection) upnp_connection->close(); }

		bool operator<(rootdevice const& rhs) const
		{ return url < rhs.url; }
	};

	int m_udp_local_port;
	int m_tcp_local_port;

	std::string const& m_user_agent;

	// the set of devices we've found
	std::set<rootdevice> m_devices;

	portmap_callback_t m_callback;

	// current retry count
	int m_retry_count;

	// used to receive responses in
	char m_receive_buffer[1024];

	// the endpoint we received the message from
	udp::endpoint m_remote;

	// the local address we're listening on
	address_v4 m_local_ip;

	// the udp socket used to send and receive
	// multicast messages on the network
	datagram_socket m_socket;

	// used to resend udp packets in case
	// they time out
	deadline_timer m_broadcast_timer;

	// timer used to refresh mappings
	deadline_timer m_refresh_timer;

	asio::strand m_strand;

	bool m_disabled;
	bool m_closing;

#ifdef TORRENT_UPNP_LOGGING
	std::ofstream m_log;
#endif
};

}

#endif

<|endoftext|>


<commit_before>#include "NTClient.h"
using namespace std;

NTClient::NTClient() {
	hasError = false;
	firstConnect = true;
	connected = false;
}
bool NTClient::login(string username, string password) {
	uname = username;
	pword = password;
	bool ret = true;
	string data = string("username=");
	data += uname;
	data += "&password=";
	data += pword;
	data += "&adb=1&tz=America%2FChicago"; // No need to have anything other than Chicago timezone
	httplib::SSLClient loginReq(NITROTYPE_HOSTNAME, HTTPS_PORT);
	shared_ptr<httplib::Response> res = loginReq.post(NT_LOGIN_ENDPOINT, data, "application/x-www-form-urlencoded; charset=UTF-8");
	if (res) {
		bool foundLoginCookie = false;
		for (int i = 0; i < res->cookies.size(); ++i) {
			string cookie = res->cookies.at(i);
			addCookie(Utils::extractCKey(cookie), Utils::extractCValue(cookie));
			if (cookie.find("ntuserrem=") == 0) {
				foundLoginCookie = true;
				token = Utils::extractCValue(cookie);
				cout << "Retrieved login token: " << token << endl;
				// addCookie("ntuserrem", token);
			}
		}
		if (!foundLoginCookie) {
			ret = false;
			cout << "Unable to locate the login cookie. Maybe try a different account?\n";
		}
	} else {
		ret = false;
		cout << "Login request failed. This might be a network issue. Maybe try resetting your internet connection?\n";
	}
	bool success = getPrimusSID();
	if (!success) return false;
	return ret;
}
bool NTClient::connect() {
	wsh = new Hub();
	time_t tnow = time(0);
	rawCookieStr = Utils::stringifyCookies(&cookies);
	stringstream uristream;
	uristream  << "wss://realtime1.nitrotype.com:443/realtime/?_primuscb=" << tnow << "-0&EIO=3&transport=websocket&sid=" << primusSid << "&t=" << tnow << "&b64=1";
	string wsURI = uristream.str();
	cout << "Connecting to endpoint: " << wsURI << endl;
	if (firstConnect) {
		addListeners();
	}
	// cout << "Cookies: " << rawCookieStr << endl << endl;
	// Create override headers
	SMap customHeaders;
	customHeaders["Cookie"] = rawCookieStr;
	customHeaders["Origin"] = "https://www.nitrotype.com";
	customHeaders["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/55.0.2883.87 Chrome/55.0.2883.87 Safari/537.36";
	// customHeaders["Host"] = "realtime1.nitrotype.com";
	wsh->connect(wsURI, (void*)this, customHeaders, 7000);
	// wsh->connect(wsURI);
	if (firstConnect) {
		wsh->run();
		firstConnect = false;
	}
	return true;
}
void NTClient::addCookie(string key, string val) {
	SPair sp = SPair(key, val);
	cookies.push_back(sp);
}
bool NTClient::getPrimusSID() {
	time_t tnow = time(0);
	rawCookieStr = Utils::stringifyCookies(&cookies);
	stringstream squery;
	squery << "?_primuscb=" << tnow << "-0&EIO=3&transport=polling&t=" << tnow << "-0&b64=1";
	string queryStr = squery.str();

	httplib::SSLClient loginReq(NT_REALTIME_HOST, HTTPS_PORT);
	string path = NT_PRIMUS_ENDPOINT + queryStr;
	shared_ptr<httplib::Response> res = loginReq.get(path.c_str(), rawCookieStr.c_str());
	if (res) {
		json jres = json::parse(res->body.substr(4, res->body.length()));
		primusSid = jres["sid"];
		cout << "Resolved primus SID: " << primusSid << endl;
		// addCookie("io", primusSid);
	} else {
		cout << "Error retrieving primus handshake data.\n";
		return false;
	}
	return true;
}
string NTClient::getJoinPacket(int avgSpeed) {
	stringstream ss;
	ss << "4{\"stream\":\"race\",\"msg\":\"join\",\"payload\":{\"debugging\":false,\"avgSpeed\":"
	<< avgSpeed
	<< ",\"forceEarlyPlace\":true,\"track\":\"desert\",\"music\":\"city_nights\"}}";
	return ss.str();
}
void NTClient::addListeners() {
	assert(wsh != nullptr);
	wsh->onError([this](void* udata) {
		cout << "Failed to connect to WebSocket server." << endl;
		hasError = true;
	});
	wsh->onConnection([this](WebSocket<CLIENT>* wsocket, HttpRequest req) {
		cout << "Realtime socket open" << endl;
		onConnection(wsocket, req);
	});
	wsh->onDisconnection([this](WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
		cout << "Disconnected from the realtime server." << endl;
		onDisconnection(wsocket, code, msg, len);
	});
	wsh->onMessage([this](WebSocket<CLIENT>* ws, char* msg, size_t len, OpCode opCode) {
		onMessage(ws, msg, len, opCode);
	});
}
void NTClient::onDisconnection(WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
	cout << "Disconn message: " << string(msg, len) << endl;
	cout << "Disconn code: " << code << endl;
}
void NTClient::handleData(WebSocket<CLIENT>* ws, json* j) {
	cout << "Recieved json data:" << endl << j->dump(4) << endl;
}
void NTClient::onMessage(WebSocket<CLIENT>* ws, char* msg, size_t len, OpCode opCode) {
	if (opCode != OpCode::TEXT) {
		cout << "The realtime server did not send a text packet for some reason, ignoring.\n";
		return;
	}
	string smsg = string(msg, len);
	if (smsg == "3probe") {
		// Response to initial connection probe
		ws->send("5", OpCode::TEXT);
		// Join packet
		this_thread::sleep_for(chrono::seconds(1));
		string joinTo = getJoinPacket(20); // 20 WPM just to test
		ws->send(joinTo.c_str(), OpCode::TEXT);
	} else if (smsg.length() > 2 && smsg[0] == '4' && smsg[1] == '{') {
		string rawJData = smsg.substr(1, smsg.length());
		json jdata;
		try {
			jdata = json::parse(rawJData);
		} catch (const exception& e) {
			// Some error parsing real race data, something must be wrong
			cout << "There was an issue parsing server data: " << e.what() << endl;
			return;
		}
		handleData(ws, &jdata);
	} else {
		cout << "Recieved unknown WebSocket message: '" << smsg << "'\n";
	}
}
void NTClient::onConnection(WebSocket<CLIENT>* wsocket, HttpRequest req) {
	// Send a probe, which is required for connection
	wsocket->send("2probe", OpCode::TEXT);
}<commit_msg>Detect when race joined<commit_after>#include "NTClient.h"
using namespace std;

NTClient::NTClient() {
	hasError = false;
	firstConnect = true;
	connected = false;
}
bool NTClient::login(string username, string password) {
	uname = username;
	pword = password;
	bool ret = true;
	string data = string("username=");
	data += uname;
	data += "&password=";
	data += pword;
	data += "&adb=1&tz=America%2FChicago"; // No need to have anything other than Chicago timezone
	httplib::SSLClient loginReq(NITROTYPE_HOSTNAME, HTTPS_PORT);
	shared_ptr<httplib::Response> res = loginReq.post(NT_LOGIN_ENDPOINT, data, "application/x-www-form-urlencoded; charset=UTF-8");
	if (res) {
		bool foundLoginCookie = false;
		for (int i = 0; i < res->cookies.size(); ++i) {
			string cookie = res->cookies.at(i);
			addCookie(Utils::extractCKey(cookie), Utils::extractCValue(cookie));
			if (cookie.find("ntuserrem=") == 0) {
				foundLoginCookie = true;
				token = Utils::extractCValue(cookie);
				cout << "Retrieved login token: " << token << endl;
				// addCookie("ntuserrem", token);
			}
		}
		if (!foundLoginCookie) {
			ret = false;
			cout << "Unable to locate the login cookie. Maybe try a different account?\n";
		}
	} else {
		ret = false;
		cout << "Login request failed. This might be a network issue. Maybe try resetting your internet connection?\n";
	}
	bool success = getPrimusSID();
	if (!success) return false;
	return ret;
}
bool NTClient::connect() {
	wsh = new Hub();
	time_t tnow = time(0);
	rawCookieStr = Utils::stringifyCookies(&cookies);
	stringstream uristream;
	uristream  << "wss://realtime1.nitrotype.com:443/realtime/?_primuscb=" << tnow << "-0&EIO=3&transport=websocket&sid=" << primusSid << "&t=" << tnow << "&b64=1";
	string wsURI = uristream.str();
	cout << "Connecting to endpoint: " << wsURI << endl;
	if (firstConnect) {
		addListeners();
	}
	// cout << "Cookies: " << rawCookieStr << endl << endl;
	// Create override headers
	SMap customHeaders;
	customHeaders["Cookie"] = rawCookieStr;
	customHeaders["Origin"] = "https://www.nitrotype.com";
	customHeaders["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/55.0.2883.87 Chrome/55.0.2883.87 Safari/537.36";
	// customHeaders["Host"] = "realtime1.nitrotype.com";
	wsh->connect(wsURI, (void*)this, customHeaders, 7000);
	// wsh->connect(wsURI);
	if (firstConnect) {
		wsh->run();
		firstConnect = false;
	}
	return true;
}
void NTClient::addCookie(string key, string val) {
	SPair sp = SPair(key, val);
	cookies.push_back(sp);
}
bool NTClient::getPrimusSID() {
	time_t tnow = time(0);
	rawCookieStr = Utils::stringifyCookies(&cookies);
	stringstream squery;
	squery << "?_primuscb=" << tnow << "-0&EIO=3&transport=polling&t=" << tnow << "-0&b64=1";
	string queryStr = squery.str();

	httplib::SSLClient loginReq(NT_REALTIME_HOST, HTTPS_PORT);
	string path = NT_PRIMUS_ENDPOINT + queryStr;
	shared_ptr<httplib::Response> res = loginReq.get(path.c_str(), rawCookieStr.c_str());
	if (res) {
		json jres = json::parse(res->body.substr(4, res->body.length()));
		primusSid = jres["sid"];
		cout << "Resolved primus SID: " << primusSid << endl;
		// addCookie("io", primusSid);
	} else {
		cout << "Error retrieving primus handshake data.\n";
		return false;
	}
	return true;
}
string NTClient::getJoinPacket(int avgSpeed) {
	stringstream ss;
	ss << "4{\"stream\":\"race\",\"msg\":\"join\",\"payload\":{\"debugging\":false,\"avgSpeed\":"
	<< avgSpeed
	<< ",\"forceEarlyPlace\":true,\"track\":\"desert\",\"music\":\"city_nights\"}}";
	return ss.str();
}
void NTClient::addListeners() {
	assert(wsh != nullptr);
	wsh->onError([this](void* udata) {
		cout << "Failed to connect to WebSocket server." << endl;
		hasError = true;
	});
	wsh->onConnection([this](WebSocket<CLIENT>* wsocket, HttpRequest req) {
		cout << "Realtime socket open" << endl;
		onConnection(wsocket, req);
	});
	wsh->onDisconnection([this](WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
		cout << "Disconnected from the realtime server." << endl;
		onDisconnection(wsocket, code, msg, len);
	});
	wsh->onMessage([this](WebSocket<CLIENT>* ws, char* msg, size_t len, OpCode opCode) {
		onMessage(ws, msg, len, opCode);
	});
}
void NTClient::onDisconnection(WebSocket<CLIENT>* wsocket, int code, char* msg, size_t len) {
	cout << "Disconn message: " << string(msg, len) << endl;
	cout << "Disconn code: " << code << endl;
}
void NTClient::handleData(WebSocket<CLIENT>* ws, json* j) {
	// Uncomment to dump all raw JSON packets
	// cout << "Recieved json data:" << endl << j->dump(4) << endl;
	if (j->operator[]("msg") == "setup") {
		cout << "I joined a race: " << endl << j->dump(4) << endl;
	}
}
void NTClient::onMessage(WebSocket<CLIENT>* ws, char* msg, size_t len, OpCode opCode) {
	if (opCode != OpCode::TEXT) {
		cout << "The realtime server did not send a text packet for some reason, ignoring.\n";
		return;
	}
	string smsg = string(msg, len);
	if (smsg == "3probe") {
		// Response to initial connection probe
		ws->send("5", OpCode::TEXT);
		// Join packet
		this_thread::sleep_for(chrono::seconds(1));
		string joinTo = getJoinPacket(20); // 20 WPM just to test
		ws->send(joinTo.c_str(), OpCode::TEXT);
	} else if (smsg.length() > 2 && smsg[0] == '4' && smsg[1] == '{') {
		string rawJData = smsg.substr(1, smsg.length());
		json jdata;
		try {
			jdata = json::parse(rawJData);
		} catch (const exception& e) {
			// Some error parsing real race data, something must be wrong
			cout << "There was an issue parsing server data: " << e.what() << endl;
			return;
		}
		handleData(ws, &jdata);
	} else {
		cout << "Recieved unknown WebSocket message: '" << smsg << "'\n";
	}
}
void NTClient::onConnection(WebSocket<CLIENT>* wsocket, HttpRequest req) {
	// Send a probe, which is required for connection
	wsocket->send("2probe", OpCode::TEXT);
}<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2010, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
//     Free Software Foundation, Inc.,
//     51 Franklin Street, Fifth Floor,
//     Boston, MA
//     02110-1301
//     USA
//
////////////////////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "Nibbler.h"
#include "rx.h"

const char* c_digits = "0123456789";

////////////////////////////////////////////////////////////////////////////////
Nibbler::Nibbler ()
: mInput ("")
, mLength (0)
, mCursor (0)
, mSaved (0)
{
}

////////////////////////////////////////////////////////////////////////////////
Nibbler::Nibbler (const char* input)
: mInput (input)
, mLength (strlen (input))
, mCursor (0)
{
}

////////////////////////////////////////////////////////////////////////////////
Nibbler::Nibbler (const std::string& input)
: mInput (input)
, mLength (input.length ())
, mCursor (0)
{
}

////////////////////////////////////////////////////////////////////////////////
Nibbler::Nibbler (const Nibbler& other)
{
  mInput  = other.mInput;
  mLength = other.mLength;
  mCursor = other.mCursor;
}

////////////////////////////////////////////////////////////////////////////////
Nibbler& Nibbler::operator= (const Nibbler& other)
{
  if (this != &other)
  {
    mInput  = other.mInput;
    mLength = other.mLength;
    mCursor = other.mCursor;
  }

  return *this;
}

////////////////////////////////////////////////////////////////////////////////
Nibbler::~Nibbler ()
{
}

////////////////////////////////////////////////////////////////////////////////
// Extract up until the next c (but not including) or EOS.
bool Nibbler::getUntil (char c, std::string& result)
{
  if (mCursor < mLength)
  {
    std::string::size_type i = mInput.find (c, mCursor);
    if (i != std::string::npos)
    {
      result = mInput.substr (mCursor, i - mCursor);
      mCursor = i;
    }
    else
    {
      result = mInput.substr (mCursor);
      mCursor = mLength;
    }

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntil (const std::string& terminator, std::string& result)
{
  if (mCursor < mLength)
  {
    std::string::size_type i = mInput.find (terminator, mCursor);
    if (i != std::string::npos)
    {
      result = mInput.substr (mCursor, i - mCursor);
      mCursor = i;
    }
    else
    {
      result = mInput.substr (mCursor);
      mCursor = mLength;
    }

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntilRx (const std::string& regex, std::string& result)
{
  if (mCursor < mLength)
  {
    std::string modified_regex;
    if (regex[0] != '(')
      modified_regex = "(" + regex + ")";
    else
      modified_regex = regex;

    std::vector <int> start;
    std::vector <int> end;
    if (regexMatch (start, end, mInput.substr (mCursor), modified_regex, true))
    {
      result = mInput.substr (mCursor, start[0]);
      mCursor += start[0];
    }
    else
    {
      result = mInput.substr (mCursor);
      mCursor = mLength;
    }

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntilOneOf (const std::string& chars, std::string& result)
{
  if (mCursor < mLength)
  {
    std::string::size_type i = mInput.find_first_of (chars, mCursor);
    if (i != std::string::npos)
    {
      result = mInput.substr (mCursor, i - mCursor);
      mCursor = i;
    }
    else
    {
      result = mInput.substr (mCursor);
      mCursor = mLength;
    }

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntilWS (std::string& result)
{
  return this->getUntilOneOf (" \t\r\n\f", result);
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntilEOL (std::string& result)
{
  return getUntil ('\n', result);
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntilEOS (std::string& result)
{
  if (mCursor < mLength)
  {
    result = mInput.substr (mCursor);
    mCursor = mLength;
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getQuoted (char c, std::string& result)
{
  std::string::size_type start = mCursor;
  if (start < mLength && mInput[start] == c)
  {
    ++start;
    if (start < mLength)
    {
      std::string::size_type end = mInput.find (c, start);
      if (end != std::string::npos)
      {
        result = mInput.substr (start, end - start);
        mCursor = end + 1;
        return true;
      }
    }
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getInt (int& result)
{
  std::string::size_type i = mCursor;

  if (i < mLength)
  {
    if (mInput[i] == '-')
      ++i;
    else if (mInput[i] == '+')
      ++i;
  }

  // TODO Potential for use of find_first_not_of
  while (i < mLength && isdigit (mInput[i]))
    ++i;

  if (i > mCursor)
  {
    result = atoi (mInput.substr (mCursor, i - mCursor).c_str ());
    mCursor = i;
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUnsignedInt (int& result)
{
  std::string::size_type i = mCursor;
  // TODO Potential for use of find_first_not_of
  while (i < mLength && isdigit (mInput[i]))
    ++i;

  if (i > mCursor)
  {
    result = atoi (mInput.substr (mCursor, i - mCursor).c_str ());
    mCursor = i;
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getLiteral (const std::string& literal)
{
  if (mCursor < mLength &&
      mInput.find (literal, mCursor) == mCursor)
  {
    mCursor += literal.length ();
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getRx (const std::string& regex, std::string& result)
{
  if (mCursor < mLength)
  {
    // Regex may be anchored to the beginning and include capturing parentheses,
    // otherwise they are added.
    std::string modified_regex;
    if (regex.substr (0, 2) != "^(")
      modified_regex = "^(" + regex + ")";
    else
      modified_regex = regex;

    std::vector <std::string> results;
    if (regexMatch (results, mInput.substr (mCursor), modified_regex, true))
    {
      result = results[0];
      mCursor += result.length ();
      return true;
    }
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skipN (const int quantity /* = 1 */)
{
  if (mCursor >= mLength)
    return false;

  if (mCursor <= mLength - quantity)
  {
    mCursor += quantity;
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skip (char c)
{
  if (mCursor < mLength &&
      mInput[mCursor] == c)
  {
    ++mCursor;
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skipAll (char c)
{
  if (mCursor < mLength)
  {
    std::string::size_type i = mInput.find_first_not_of (c, mCursor);
    if (i == mCursor)
      return false;

    if (i == std::string::npos)
      mCursor = mLength;  // Yes, off the end.
    else
      mCursor = i;

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skipWS ()
{
  return this->skipAllOneOf (" \t\n\r\f");
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skipRx (const std::string& regex)
{
  if (mCursor < mLength)
  {
    // Regex may be anchored to the beginning and include capturing parentheses,
    // otherwise they are added.
    std::string modified_regex;
    if (regex.substr (0, 2) != "^(")
      modified_regex = "^(" + regex + ")";
    else
      modified_regex = regex;

    std::vector <std::string> results;
    if (regexMatch (results, mInput.substr (mCursor), modified_regex, true))
    {
      mCursor += results[0].length ();
      return true;
    }
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skipAllOneOf (const std::string& chars)
{
  if (mCursor < mLength)
  {
    std::string::size_type i = mInput.find_first_not_of (chars, mCursor);
    if (i == mCursor)
      return false;

    if (i == std::string::npos)
      mCursor = mLength;  // Yes, off the end.
    else
      mCursor = i;

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
// Peeks ahead - does not move cursor.
char Nibbler::next ()
{
  if (mCursor < mLength)
    return mInput[mCursor];

  return '\0';
}

////////////////////////////////////////////////////////////////////////////////
// Peeks ahead - does not move cursor.
std::string Nibbler::next (const int quantity)
{
  if (           mCursor  <  mLength &&
      (unsigned) quantity <= mLength &&
                 mCursor  <= mLength - quantity)
    return mInput.substr (mCursor, quantity);

  return "";
}

////////////////////////////////////////////////////////////////////////////////
void Nibbler::save ()
{
  mSaved = mCursor;
}

////////////////////////////////////////////////////////////////////////////////
void Nibbler::restore ()
{
  mCursor = mSaved;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::depleted ()
{
  if (mCursor >= mLength)
    return true;

  return false;
}

////////////////////////////////////////////////////////////////////////////////
std::string Nibbler::dump ()
{
  return std::string ("Nibbler ‹")
         + mInput.substr (mCursor)
         + "›";
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>Code Cleaup<commit_after>////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2010, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
//     Free Software Foundation, Inc.,
//     51 Franklin Street, Fifth Floor,
//     Boston, MA
//     02110-1301
//     USA
//
////////////////////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "Nibbler.h"
#include "rx.h"

const char* c_digits = "0123456789";

////////////////////////////////////////////////////////////////////////////////
Nibbler::Nibbler ()
: mInput ("")
, mLength (0)
, mCursor (0)
, mSaved (0)
{
}

////////////////////////////////////////////////////////////////////////////////
Nibbler::Nibbler (const char* input)
: mInput (input)
, mLength (strlen (input))
, mCursor (0)
{
}

////////////////////////////////////////////////////////////////////////////////
Nibbler::Nibbler (const std::string& input)
: mInput (input)
, mLength (input.length ())
, mCursor (0)
{
}

////////////////////////////////////////////////////////////////////////////////
Nibbler::Nibbler (const Nibbler& other)
{
  mInput  = other.mInput;
  mLength = other.mLength;
  mCursor = other.mCursor;
}

////////////////////////////////////////////////////////////////////////////////
Nibbler& Nibbler::operator= (const Nibbler& other)
{
  if (this != &other)
  {
    mInput  = other.mInput;
    mLength = other.mLength;
    mCursor = other.mCursor;
  }

  return *this;
}

////////////////////////////////////////////////////////////////////////////////
Nibbler::~Nibbler ()
{
}

////////////////////////////////////////////////////////////////////////////////
// Extract up until the next c (but not including) or EOS.
bool Nibbler::getUntil (char c, std::string& result)
{
  if (mCursor < mLength)
  {
    std::string::size_type i = mInput.find (c, mCursor);
    if (i != std::string::npos)
    {
      result = mInput.substr (mCursor, i - mCursor);
      mCursor = i;
    }
    else
    {
      result = mInput.substr (mCursor);
      mCursor = mLength;
    }

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntil (const std::string& terminator, std::string& result)
{
  if (mCursor < mLength)
  {
    std::string::size_type i = mInput.find (terminator, mCursor);
    if (i != std::string::npos)
    {
      result = mInput.substr (mCursor, i - mCursor);
      mCursor = i;
    }
    else
    {
      result = mInput.substr (mCursor);
      mCursor = mLength;
    }

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntilRx (const std::string& regex, std::string& result)
{
  if (mCursor < mLength)
  {
    std::string modified_regex;
    if (regex[0] != '(')
      modified_regex = "(" + regex + ")";
    else
      modified_regex = regex;

    std::vector <int> start;
    std::vector <int> end;
    if (regexMatch (start, end, mInput.substr (mCursor), modified_regex, true))
    {
      result = mInput.substr (mCursor, start[0]);
      mCursor += start[0];
    }
    else
    {
      result = mInput.substr (mCursor);
      mCursor = mLength;
    }

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntilOneOf (const std::string& chars, std::string& result)
{
  if (mCursor < mLength)
  {
    std::string::size_type i = mInput.find_first_of (chars, mCursor);
    if (i != std::string::npos)
    {
      result = mInput.substr (mCursor, i - mCursor);
      mCursor = i;
    }
    else
    {
      result = mInput.substr (mCursor);
      mCursor = mLength;
    }

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntilWS (std::string& result)
{
  return this->getUntilOneOf (" \t\r\n\f", result);
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntilEOL (std::string& result)
{
  return getUntil ('\n', result);
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUntilEOS (std::string& result)
{
  if (mCursor < mLength)
  {
    result = mInput.substr (mCursor);
    mCursor = mLength;
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getQuoted (char c, std::string& result)
{
  std::string::size_type backup = mCursor;

  if (skip (c) &&
      getUntil (c, result) &&
      skip (c))
  {
    return true;
  }

  mCursor = backup;
  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getInt (int& result)
{
  std::string::size_type i = mCursor;

  if (i < mLength)
  {
    if (mInput[i] == '-')
      ++i;
    else if (mInput[i] == '+')
      ++i;
  }

  // TODO Potential for use of find_first_not_of
  while (i < mLength && isdigit (mInput[i]))
    ++i;

  if (i > mCursor)
  {
    result = atoi (mInput.substr (mCursor, i - mCursor).c_str ());
    mCursor = i;
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getUnsignedInt (int& result)
{
  std::string::size_type i = mCursor;
  // TODO Potential for use of find_first_not_of
  while (i < mLength && isdigit (mInput[i]))
    ++i;

  if (i > mCursor)
  {
    result = atoi (mInput.substr (mCursor, i - mCursor).c_str ());
    mCursor = i;
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getLiteral (const std::string& literal)
{
  if (mCursor < mLength &&
      mInput.find (literal, mCursor) == mCursor)
  {
    mCursor += literal.length ();
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::getRx (const std::string& regex, std::string& result)
{
  if (mCursor < mLength)
  {
    // Regex may be anchored to the beginning and include capturing parentheses,
    // otherwise they are added.
    std::string modified_regex;
    if (regex.substr (0, 2) != "^(")
      modified_regex = "^(" + regex + ")";
    else
      modified_regex = regex;

    std::vector <std::string> results;
    if (regexMatch (results, mInput.substr (mCursor), modified_regex, true))
    {
      result = results[0];
      mCursor += result.length ();
      return true;
    }
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skipN (const int quantity /* = 1 */)
{
  if (mCursor < mLength &&
      mCursor <= mLength - quantity)
  {
    mCursor += quantity;
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skip (char c)
{
  if (mCursor < mLength &&
      mInput[mCursor] == c)
  {
    ++mCursor;
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skipAll (char c)
{
  if (mCursor < mLength)
  {
    std::string::size_type i = mInput.find_first_not_of (c, mCursor);
    if (i == mCursor)
      return false;

    if (i == std::string::npos)
      mCursor = mLength;  // Yes, off the end.
    else
      mCursor = i;

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skipWS ()
{
  return this->skipAllOneOf (" \t\n\r\f");
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skipRx (const std::string& regex)
{
  if (mCursor < mLength)
  {
    // Regex may be anchored to the beginning and include capturing parentheses,
    // otherwise they are added.
    std::string modified_regex;
    if (regex.substr (0, 2) != "^(")
      modified_regex = "^(" + regex + ")";
    else
      modified_regex = regex;

    std::vector <std::string> results;
    if (regexMatch (results, mInput.substr (mCursor), modified_regex, true))
    {
      mCursor += results[0].length ();
      return true;
    }
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::skipAllOneOf (const std::string& chars)
{
  if (mCursor < mLength)
  {
    std::string::size_type i = mInput.find_first_not_of (chars, mCursor);
    if (i == mCursor)
      return false;

    if (i == std::string::npos)
      mCursor = mLength;  // Yes, off the end.
    else
      mCursor = i;

    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
// Peeks ahead - does not move cursor.
char Nibbler::next ()
{
  if (mCursor < mLength)
    return mInput[mCursor];

  return '\0';
}

////////////////////////////////////////////////////////////////////////////////
// Peeks ahead - does not move cursor.
std::string Nibbler::next (const int quantity)
{
  if (           mCursor  <  mLength &&
      (unsigned) quantity <= mLength &&
                 mCursor  <= mLength - quantity)
    return mInput.substr (mCursor, quantity);

  return "";
}

////////////////////////////////////////////////////////////////////////////////
void Nibbler::save ()
{
  mSaved = mCursor;
}

////////////////////////////////////////////////////////////////////////////////
void Nibbler::restore ()
{
  mCursor = mSaved;
}

////////////////////////////////////////////////////////////////////////////////
bool Nibbler::depleted ()
{
  if (mCursor >= mLength)
    return true;

  return false;
}

////////////////////////////////////////////////////////////////////////////////
std::string Nibbler::dump ()
{
  return std::string ("Nibbler ‹")
         + mInput.substr (mCursor)
         + "›";
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>/********************************************************************************
  libvideogfx/graphics/datatypes/primitives.hh

  purpose:
    Very basic data types.

  notes:

  to do:

  author(s):
   - Dirk Farin, dirk.farin@gmx.de

  modifications:
    17/Nov/1999 - Dirk Farin - first revision
 ********************************************************************************
    LibVideoGfx - video processing library
    Copyright (C) 2002  Dirk Farin

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef LIBVIDEOGFX_GRAPHICS_DATATYPES_PRIMITIVES_HH
#define LIBVIDEOGFX_GRAPHICS_DATATYPES_PRIMITIVES_HH

#include <math.h>
#include <algorithm>

namespace videogfx {

  template <class T> struct Point2D
  {
    Point2D() { }
    Point2D(const T& _x,const T& _y) { x = _x; y = _y; }

    Point2D<T> operator*(double scale) const { return Point2D<T>(x*scale,y*scale); }

    bool operator==(const Point2D<T>& p) const { return p.x==x && p.y==y; }
    bool operator!=(const Point2D<T>& p) const { return p.x!=x || p.y!=y; }

    void shiftByOffset(T ox,T oy) { x+=ox; y+=oy; }

    T x,y;
  };

  template <class T> T SquaredDistance(const Point2D<T>& p1,const Point2D<T>& p2)
  {
    return hypot(p1.x-p2.x, p1.y-p2.y);
  }

  template <class T> struct Vector2D
  {
    Vector2D() { }
    Vector2D(const T& _x,const T& _y) { x = _x; y = _y; }

    T x,y;

    T Length() const { return (T)hypot((double)x,(double)y); }
  };

  template <class T> struct Rect2D
  {
    Point2D<T> upperleft;
    Point2D<T> lowerright;

    int& left()   { return upperleft.x; }
    int& top()    { return upperleft.y; }
    int& right()  { return lowerright.x; }
    int& bottom() { return lowerright.y; }

    int left()   const { return upperleft.x; }
    int top()    const { return upperleft.y; }
    int right()  const { return lowerright.x; }
    int bottom() const { return lowerright.y; }

    int width()  const { return right()-left()+1; }
    int height() const { return bottom()-top()+1; }

    void initEmpty(T w,T h)
    {
      left()  = w;
      right() = 0;
      top()   = h;
      bottom()= 0;
    }

    void extendToIncludePoint(T x,T y)
    {
      left() = std::min(left(),x);
      right()= std::max(right(),x);
      top()  = std::min(top() ,y);
      bottom()=std::max(bottom(),y);
    }

    void extendToIncludeRect(const Rect2D<T>& r)
    {
      left()  = std::min(left()  ,r.left());
      right() = std::max(right() ,r.right());
      top()   = std::min(top()   ,r.top());
      bottom()= std::max(bottom(),r.bottom());
    }

    void shiftByOffset(int x,int y)
    {
      left() += x;
      right() += x;
      top() += y;
      bottom() += y;
    }
  };

  template <class T> struct Color
  {
    Color() { }
    Color(T v1,T v2,T v3,T alpha) { c[0]=v1; c[1]=v2; c[2]=v3; c[3]=alpha; }
    Color(T v1,T v2,T v3)         { c[0]=v1; c[1]=v2; c[2]=v3; }
    Color(int v1,int v2,int v3,int alpha) { c[0]=(T)v1; c[1]=(T)v2; c[2]=(T)v3; c[3]=(T)alpha; }
    Color(int v1,int v2,int v3)           { c[0]=(T)v1; c[1]=(T)v2; c[2]=(T)v3; }

    T c[4];  // 0,1,2 - color | 3 - alpha
  };

}

#endif
<commit_msg>added empty region check<commit_after>/********************************************************************************
  libvideogfx/graphics/datatypes/primitives.hh

  purpose:
    Very basic data types.

  notes:

  to do:

  author(s):
   - Dirk Farin, dirk.farin@gmx.de

  modifications:
    17/Nov/1999 - Dirk Farin - first revision
 ********************************************************************************
    LibVideoGfx - video processing library
    Copyright (C) 2002  Dirk Farin

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef LIBVIDEOGFX_GRAPHICS_DATATYPES_PRIMITIVES_HH
#define LIBVIDEOGFX_GRAPHICS_DATATYPES_PRIMITIVES_HH

#include <math.h>
#include <algorithm>

namespace videogfx {

  template <class T> struct Point2D
  {
    Point2D() { }
    Point2D(const T& _x,const T& _y) { x = _x; y = _y; }

    Point2D<T> operator*(double scale) const { return Point2D<T>(x*scale,y*scale); }

    bool operator==(const Point2D<T>& p) const { return p.x==x && p.y==y; }
    bool operator!=(const Point2D<T>& p) const { return p.x!=x || p.y!=y; }

    void shiftByOffset(T ox,T oy) { x+=ox; y+=oy; }

    T x,y;
  };

  template <class T> T SquaredDistance(const Point2D<T>& p1,const Point2D<T>& p2)
  {
    return hypot(p1.x-p2.x, p1.y-p2.y);
  }

  template <class T> struct Vector2D
  {
    Vector2D() { }
    Vector2D(const T& _x,const T& _y) { x = _x; y = _y; }

    T x,y;

    T Length() const { return (T)hypot((double)x,(double)y); }
  };

  template <class T> struct Rect2D
  {
    Point2D<T> upperleft;
    Point2D<T> lowerright;

    int& left()   { return upperleft.x; }
    int& top()    { return upperleft.y; }
    int& right()  { return lowerright.x; }
    int& bottom() { return lowerright.y; }

    int left()   const { return upperleft.x; }
    int top()    const { return upperleft.y; }
    int right()  const { return lowerright.x; }
    int bottom() const { return lowerright.y; }

    int width()  const { return right()-left()+1; }
    int height() const { return bottom()-top()+1; }

    void initEmpty(T w,T h)
    {
      left()  = w;
      right() = 0;
      top()   = h;
      bottom()= 0;
    }

    bool isEmpty() const
    {
      return left()>right() || top()>bottom();
    }

    void extendToIncludePoint(T x,T y)
    {
      left() = std::min(left(),x);
      right()= std::max(right(),x);
      top()  = std::min(top() ,y);
      bottom()=std::max(bottom(),y);
    }

    void extendToIncludeRect(const Rect2D<T>& r)
    {
      left()  = std::min(left()  ,r.left());
      right() = std::max(right() ,r.right());
      top()   = std::min(top()   ,r.top());
      bottom()= std::max(bottom(),r.bottom());
    }

    void shiftByOffset(int x,int y)
    {
      left() += x;
      right() += x;
      top() += y;
      bottom() += y;
    }
  };

  template <class T> struct Color
  {
    Color() { }
    Color(T v1,T v2,T v3,T alpha) { c[0]=v1; c[1]=v2; c[2]=v3; c[3]=alpha; }
    Color(T v1,T v2,T v3)         { c[0]=v1; c[1]=v2; c[2]=v3; }
    Color(int v1,int v2,int v3,int alpha) { c[0]=(T)v1; c[1]=(T)v2; c[2]=(T)v3; c[3]=(T)alpha; }
    Color(int v1,int v2,int v3)           { c[0]=(T)v1; c[1]=(T)v2; c[2]=(T)v3; }

    T c[4];  // 0,1,2 - color | 3 - alpha
  };

}

#endif
<|endoftext|>