<commit_before>#ifndef GNR_DISPATCH_HPP
# define GNR_DISPATCH_HPP
# pragma once

#include <type_traits>

#include <utility>

#include "invoke.hpp"

namespace gnr
{

namespace detail
{

template <std::size_t I, typename ...T>
using at_t = std::tuple_element_t<I, std::tuple<T...>>;

template <typename R>
using result_t = std::conditional_t<
  std::is_array_v<std::remove_reference_t<R>> &&
  (1 == std::rank_v<std::remove_reference_t<R>>) &&
  std::is_same_v<
    char,
    std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
  >,
  std::remove_extent_t<std::remove_reference_t<R>>(*)[],
  std::conditional_t<
    std::is_reference_v<R>,
    std::remove_reference_t<R>*,
    R
  >
>;

template <typename F>
constexpr auto is_noexcept_dispatchable() noexcept
{
  auto const f(static_cast<std::remove_reference_t<F>*>(nullptr));

  if constexpr(std::is_void_v<decltype((*f)())> ||
    std::is_reference_v<decltype((*f)())>)
  {
    return noexcept((*f)());
  }
  else
  {
    return noexcept(std::declval<decltype((*f)())&>() = (*f)());
  }
}

}

constexpr decltype(auto) dispatch(auto const i, auto&& ...f)
  noexcept(
    (
      detail::is_noexcept_dispatchable<decltype(f)>() && ...
    )
  )
  requires(
    std::is_enum_v<std::remove_const_t<decltype(i)>> &&
    std::conjunction_v<
      std::is_same<
        std::decay_t<
          decltype(std::declval<detail::at_t<0, decltype(f)...>>()())
        >,
        std::decay_t<decltype(std::declval<decltype(f)>()())>
      >...
    >
  )
{
  using int_t = std::underlying_type_t<std::remove_const_t<decltype(i)>>;
  using R = decltype(std::declval<detail::at_t<0, decltype(f)...>>()());

  return [&]<auto ...I>(std::integer_sequence<int_t, I...>)
    noexcept(noexcept((f(), ...))) -> decltype(auto)
  {
    if constexpr(std::is_void_v<R>)
    {
      ((I == int_t(i) ? (f(), 0) : 0), ...);
    }
    else if constexpr(
      (
        std::is_array_v<std::remove_reference_t<R>> &&
        (1 == std::rank_v<std::remove_reference_t<R>>) &&
        std::is_same_v<
          char,
          std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
        >
      ) ||
      std::is_reference_v<R>
    )
    {
      detail::result_t<R> r;

      (
        (
          I == int_t(i) ?
            r = reinterpret_cast<decltype(r)>(&f()) :
            nullptr
        ),
        ...
      );

      return *r;
    }
    else
    {
      R r;

      ((I == int_t(i) ? (r = f(), 0) : 0), ...);

      return r;
    }
  }(std::make_integer_sequence<int_t, sizeof...(f)>());
}

constexpr decltype(auto) dispatch2(auto const i, auto&& ...a)
#ifndef __clang__
  noexcept(noexcept(
      gnr::invoke_split<2>(
        [](auto&&, auto&& f)
        {
          detail::is_noexcept_dispatchable<decltype(f)>();
        },
        std::forward<decltype(a)>(a)...
      )
    )
  )
#endif // __clang__
{
  using R = decltype(std::declval<detail::at_t<1, decltype(a)...>>()());

  if constexpr(std::is_void_v<R>)
  {
    gnr::invoke_split<2>(
      [&](auto&& e, auto&& f) noexcept(noexcept(f()))
      {
        if (e == i)
        {
          f();
        }
      },
      std::forward<decltype(a)>(a)...
    );
  }
  else if constexpr(
    (
      std::is_array_v<std::remove_reference_t<R>> &&
      (1 == std::rank_v<std::remove_reference_t<R>>) &&
      std::is_same_v<
        char,
        std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
      >
    ) ||
    std::is_reference_v<R>
  )
  {
    detail::result_t<R> r;

    gnr::invoke_split<2>(
      [&](auto&& e, auto&& f) noexcept(noexcept(f()))
      {
        if (e == i)
        {
          r = reinterpret_cast<decltype(r)>(&f());
        }
      },
      std::forward<decltype(a)>(a)...
    );

    return *r;
  }
  else
  {
    R r;

    gnr::invoke_split<2>(
      [&](auto&& e, auto&& f)
        noexcept(noexcept(std::declval<R&>() = f()))
      {
        if (e == i)
        {
          r = f();
        }
      },
      std::forward<decltype(a)>(a)...
    );

    return r;
  }
}

constexpr decltype(auto) select(auto const i, auto&& ...v) noexcept
  requires(
    std::conjunction_v<
      std::is_same<
        std::decay_t<
          decltype(std::declval<detail::at_t<0, decltype(v)...>>())
        >,
        std::decay_t<decltype(std::declval<decltype(v)>())>
      >...
    >
  )
{
  return [&]<auto ...I>(std::index_sequence<I...>) noexcept -> decltype(auto)
  {
    detail::result_t<detail::at_t<0, decltype(v)...>> r;

    ((I == i ? r = reinterpret_cast<decltype(r)>(&v) : nullptr), ...);

    return *r;
  }(std::make_index_sequence<sizeof...(v)>());
}

constexpr decltype(auto) select2(auto const i, auto&& ...a) noexcept
{
  using R = decltype(std::declval<detail::at_t<1, decltype(a)...>>());
  detail::result_t<R> r;

  gnr::invoke_split<2>(
    [&](auto&& e, auto&& v) noexcept
    {
      if (e == i)
      {
        r = reinterpret_cast<decltype(r)>(&v);
      }
    },
    std::forward<decltype(a)>(a)...
  );

  return *r;
}

}

#endif // GNR_DISPATCH_HPP
<commit_msg>some fixes<commit_after>#ifndef GNR_DISPATCH_HPP
# define GNR_DISPATCH_HPP
# pragma once

#include <type_traits>

#include <utility>

#include "invoke.hpp"

namespace gnr
{

namespace detail
{

template <std::size_t I, typename ...T>
using at_t = std::tuple_element_t<I, std::tuple<T...>>;

template <typename R>
using result_t = std::conditional_t<
  std::is_array_v<std::remove_reference_t<R>> &&
  (1 == std::rank_v<std::remove_reference_t<R>>) &&
  std::is_same_v<
    char,
    std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
  >,
  std::remove_extent_t<std::remove_reference_t<R>>(*)[],
  std::conditional_t<
    std::is_reference_v<R>,
    std::remove_reference_t<R>*,
    R
  >
>;

template <typename F>
constexpr auto is_noexcept_dispatchable() noexcept
{
  auto const f(static_cast<std::remove_reference_t<F>*>(nullptr));

  if constexpr(std::is_void_v<decltype((*f)())> ||
    std::is_reference_v<decltype((*f)())>)
  {
    return noexcept((*f)());
  }
  else
  {
    return noexcept(std::declval<decltype((*f)())&>() = (*f)());
  }
}

}

constexpr decltype(auto) dispatch(auto const i, auto&& ...f)
  noexcept(
    (detail::is_noexcept_dispatchable<decltype(f)>() && ...)
  )
  requires(
    std::is_enum_v<std::remove_const_t<decltype(i)>> &&
    std::conjunction_v<
      std::is_same<
        std::decay_t<
          decltype(std::declval<detail::at_t<0, decltype(f)...>>()())
        >,
        std::decay_t<decltype(std::declval<decltype(f)>()())>
      >...
    >
  )
{
  using int_t = std::underlying_type_t<std::remove_const_t<decltype(i)>>;
  using R = decltype(std::declval<detail::at_t<0, decltype(f)...>>()());

  return [&]<auto ...I>(std::integer_sequence<int_t, I...>)
    noexcept((detail::is_noexcept_dispatchable<decltype(f)>() && ...)) ->
    decltype(auto)
  {
    if constexpr(std::is_void_v<R>)
    {
      ((I == int_t(i) ? (f(), 0) : 0), ...);
    }
    else if constexpr(
      (
        std::is_array_v<std::remove_reference_t<R>> &&
        (1 == std::rank_v<std::remove_reference_t<R>>) &&
        std::is_same_v<
          char,
          std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
        >
      ) ||
      std::is_reference_v<R>
    )
    {
      detail::result_t<R> r;

      (
        (
          I == int_t(i) ?
            r = reinterpret_cast<decltype(r)>(&f()) :
            nullptr
        ),
        ...
      );

      return *r;
    }
    else
    {
      R r;

      ((I == int_t(i) ? (r = f(), 0) : 0), ...);

      return r;
    }
  }(std::make_integer_sequence<int_t, sizeof...(f)>());
}

constexpr decltype(auto) dispatch2(auto const i, auto&& ...a)
#ifndef __clang__
  noexcept(noexcept(
      gnr::invoke_split<2>(
        [](auto&&, auto&& f)
        {
          detail::is_noexcept_dispatchable<decltype(f)>();
        },
        std::forward<decltype(a)>(a)...
      )
    )
  )
#endif // __clang__
{
  using R = decltype(std::declval<detail::at_t<1, decltype(a)...>>()());

  if constexpr(std::is_void_v<R>)
  {
    gnr::invoke_split<2>(
      [&](auto&& e, auto&& f) noexcept(noexcept(f()))
      {
        if (e == i)
        {
          f();
        }
      },
      std::forward<decltype(a)>(a)...
    );
  }
  else if constexpr(
    (
      std::is_array_v<std::remove_reference_t<R>> &&
      (1 == std::rank_v<std::remove_reference_t<R>>) &&
      std::is_same_v<
        char,
        std::remove_const_t<std::remove_extent_t<std::remove_reference_t<R>>>
      >
    ) ||
    std::is_reference_v<R>
  )
  {
    detail::result_t<R> r;

    gnr::invoke_split<2>(
      [&](auto&& e, auto&& f) noexcept(noexcept(f()))
      {
        if (e == i)
        {
          r = reinterpret_cast<decltype(r)>(&f());
        }
      },
      std::forward<decltype(a)>(a)...
    );

    return *r;
  }
  else
  {
    R r;

    gnr::invoke_split<2>(
      [&](auto&& e, auto&& f)
        noexcept(noexcept(std::declval<R&>() = f()))
      {
        if (e == i)
        {
          r = f();
        }
      },
      std::forward<decltype(a)>(a)...
    );

    return r;
  }
}

constexpr decltype(auto) select(auto const i, auto&& ...v) noexcept
  requires(
    std::conjunction_v<
      std::is_same<
        std::decay_t<
          decltype(std::declval<detail::at_t<0, decltype(v)...>>())
        >,
        std::decay_t<decltype(std::declval<decltype(v)>())>
      >...
    >
  )
{
  return [&]<auto ...I>(std::index_sequence<I...>) noexcept -> decltype(auto)
  {
    detail::result_t<detail::at_t<0, decltype(v)...>> r;

    ((I == i ? r = reinterpret_cast<decltype(r)>(&v) : nullptr), ...);

    return *r;
  }(std::make_index_sequence<sizeof...(v)>());
}

constexpr decltype(auto) select2(auto const i, auto&& ...a) noexcept
{
  using R = decltype(std::declval<detail::at_t<1, decltype(a)...>>());
  detail::result_t<R> r;

  gnr::invoke_split<2>(
    [&](auto&& e, auto&& v) noexcept
    {
      if (e == i)
      {
        r = reinterpret_cast<decltype(r)>(&v);
      }
    },
    std::forward<decltype(a)>(a)...
  );

  return *r;
}

}

#endif // GNR_DISPATCH_HPP
<|endoftext|>


<commit_before>#include "TcpConnecterProcess.h"

#include "ThreadSafeMessaging.h"
#include "ProcessMessageConnectToServer.h"
#include "ProcessMessageTerminate.h"
#include <DebugUtil.h>

#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/thread/thread.hpp>

using namespace boost::asio::ip;

TcpConnecterProcess::TcpConnecterProcess( ThreadSafeMessaging* p_parent,
		boost::asio::io_service* p_ioService, string p_address, string p_port )
{
	m_parent = p_parent;
	m_ioService = p_ioService;

	m_address = p_address;
	m_port = p_port;

	m_running = false;
}

TcpConnecterProcess::~TcpConnecterProcess()
{
}

void TcpConnecterProcess::body()
{
	m_running = true;

	// resolver:
	tcp::resolver tcpResolver( *m_ioService );
	tcp::resolver::query tcpQuery( m_address, m_port );

	tcp::resolver::iterator endpointIterator;
	tcp::resolver::iterator end;

	endpointIterator = tcpResolver.resolve( tcpQuery );
	end = tcp::resolver::iterator();

	// socket:
	tcp::socket* activeSocket = new tcp::socket( *m_ioService );

	boost::system::error_code error;

	// The client will try to connect until a response from the server has been done, with a timeout.
	while (m_running)
	{

		DEBUGPRINT(("Attempting to connect to server...\n"));
		error = boost::asio::error::host_not_found;
		endpointIterator = tcpResolver.resolve( tcpQuery );

		// Iterate and attempt to connect to resolved endpoints.
		while( error && endpointIterator != end )
		{
			activeSocket->close();
			activeSocket->connect( *endpointIterator, error );

			*endpointIterator++;
		}

		// When the resolver is finished, let's see if we found a connection.
		if( error )
		{
			//cout << error.message() << endl;
			DEBUGPRINT(((error.message()+"\n").c_str()));
		}
		else
		{
			DEBUGPRINT(("Connection established!\n"));
			m_parent->putMessage( new ProcessMessageConnectToServer( this, activeSocket ) );
			m_running = false;
		}

		processMessages();
	}

	if (error)
	{
		delete activeSocket;
		activeSocket = NULL;
	}
}

void TcpConnecterProcess::processMessages()
{
	queue< ProcessMessage* > messages;
	messages = checkoutMessageQueue();

	while( messages.size() > 0 )
	{
		ProcessMessage* msg = messages.front();
		messages.pop();

		boost::this_thread::sleep(boost::posix_time::milliseconds(1));

		if( msg->type = MessageType::TERMINATE )
			m_running = false;

		delete msg;
	}
}
<commit_msg>TcpConnecterProcess fail fix.<commit_after>#include "TcpConnecterProcess.h"

#include "ThreadSafeMessaging.h"
#include "ProcessMessageConnectToServer.h"
#include "ProcessMessageTerminate.h"
#include <DebugUtil.h>

#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/thread/thread.hpp>

using namespace boost::asio::ip;

TcpConnecterProcess::TcpConnecterProcess( ThreadSafeMessaging* p_parent,
		boost::asio::io_service* p_ioService, string p_address, string p_port )
{
	m_parent = p_parent;
	m_ioService = p_ioService;

	m_address = p_address;
	m_port = p_port;

	m_running = false;
}

TcpConnecterProcess::~TcpConnecterProcess()
{
}

void TcpConnecterProcess::body()
{
	m_running = true;

	// resolver:
	tcp::resolver tcpResolver( *m_ioService );
	tcp::resolver::query tcpQuery( m_address, m_port );

	tcp::resolver::iterator endpointIterator;
	tcp::resolver::iterator end;

	endpointIterator = tcpResolver.resolve( tcpQuery );
	end = tcp::resolver::iterator();

	// socket:
	tcp::socket* activeSocket = new tcp::socket( *m_ioService );

	boost::system::error_code error;

	// The client will try to connect until a response from the server has been done, with a timeout.
	while (m_running)
	{

		DEBUGPRINT(("Attempting to connect to server...\n"));
		error = boost::asio::error::host_not_found;
		endpointIterator = tcpResolver.resolve( tcpQuery );

		// Iterate and attempt to connect to resolved endpoints.
		while( error && endpointIterator != end )
		{
			activeSocket->close();
			activeSocket->connect( *endpointIterator, error );

			*endpointIterator++;
		}

		// When the resolver is finished, let's see if we found a connection.
		if( error )
		{
			//cout << error.message() << endl;
			DEBUGPRINT(((error.message()+"\n").c_str()));
		}
		else
		{
			DEBUGPRINT(("Connection established!\n"));
			m_parent->putMessage( new ProcessMessageConnectToServer( this, activeSocket ) );
			m_running = false;
		}

		processMessages();
	}

	if (error)
	{
		delete activeSocket;
		activeSocket = NULL;
	}
}

void TcpConnecterProcess::processMessages()
{
	queue< ProcessMessage* > messages;
	messages = checkoutMessageQueue();

	while( messages.size() > 0 )
	{
		ProcessMessage* msg = messages.front();
		messages.pop();

		boost::this_thread::sleep(boost::posix_time::milliseconds(1));

		if( msg->type == MessageType::TERMINATE )
			m_running = false;

		delete msg;
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include <cstdlib>
#include <iterator>
#include <map>
#include <sstream>
#include <tuple>
#include "LoaderOBJ.hpp"
#include "Cache.hpp"
#include "core/Engine.hpp"
#include "graphics/Material.hpp"
#include "utils/Log.hpp"

namespace ouzel
{
    namespace assets
    {
        LoaderOBJ::LoaderOBJ():
            Loader({"obj"})
        {
        }

        bool LoaderOBJ::loadAsset(const std::string& filename, const std::vector<uint8_t>& data)
        {
            std::stringstream stream;
            std::copy(data.begin(), data.end(), std::ostream_iterator<uint8_t>(stream));

            std::string name = filename;
            std::shared_ptr<graphics::Material> material;
            std::vector<Vector3> positions;
            std::vector<Vector2> texCoords;
            std::vector<Vector3> normals;
            std::vector<graphics::Vertex> vertices;
            std::map<std::tuple<uint32_t, uint32_t, uint32_t>, uint32_t> vertexMap;
            std::vector<uint32_t> indices;
            Box3 boundingBox;

            uint32_t objectCount = 0;
            std::string read;

            for (std::string line; std::getline(stream, line);)
            {
                if (!line.empty())
                {
                    std::stringstream lineStream;
                    lineStream << line;

                    read.clear();
                    lineStream >> read;

                    if (read.empty() || read[0] == '#') // empty or comment
                    {
                        continue;
                    }
                    else if (read == "mtllib")
                    {
                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse material library file name";
                            return false;
                        }

                        read.clear();
                        lineStream >> read;
                        cache->loadAsset(read);
                    }
                    else if (read == "usemtl")
                    {
                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse material name";
                            return false;
                        }

                        read.clear();
                        lineStream >> read;
                        material = cache->getMaterial(read);
                    }
                    else if (read == "o") // object name
                    {
                        if (objectCount)
                        {
                            scene::ModelData modelData;
                            modelData.init(boundingBox, indices, vertices, material);
                            engine->getCache()->setModelData(name, modelData);
                        }

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse object name";
                            return false;
                        }

                        read.clear();
                        lineStream >> read;

                        name = read;
                        material.reset();
                        positions.clear();
                        texCoords.clear();
                        normals.clear();
                        vertices.clear();
                        indices.clear();
                        boundingBox.reset();
                        ++objectCount;
                    }
                    else if (read == "v") // vertex
                    {
                        Vector3 position;
                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse position";
                            return false;
                        }

                        lineStream >> position.x;

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse position";
                            return false;
                        }

                        lineStream >> position.y;

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse position";
                            return false;
                        }

                        lineStream >> position.z;

                        positions.push_back(position);
                    }
                    else if (read == "vt") // texture coordinates
                    {
                        Vector3 texCoord;
                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse texture coordinates";
                            return false;
                        }

                        lineStream >> texCoord.x;

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse texture coordinates";
                            return false;
                        }

                        lineStream >> texCoord.y;

                        texCoords.push_back(texCoord);
                    }
                    else if (read == "vn") // normal
                    {
                        Vector3 normal;
                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse normal";
                            return false;
                        }

                        lineStream >> normal.x;

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse normal";
                            return false;
                        }

                        lineStream >> normal.y;

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse normal";
                            return false;
                        }

                        lineStream >> normal.z;

                        normals.push_back(normal);
                    }
                    else if (read == "f") // face
                    {
                        std::vector<uint32_t> vertexIndices;

                        while (!lineStream.eof())
                        {
                            read.clear();
                            lineStream >> read;

                            std::stringstream vertexStream;
                            vertexStream << read;

                            std::tuple<uint32_t, uint32_t, uint32_t> i = std::make_tuple(0, 0, 0);

                            if (!std::getline(vertexStream, read, '/'))
                            {
                                Log(Log::Level::ERR) << "Failed to parse face";
                                return false;
                            }

                            long index = std::strtol(read.c_str(), nullptr, 0);

                            if (index < 0)
                                std::get<0>(i) = static_cast<uint32_t>(static_cast<long>(positions.size()) + index);
                            else if (index > 0)
                                std::get<0>(i) = static_cast<uint32_t>(index - 1);
                            else
                            {
                                Log(Log::Level::ERR) << "Failed to parse face";
                                return false;
                            }

                            if (std::getline(vertexStream, read, '/'))
                            {
                                index = std::strtol(read.c_str(), nullptr, 0);

                                if (index < 0)
                                    std::get<1>(i) = static_cast<uint32_t>(static_cast<long>(texCoords.size()) + index);
                                else if (index > 0)
                                    std::get<1>(i) = static_cast<uint32_t>(index - 1);
                                else
                                {
                                    Log(Log::Level::ERR) << "Failed to parse face";
                                    return false;
                                }
                            }

                            if (std::getline(vertexStream, read, '/'))
                            {
                                index = std::strtol(read.c_str(), nullptr, 0);

                                if (index < 0)
                                    std::get<2>(i) = static_cast<uint32_t>(static_cast<long>(normals.size()) + index);
                                else if (index > 0)
                                    std::get<2>(i) = static_cast<uint32_t>(index - 1);
                                else
                                {
                                    Log(Log::Level::ERR) << "Failed to parse face";
                                    return false;
                                }
                            }

                            auto vertexIterator = vertexMap.find(i);
                            if (vertexIterator != vertexMap.end())
                            {
                                vertexIndices.push_back(vertexIterator->second);
                            }
                            else
                            {
                                graphics::Vertex vertex;
                                vertex.position = positions[std::get<0>(i)];
                                vertex.texCoords[0] = texCoords[std::get<1>(i)];
                                vertex.color = Color::WHITE;
                                vertex.normal = normals[std::get<2>(i)];
                                vertexIndices.push_back(static_cast<uint32_t>(vertices.size()));
                                vertices.push_back(vertex);
                                boundingBox.insertPoint(vertex.position);
                            }
                        }

                        if (vertexIndices.size() < 3)
                        {
                            Log(Log::Level::ERR) << "Invalid face count";
                            return false;
                        }
                        else if (vertexIndices.size() == 3)
                        {
                            for (uint32_t vertexIndex : vertexIndices)
                            {
                                indices.push_back(vertexIndex);
                            }
                        }
                        else
                        {
                            // TODO: implement
                        }
                    }

                    if (!objectCount) ++objectCount; // if we got at least one attribute, we have an object
                }
            }

            if (objectCount)
            {
                scene::ModelData modelData;
                modelData.init(boundingBox, indices, vertices, material);
                engine->getCache()->setModelData(name, modelData);
            }

            return true;
        }
    } // namespace assets
} // namespace ouzel
<commit_msg>Log error on non-triangle faces in OBJ loader<commit_after>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include <cstdlib>
#include <iterator>
#include <map>
#include <sstream>
#include <tuple>
#include "LoaderOBJ.hpp"
#include "Cache.hpp"
#include "core/Engine.hpp"
#include "graphics/Material.hpp"
#include "utils/Log.hpp"

namespace ouzel
{
    namespace assets
    {
        LoaderOBJ::LoaderOBJ():
            Loader({"obj"})
        {
        }

        bool LoaderOBJ::loadAsset(const std::string& filename, const std::vector<uint8_t>& data)
        {
            std::stringstream stream;
            std::copy(data.begin(), data.end(), std::ostream_iterator<uint8_t>(stream));

            std::string name = filename;
            std::shared_ptr<graphics::Material> material;
            std::vector<Vector3> positions;
            std::vector<Vector2> texCoords;
            std::vector<Vector3> normals;
            std::vector<graphics::Vertex> vertices;
            std::map<std::tuple<uint32_t, uint32_t, uint32_t>, uint32_t> vertexMap;
            std::vector<uint32_t> indices;
            Box3 boundingBox;

            uint32_t objectCount = 0;
            std::string read;

            for (std::string line; std::getline(stream, line);)
            {
                if (!line.empty())
                {
                    std::stringstream lineStream;
                    lineStream << line;

                    read.clear();
                    lineStream >> read;

                    if (read.empty() || read[0] == '#') // empty or comment
                    {
                        continue;
                    }
                    else if (read == "mtllib")
                    {
                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse material library file name";
                            return false;
                        }

                        read.clear();
                        lineStream >> read;
                        cache->loadAsset(read);
                    }
                    else if (read == "usemtl")
                    {
                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse material name";
                            return false;
                        }

                        read.clear();
                        lineStream >> read;
                        material = cache->getMaterial(read);
                    }
                    else if (read == "o") // object name
                    {
                        if (objectCount)
                        {
                            scene::ModelData modelData;
                            modelData.init(boundingBox, indices, vertices, material);
                            engine->getCache()->setModelData(name, modelData);
                        }

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse object name";
                            return false;
                        }

                        read.clear();
                        lineStream >> read;

                        name = read;
                        material.reset();
                        positions.clear();
                        texCoords.clear();
                        normals.clear();
                        vertices.clear();
                        indices.clear();
                        boundingBox.reset();
                        ++objectCount;
                    }
                    else if (read == "v") // vertex
                    {
                        Vector3 position;
                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse position";
                            return false;
                        }

                        lineStream >> position.x;

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse position";
                            return false;
                        }

                        lineStream >> position.y;

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse position";
                            return false;
                        }

                        lineStream >> position.z;

                        positions.push_back(position);
                    }
                    else if (read == "vt") // texture coordinates
                    {
                        Vector3 texCoord;
                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse texture coordinates";
                            return false;
                        }

                        lineStream >> texCoord.x;

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse texture coordinates";
                            return false;
                        }

                        lineStream >> texCoord.y;

                        texCoords.push_back(texCoord);
                    }
                    else if (read == "vn") // normal
                    {
                        Vector3 normal;
                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse normal";
                            return false;
                        }

                        lineStream >> normal.x;

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse normal";
                            return false;
                        }

                        lineStream >> normal.y;

                        if (lineStream.eof())
                        {
                            Log(Log::Level::ERR) << "Failed to parse normal";
                            return false;
                        }

                        lineStream >> normal.z;

                        normals.push_back(normal);
                    }
                    else if (read == "f") // face
                    {
                        std::vector<uint32_t> vertexIndices;

                        while (!lineStream.eof())
                        {
                            read.clear();
                            lineStream >> read;

                            std::stringstream vertexStream;
                            vertexStream << read;

                            std::tuple<uint32_t, uint32_t, uint32_t> i = std::make_tuple(0, 0, 0);

                            if (!std::getline(vertexStream, read, '/'))
                            {
                                Log(Log::Level::ERR) << "Failed to parse face";
                                return false;
                            }

                            long index = std::strtol(read.c_str(), nullptr, 0);

                            if (index < 0)
                                std::get<0>(i) = static_cast<uint32_t>(static_cast<long>(positions.size()) + index);
                            else if (index > 0)
                                std::get<0>(i) = static_cast<uint32_t>(index - 1);
                            else
                            {
                                Log(Log::Level::ERR) << "Failed to parse face";
                                return false;
                            }

                            if (std::getline(vertexStream, read, '/'))
                            {
                                index = std::strtol(read.c_str(), nullptr, 0);

                                if (index < 0)
                                    std::get<1>(i) = static_cast<uint32_t>(static_cast<long>(texCoords.size()) + index);
                                else if (index > 0)
                                    std::get<1>(i) = static_cast<uint32_t>(index - 1);
                                else
                                {
                                    Log(Log::Level::ERR) << "Failed to parse face";
                                    return false;
                                }
                            }

                            if (std::getline(vertexStream, read, '/'))
                            {
                                index = std::strtol(read.c_str(), nullptr, 0);

                                if (index < 0)
                                    std::get<2>(i) = static_cast<uint32_t>(static_cast<long>(normals.size()) + index);
                                else if (index > 0)
                                    std::get<2>(i) = static_cast<uint32_t>(index - 1);
                                else
                                {
                                    Log(Log::Level::ERR) << "Failed to parse face";
                                    return false;
                                }
                            }

                            auto vertexIterator = vertexMap.find(i);
                            if (vertexIterator != vertexMap.end())
                            {
                                vertexIndices.push_back(vertexIterator->second);
                            }
                            else
                            {
                                graphics::Vertex vertex;
                                vertex.position = positions[std::get<0>(i)];
                                vertex.texCoords[0] = texCoords[std::get<1>(i)];
                                vertex.color = Color::WHITE;
                                vertex.normal = normals[std::get<2>(i)];
                                vertexIndices.push_back(static_cast<uint32_t>(vertices.size()));
                                vertices.push_back(vertex);
                                boundingBox.insertPoint(vertex.position);
                            }
                        }

                        if (vertexIndices.size() < 3)
                        {
                            Log(Log::Level::ERR) << "Invalid face count";
                            return false;
                        }
                        else if (vertexIndices.size() == 3)
                        {
                            for (uint32_t vertexIndex : vertexIndices)
                            {
                                indices.push_back(vertexIndex);
                            }
                        }
                        else
                        {
                            // TODO: implement
                            Log(Log::Level::ERR) << "Non-triangle faces are not supported";
                            return false;
                        }
                    }

                    if (!objectCount) ++objectCount; // if we got at least one attribute, we have an object
                }
            }

            if (objectCount)
            {
                scene::ModelData modelData;
                modelData.init(boundingBox, indices, vertices, material);
                engine->getCache()->setModelData(name, modelData);
            }

            return true;
        }
    } // namespace assets
} // namespace ouzel
<|endoftext|>


<commit_before>//
// Created by Sam on 9/25/2017.
//

#include "../../include/Network/Client.h"
#include "../../include/Network/Server.h"
#include "../../include/Game/Core/Game.h"
#include "../../include/Game/Core/Player.h"

#include <iostream>

typedef boost::shared_ptr<Client> pointer;

pointer Client::Create(boost::asio::io_service & ioService)
{
    return pointer(new Client(ioService));
}

boost::asio::ip::tcp::socket & Client::GetSocket()
{
    return socket;
}

std::string Client::GetAddress()
{
    return shared_from_this()->GetSocket().remote_endpoint().address().to_string();
}

void Client::Start(Server* server)
{
    this->server = server;
    Write("Connected!");

    listening = true;
    Write("What is your name?");
    AsyncListen(&Client::authenticateClient);
}

void Client::Write(std::string data)
{
    data.append(delimiter);

    boost::asio::async_write(socket, boost::asio::buffer(data.c_str(), data.size()),
                             boost::bind(&Client::OnWrite, shared_from_this(),
                                         boost::asio::placeholders::error,
                                         boost::asio::placeholders::bytes_transferred));
}

void Client::Disconnect()
{
    socket.close();
    server->RemoveClient(shared_from_this());
    std::cout << "Lost connection to client!" << std::endl;
}

void Client::AsyncListen(void (Client::*callback)())
{
    boost::asio::async_read_until(socket, buffer, delimiter,
                                  boost::bind(&Client::Listen, shared_from_this(),
                                              boost::asio::placeholders::error, callback));
}

void Client::Listen(const boost::system::error_code& errorCode, void (Client::*callback)())
{
    if (errorCode == nullptr && listening)
    {
        (*this.*callback)();
        AsyncListen(&Client::printMessage);
    }
    else
    {
        Disconnect();
    }
}

void Client::emptyBuffer()
{
    buffer.consume(buffer.size());
}

void Client::authenticateClient()
{
    std::string message = GetString(buffer);
    name = message;
    emptyBuffer();

    server->AddClient(shared_from_this());
}

void Client::printMessage()
{
    std::string message = GetString(buffer);
    std::cout << "Message from " << static_cast<void*>(this) << ": " << message << std::endl;
    emptyBuffer();
}

std::string Client::GetString(boost::asio::streambuf& buffer)
{
    boost::asio::streambuf::const_buffers_type bufs = buffer.data();
    std::string data(
            boost::asio::buffers_begin(bufs),
            boost::asio::buffers_begin(bufs) + buffer.size());

    // Return everything except the last character delimeter
    return data.substr(0, data.size() - 1);
}

void Client::OnWrite(const boost::system::error_code & errorCode, size_t bytesTransferred) const
{
}

Client::Client(boost::asio::io_service & ioService)
        : player(nullptr), server(nullptr), listening(false), socket(ioService), delimiter("\n")
{
}

<commit_msg>Implemented the message class when we send messages to clients. Currently this only happens during the client connection handshake<commit_after>//
// Created by Sam on 9/25/2017.
//

#include "../../include/Network/Client.h"
#include "../../include/Network/Server.h"
#include "../../include/Game/Core/Game.h"
#include "../../include/Game/Core/Player.h"
#include "../../include/Network/Message.h"

#include <iostream>

typedef boost::shared_ptr<Client> pointer;

pointer Client::Create(boost::asio::io_service & ioService)
{
    return pointer(new Client(ioService));
}

boost::asio::ip::tcp::socket & Client::GetSocket()
{
    return socket;
}

std::string Client::GetAddress()
{
    return shared_from_this()->GetSocket().remote_endpoint().address().to_string();
}

void Client::Start(Server* server)
{
    this->server = server;
    Write(Message("success", "Connected!").exportJSON());

    listening = true;
    Write(Message("authentication", "What is your name?").exportJSON());
    AsyncListen(&Client::authenticateClient);
}

void Client::Write(std::string data)
{
    data.append(delimiter);

    boost::asio::async_write(socket, boost::asio::buffer(data.c_str(), data.size()),
                             boost::bind(&Client::OnWrite, shared_from_this(),
                                         boost::asio::placeholders::error,
                                         boost::asio::placeholders::bytes_transferred));
}

void Client::Disconnect()
{
    socket.close();
    server->RemoveClient(shared_from_this());
    std::cout << "Lost connection to client!" << std::endl;
}

void Client::AsyncListen(void (Client::*callback)())
{
    boost::asio::async_read_until(socket, buffer, delimiter,
                                  boost::bind(&Client::Listen, shared_from_this(),
                                              boost::asio::placeholders::error, callback));
}

void Client::Listen(const boost::system::error_code& errorCode, void (Client::*callback)())
{
    if (errorCode == nullptr && listening)
    {
        (*this.*callback)();
        AsyncListen(&Client::printMessage);
    }
    else
    {
        Disconnect();
    }
}

void Client::emptyBuffer()
{
    buffer.consume(buffer.size());
}

void Client::authenticateClient()
{
    std::string message = GetString(buffer);
    name = message;
    emptyBuffer();

    server->AddClient(shared_from_this());
}

void Client::printMessage()
{
    std::string message = GetString(buffer);
    std::cout << "Message from " << name << ": " << message << std::endl;
    emptyBuffer();
}

std::string Client::GetString(boost::asio::streambuf& buffer)
{
    boost::asio::streambuf::const_buffers_type bufs = buffer.data();
    std::string data(
            boost::asio::buffers_begin(bufs),
            boost::asio::buffers_begin(bufs) + buffer.size());

    // Return everything except the last character delimeter
    return data.substr(0, data.size() - 1);
}

void Client::OnWrite(const boost::system::error_code & errorCode, size_t bytesTransferred) const
{
}

Client::Client(boost::asio::io_service & ioService)
        : player(nullptr), server(nullptr), listening(false), socket(ioService), delimiter("\n")
{
}

<|endoftext|>


<commit_before>/* -*- indent-tabs-mode: nil -*- */
/*
  ODBCConnection.cpp

  Qore ODBC module

  Copyright (C) 2016 Ondrej Musil

  Permission is hereby granted, free of charge, to any person obtaining a
  copy of this software and associated documentation files (the "Software"),
  to deal in the Software without restriction, including without limitation
  the rights to use, copy, modify, merge, publish, distribute, sublicense,
  and/or sell copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  DEALINGS IN THE SOFTWARE.
*/

#include "ODBCConnection.h"

#include <memory>

#include "ErrorHelper.h"
#include "ODBCStatement.h"

ODBCConnection::ODBCConnection(Datasource* d, const char* str, ExceptionSink* xsink) : ds(d) {
    SQLRETURN ret;
    // Allocate an environment handle.
    ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
    if (!SQL_SUCCEEDED(ret)) { // error
        xsink->raiseException("DBI:ODBC:ENV-HANDLE-ERROR", "could not allocate an environment handle");
        return;
    }

    // We want ODBC 3 support.
    SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*) SQL_OV_ODBC3, 0);

    // Allocate a connection handle.
    ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbConn);
    if (!SQL_SUCCEEDED(ret)) { // error
        xsink->raiseException("DBI:ODBC:CONNECTION-HANDLE-ERROR", "could not allocate a connection handle");
        return;
    }

    // Set connection attributes.
    SQLSetConnectAttr(dbConn, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER);
    SQLSetConnectAttr(dbConn, SQL_ATTR_QUIET_MODE, NULL, SQL_IS_POINTER);

    SQLCHAR* odbcDS = reinterpret_cast<SQLCHAR*>(const_cast<char*>(str));

    // Connect.
    //ret = SQLDriverConnectA(dbConn, NULL, "DSN=web;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
    ret = SQLDriverConnectA(dbConn, NULL, odbcDS, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
    if (!SQL_SUCCEEDED(ret)) { // error
        handleDbcError("could not connect to the driver", "DBI:ODBC:CONNECTION-ERROR", xsink);
        return;
    }

    // server version

    // timezones

    // encoding

    /*const char *pstr;
    // get server version to encode/decode binary values properly
#if POSTGRES_VERSION_MAJOR >= 8
    int server_version = PQserverVersion(pc);
    //printd(5, "version: %d\n", server_version);
    interval_has_day = server_version >= 80100 ? true : false;
#else
    pstr = PQparameterStatus(pc, "server_version");
    interval_has_day = strcmp(pstr, "8.1") >= 0 ? true : false;
#endif
    pstr = PQparameterStatus(pc, "integer_datetimes");

    if (!pstr || !pstr[0]) {
        // encoding does not matter here; we are only getting an integer
        QorePgsqlStatement res(this, QCS_DEFAULT);
        integer_datetimes = res.checkIntegerDateTimes(xsink);
    }
    else
        integer_datetimes = strcmp(pstr, "off");

    if (PQsetClientEncoding(pc, ds->getDBEncoding()))
        xsink->raiseException("DBI:PGSQL:ENCODING-ERROR", "invalid PostgreSQL encoding '%s'", ds->getDBEncoding());*/
}

ODBCConnection::~ODBCConnection() {
    // Free up allocated handles.
    SQLFreeHandle(SQL_HANDLE_DBC, dbConn);
    SQLFreeHandle(SQL_HANDLE_ENV, env);
}

int ODBCConnection::commit(ExceptionSink* xsink) {
    SQLRETURN ret = SQLEndTran(SQL_HANDLE_DBC, dbConn, SQL_COMMIT);
    if (!SQL_SUCCEEDED(ret)) { // error
        handleDbcError("DBI:ODBC:COMMIT-ERROR", "could not commit the transaction", xsink);
        return -1;
    }
    return 0;
}

int ODBCConnection::rollback(ExceptionSink* xsink) {
    SQLRETURN ret = SQLEndTran(SQL_HANDLE_DBC, dbConn, SQL_ROLLBACK);
    if (!SQL_SUCCEEDED(ret)) { // error
        handleDbcError("DBI:ODBC:ROLLBACK-ERROR", "could not rollback the transaction", xsink);
        return -1;
    }
    return 0;
}

QoreListNode* ODBCConnection::selectRows(const QoreString* qstr, const QoreListNode* args, ExceptionSink* xsink) {
    ODBCStatement res(this, xsink);
    if (res.exec(qstr, args, xsink))
        return NULL;

    return res.getOutputList(xsink);
}

QoreHashNode* ODBCConnection::selectRow(const QoreString* qstr, const QoreListNode* args, ExceptionSink* xsink) {
    ODBCStatement res(this, xsink);
    if (res.exec(qstr, args, xsink))
        return NULL;

    return res.getSingleRow(xsink);
}

AbstractQoreNode* ODBCConnection::exec(const QoreString* qstr, const QoreListNode* args, ExceptionSink* xsink) {
    ODBCStatement res(this, xsink);
    if (res.exec(qstr, args, xsink))
        return NULL;

    if (res.hasResultData())
        return res.getOutputHash(xsink);

    return new QoreBigIntNode(res.rowsAffected());
}

AbstractQoreNode* ODBCConnection::execRaw(const QoreString* qstr, ExceptionSink* xsink) {
    ODBCStatement res(this, xsink);

    // Convert string to required character encoding or copy.
    std::unique_ptr<QoreString> str(qstr->convertEncoding(QEM.findCreate("ASCII"), xsink));
    if (!str.get())
        return NULL;

    if (res.exec(str->getBuffer(), xsink))
        return NULL;

    if (res.hasResultData())
        return res.getOutputHash(xsink);

    return new QoreBigIntNode(res.rowsAffected());
}

int ODBCConnection::getServerVersion() const {
    // TODO
    return 0;
}

void ODBCConnection::allocStatementHandle(SQLHSTMT& stmt, ExceptionSink* xsink) {
    SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_STMT, dbConn, &stmt);
    if (!SQL_SUCCEEDED(ret)) { // error
        handleDbcError("DBI:ODBC:STATEMENT-ALLOC-ERROR", "could not allocate a statement handle", xsink);
    }
}

void ODBCConnection::handleDbcError(const char* err, const char* desc, ExceptionSink* xsink) {
    std::stringstream s(desc);
    ErrorHelper::extractDiag(SQL_HANDLE_DBC, dbConn, s);
    xsink->raiseException(err, s.str().c_str());
}

<commit_msg>Fixed disconnecting in ODBCConnection.<commit_after>/* -*- indent-tabs-mode: nil -*- */
/*
  ODBCConnection.cpp

  Qore ODBC module

  Copyright (C) 2016 Ondrej Musil

  Permission is hereby granted, free of charge, to any person obtaining a
  copy of this software and associated documentation files (the "Software"),
  to deal in the Software without restriction, including without limitation
  the rights to use, copy, modify, merge, publish, distribute, sublicense,
  and/or sell copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  DEALINGS IN THE SOFTWARE.
*/

#include "ODBCConnection.h"

#include <memory>

#include "qore/QoreLib.h"

#include "ErrorHelper.h"
#include "ODBCStatement.h"

ODBCConnection::ODBCConnection(Datasource* d, const char* str, ExceptionSink* xsink) : ds(d) {
    SQLRETURN ret;
    // Allocate an environment handle.
    ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
    if (!SQL_SUCCEEDED(ret)) { // error
        xsink->raiseException("DBI:ODBC:ENV-HANDLE-ERROR", "could not allocate an environment handle");
        return;
    }

    // Use ODBC version 3.
    SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*) SQL_OV_ODBC3, 0);

    // Allocate a connection handle.
    ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbConn);
    if (!SQL_SUCCEEDED(ret)) { // error
        xsink->raiseException("DBI:ODBC:CONNECTION-HANDLE-ERROR", "could not allocate a connection handle");
        return;
    }

    // Set connection attributes.
    SQLSetConnectAttr(dbConn, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER);
    SQLSetConnectAttr(dbConn, SQL_ATTR_QUIET_MODE, NULL, SQL_IS_POINTER);

    SQLCHAR* odbcDS = reinterpret_cast<SQLCHAR*>(const_cast<char*>(str));

    // Connect.
    //ret = SQLDriverConnectA(dbConn, NULL, "DSN=web;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
    ret = SQLDriverConnectA(dbConn, NULL, odbcDS, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
    if (!SQL_SUCCEEDED(ret)) { // error
        handleDbcError("could not connect to the driver", "DBI:ODBC:CONNECTION-ERROR", xsink);
        return;
    }

    // server version

    // timezones

    // encoding

    /*const char *pstr;
    // get server version to encode/decode binary values properly
#if POSTGRES_VERSION_MAJOR >= 8
    int server_version = PQserverVersion(pc);
    //printd(5, "version: %d\n", server_version);
    interval_has_day = server_version >= 80100 ? true : false;
#else
    pstr = PQparameterStatus(pc, "server_version");
    interval_has_day = strcmp(pstr, "8.1") >= 0 ? true : false;
#endif
    pstr = PQparameterStatus(pc, "integer_datetimes");

    if (!pstr || !pstr[0]) {
        // encoding does not matter here; we are only getting an integer
        QorePgsqlStatement res(this, QCS_DEFAULT);
        integer_datetimes = res.checkIntegerDateTimes(xsink);
    }
    else
        integer_datetimes = strcmp(pstr, "off");

    if (PQsetClientEncoding(pc, ds->getDBEncoding()))
        xsink->raiseException("DBI:PGSQL:ENCODING-ERROR", "invalid PostgreSQL encoding '%s'", ds->getDBEncoding());*/
}

ODBCConnection::~ODBCConnection() {
    while (true) {
        SQLRETURN ret = SQLDisconnect(dbConn);
        if (SQL_SUCCEEDED(ret))
            break;
        qore_usleep(50*1000); // Sleep in intervals of 50 ms until disconnected.
    }

    // Free up allocated handles.
    SQLFreeHandle(SQL_HANDLE_DBC, dbConn);
    SQLFreeHandle(SQL_HANDLE_ENV, env);
}

int ODBCConnection::commit(ExceptionSink* xsink) {
    SQLRETURN ret = SQLEndTran(SQL_HANDLE_DBC, dbConn, SQL_COMMIT);
    if (!SQL_SUCCEEDED(ret)) { // error
        handleDbcError("DBI:ODBC:COMMIT-ERROR", "could not commit the transaction", xsink);
        return -1;
    }
    return 0;
}

int ODBCConnection::rollback(ExceptionSink* xsink) {
    SQLRETURN ret = SQLEndTran(SQL_HANDLE_DBC, dbConn, SQL_ROLLBACK);
    if (!SQL_SUCCEEDED(ret)) { // error
        handleDbcError("DBI:ODBC:ROLLBACK-ERROR", "could not rollback the transaction", xsink);
        return -1;
    }
    return 0;
}

QoreListNode* ODBCConnection::selectRows(const QoreString* qstr, const QoreListNode* args, ExceptionSink* xsink) {
    ODBCStatement res(this, xsink);
    if (res.exec(qstr, args, xsink))
        return NULL;

    return res.getOutputList(xsink);
}

QoreHashNode* ODBCConnection::selectRow(const QoreString* qstr, const QoreListNode* args, ExceptionSink* xsink) {
    ODBCStatement res(this, xsink);
    if (res.exec(qstr, args, xsink))
        return NULL;

    return res.getSingleRow(xsink);
}

AbstractQoreNode* ODBCConnection::exec(const QoreString* qstr, const QoreListNode* args, ExceptionSink* xsink) {
    ODBCStatement res(this, xsink);
    if (res.exec(qstr, args, xsink))
        return NULL;

    if (res.hasResultData())
        return res.getOutputHash(xsink);

    return new QoreBigIntNode(res.rowsAffected());
}

AbstractQoreNode* ODBCConnection::execRaw(const QoreString* qstr, ExceptionSink* xsink) {
    ODBCStatement res(this, xsink);

    // Convert string to required character encoding or copy.
    std::unique_ptr<QoreString> str(qstr->convertEncoding(QEM.findCreate("ASCII"), xsink));
    if (!str.get())
        return NULL;

    if (res.exec(str->getBuffer(), xsink))
        return NULL;

    if (res.hasResultData())
        return res.getOutputHash(xsink);

    return new QoreBigIntNode(res.rowsAffected());
}

int ODBCConnection::getServerVersion() const {
    // TODO
    return 0;
}

void ODBCConnection::allocStatementHandle(SQLHSTMT& stmt, ExceptionSink* xsink) {
    SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_STMT, dbConn, &stmt);
    if (!SQL_SUCCEEDED(ret)) { // error
        handleDbcError("DBI:ODBC:STATEMENT-ALLOC-ERROR", "could not allocate a statement handle", xsink);
    }
}

void ODBCConnection::handleDbcError(const char* err, const char* desc, ExceptionSink* xsink) {
    std::stringstream s(desc);
    ErrorHelper::extractDiag(SQL_HANDLE_DBC, dbConn, s);
    xsink->raiseException(err, s.str().c_str());
}

<|endoftext|>


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

#pragma once

#include "NvOnnxParser.h"
#include "ShapedWeights.hpp"
#include "TensorOrWeights.hpp"
#include "Status.hpp"
#include "plugin.hpp"

#include <onnx/onnx.pb.h>
#include <NvInfer.h>
#include <vector>

namespace onnx2trt {

class IImporterContext;

// TODO: Find ABI-safe alternative approach for this:
//         Can't use std::vector
//         Can't use ::onnx::NodeProto
//         Can't use std::function
typedef ValueOrStatus<std::vector<TensorOrWeights>> NodeImportResult;
typedef std::function<NodeImportResult(IImporterContext *ctx,
                                       ::ONNX_NAMESPACE::NodeProto const &node,
                                       std::vector<TensorOrWeights> &inputs)>
    NodeImporter;

struct IImporterContext {
  virtual nvinfer1::INetworkDefinition* network() = 0;
  virtual ShapedWeights createTempWeights(ShapedWeights::DataType type,
                                          nvinfer1::Dims shape) = 0;
  virtual nvinfer1::IPluginLayer* addPlugin(
      Plugin* plugin,
      std::vector<nvinfer1::ITensor*> const& inputs) = 0;
  virtual int64_t getOpsetVersion(const char* domain="") const = 0;
protected:
  virtual ~IImporterContext() {}
};

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

#pragma once

#include "NvOnnxParser.h"
#include "ShapedWeights.hpp"
#include "TensorOrWeights.hpp"
#include "Status.hpp"
#include "plugin.hpp"

#include <onnx/onnx.pb.h>
#include <NvInfer.h>
#include <vector>
#include <functional>

namespace onnx2trt {

class IImporterContext;

// TODO: Find ABI-safe alternative approach for this:
//         Can't use std::vector
//         Can't use ::onnx::NodeProto
//         Can't use std::function
typedef ValueOrStatus<std::vector<TensorOrWeights>> NodeImportResult;
typedef std::function<NodeImportResult(IImporterContext *ctx,
                                       ::ONNX_NAMESPACE::NodeProto const &node,
                                       std::vector<TensorOrWeights> &inputs)>
    NodeImporter;

struct IImporterContext {
  virtual nvinfer1::INetworkDefinition* network() = 0;
  virtual ShapedWeights createTempWeights(ShapedWeights::DataType type,
                                          nvinfer1::Dims shape) = 0;
  virtual nvinfer1::IPluginLayer* addPlugin(
      Plugin* plugin,
      std::vector<nvinfer1::ITensor*> const& inputs) = 0;
  virtual int64_t getOpsetVersion(const char* domain="") const = 0;
protected:
  virtual ~IImporterContext() {}
};

} // namespace onnx2trt
<|endoftext|>


<commit_before>#include "../glm/gtx/transform.hpp"

#include "camera.h"

using namespace glm;

Camera::Camera(vec3 pos, vec3 tar, vec3 up) : m_position(pos), m_target(tar), m_up(normalize(up))
{
	setTarget(m_target);
	update();
}

Camera::~Camera()
{
}

void Camera::updateMatrix()
{
	m_passage = mat3(m_forward, m_left, m_up);
	m_passageInverse = inverse(m_passage);
}

void Camera::updateAngles()
{
	vec3 m_vect = m_passageInverse * m_orientation;
	m_phi = asin(m_vect.z);
	m_theta = acos(m_vect.y / cos(m_phi));
}

void Camera::setPosition(glm::vec3 pos)
{
	m_position = pos;
	m_target = m_position + m_orientation;
}

void Camera::setUp(glm::vec3 up)
{
	m_up = normalize(up);
	m_left = normalize(cross(m_up, m_forward));
	m_forward = normalize(cross(m_left, m_up));

	updateMatrix();
	setOrientation(0, 0);
	update();
}

void Camera::setTarget(glm::vec3 tar)
{
	m_orientation = normalize(m_target - m_position);
	m_left = normalize(cross(m_up, m_orientation));
	m_forward = normalize(cross(m_left, m_up));

	updateMatrix();
	updateAngles();
}

void Camera::setOrientation(double x, double y)
{
	m_theta += -x * 0.002f;
	m_phi += -y * 0.002f;

	double limite = 1.55;
	if (m_phi > limite)
		m_phi = limite;
	else if (m_phi < - limite)
		m_phi = -limite;

	vec3 m_vect = m_passage * m_orientation;

	m_vect.x = cos(m_phi) * cos(m_theta);
	m_vect.y = cos(m_phi) * sin(m_theta);
	m_vect.z = sin(m_phi);

	m_orientation = m_passageInverse * m_vect;
	m_left = normalize(cross(m_up, m_orientation));

	m_target = m_position + m_orientation;

	update();
}

void Camera::move(vec3 mvt, float time)
{
	if (mvt != vec3(0, 0, 0))
	{
		mvt = normalize(mvt) * time * 10.f;
		setPosition(m_position + m_orientation * mvt.x + m_left * mvt.y + normalize(cross(m_orientation, m_left)) * mvt.z);
		update();
	}
}

void Camera::update()
{
	m_view = lookAt(m_position, m_target, m_up);
}

mat4 Camera::getView() const
{
	return m_view ;
}

vec3 Camera::getPosition() const
{
	return m_position;
}

glm::vec3 Camera::getOrientation() const
{
	return m_orientation;
}

glm::vec3 Camera::getUp() const
{
	return m_up;
}

glm::vec3 Camera::getTarget() const
{
	return m_target;
}

glm::vec3 Camera::getLeft() const
{
	return m_left;
}
<commit_msg>fix camera<commit_after>#include "../glm/gtx/transform.hpp"

#include "camera.h"

using namespace glm;

Camera::Camera(vec3 pos, vec3 tar, vec3 up) : m_position(pos), m_up(normalize(up))
{
	setTarget(tar);
	update();
}

Camera::~Camera()
{
}

void Camera::updateMatrix()
{
	m_passage = mat3(m_forward, m_left, m_up);
	m_passageInverse = inverse(m_passage);
}

void Camera::updateAngles()
{
	vec3 m_vect = m_passageInverse * m_orientation;
	m_phi = asin(m_vect.z);
	m_theta = asin(m_vect.y / cos(m_phi));
}

void Camera::setPosition(glm::vec3 pos)
{
	m_position = pos;
	m_target = m_position + m_orientation;
}

void Camera::setUp(glm::vec3 up)
{
	m_up = normalize(up);
	m_left = normalize(cross(m_up, m_forward));
	m_forward = normalize(cross(m_left, m_up));

	updateMatrix();
	setOrientation(0, 0);
	update();
}

void Camera::setTarget(glm::vec3 tar)
{
	m_orientation = normalize(tar - m_position);
	m_left = normalize(cross(m_up, m_orientation));
	m_forward = normalize(cross(m_left, m_up));

	updateMatrix();
	updateAngles();
}

void Camera::setOrientation(double x, double y)
{
	m_theta += -x * 0.002f;
	m_phi += -y * 0.002f;

	double limite = 1.55;
	if (m_phi > limite)
		m_phi = limite;
	else if (m_phi < - limite)
		m_phi = -limite;

	vec3 m_vect = m_passage * m_orientation;

	m_vect.x = cos(m_phi) * cos(m_theta);
	m_vect.y = cos(m_phi) * sin(m_theta);
	m_vect.z = sin(m_phi);

	m_orientation = m_passageInverse * m_vect;
	m_left = normalize(cross(m_up, m_orientation));

	m_target = m_position + m_orientation;

	update();
}

void Camera::move(vec3 mvt, float time)
{
	if (mvt != vec3(0, 0, 0))
	{
		mvt = normalize(mvt) * time * 10.f;
		setPosition(m_position + m_orientation * mvt.x + m_left * mvt.y + normalize(cross(m_orientation, m_left)) * mvt.z);
		update();
	}
}

void Camera::update()
{
	m_view = lookAt(m_position, m_target, m_up);
}

mat4 Camera::getView() const
{
	return m_view ;
}

vec3 Camera::getPosition() const
{
	return m_position;
}

glm::vec3 Camera::getOrientation() const
{
	return m_orientation;
}

glm::vec3 Camera::getUp() const
{
	return m_up;
}

glm::vec3 Camera::getTarget() const
{
	return m_target;
}

glm::vec3 Camera::getLeft() const
{
	return m_left;
}
<|endoftext|>


<commit_before>#ifndef _GRIDPATH_HPP_
#define _GRIDPATH_HPP_

#include "gridmap.hpp"
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cassert>

struct GridNav {

	struct Cost {
		Cost(void) { }

		explicit Cost(int u, int s = 0) : units(u), sqrts(s) { compute(); }

		Cost &operator=(const Cost &o) {
			units = o.units;
			sqrts = o.sqrts;
			val = o.val;
			return *this;
		}

		Cost &operator+=(const Cost &o) {
			units += o.units;
			sqrts += o.sqrts;
			compute();
			return *this;
		}

		Cost &operator-=(const Cost &o) {
			units -= o.units;
			sqrts -= o.sqrts;
			compute();
			return *this;
		}

		operator double() { return val; }

		Cost operator+(const Cost &o) const {
			return Cost(units + o.units, sqrts + o.sqrts);
		}

		Cost operator-(const Cost &o) const {
			return Cost(units - o.units, sqrts - o.sqrts);
		}

		bool operator<(const Cost &o) const {
			return val < o.val;
		}

		bool operator>(const Cost &o) const {
			return val > o.val;
		}

		bool operator==(const Cost &o) const {
			return units == o.units && sqrts == o.sqrts;
		}

		bool operator!=(const Cost &o) const {
			return !(*this == o);
		}

		bool operator>=(const Cost &o) const {
			return !(*this < o);
		}

		bool operator<=(const Cost &o) const {
			return !(*this > o);
		}

	private:

		void compute(void) {
			val = units + sqrts * sqrt(2);
		}

		int units, sqrts;
		double val;
	};

	typedef int Oper;	// Index into the ops arrays.
	enum { Nop = -1 };

	GridNav(GridMap*, unsigned int, unsigned int,
		unsigned int, unsigned int);

	struct State {
		State &operator=(const State &o) {
 			loc = o.loc;
			nops = -1;
 			return *this;
		}

		State(void) :nops(-1) { }

		State (const State &o) : loc(o.loc), nops(-1) { }

		State(unsigned int l) : loc(l), nops(-1) { }

	private:
		friend struct GridNav;
		int loc;
		int nops;
		Oper ops[8];
	};

	struct PackedState {
		int loc;

		unsigned long hash(void) { return loc; }

		bool eq(const PackedState &other) const {
			return other.loc == loc;
		}
	};

	State initialstate(void);

	Cost h(State &s) const {
		if (map->nmvs > 4)
			return octiledist(s.loc, finish);
		return manhattan(s.loc, finish);
	}

	Cost d(State &s) const {
		if (map->nmvs > 4)
			return octilecells(s.loc, finish);
		return manhattan(s.loc, finish);
	}

	bool isgoal(State &s) const {
		return s.loc == finish;
	}

	unsigned int nops(State &s) const {
		if (s.nops > 0)
			return s.nops;

		s.nops = 0;
		for (unsigned int i = 0; i < map->nmvs; i++) {
			if (map->ok(s.loc, map->mvs[i]))
				s.ops[s.nops++] = i;
		}
		return s.nops;
	}

	Oper nthop(State &s, unsigned int n) const {
		return s.ops[n];
	}

	struct Transition {
		Cost cost;
		Oper revop;
		State state;

		Transition(GridNav &d, State &s, Oper op) :
				revop(d.rev[op]),
				state(s.loc + d.map->mvs[op].delta) {
			assert (state.loc < (int) d.map->sz);
			if (d.map->mvs[op].cost == 1.0)
				cost = Cost(1, 0);
			else
				cost = Cost(0, 1);
		}
	};

	void pack(PackedState &dst, State &src) const {
		dst.loc = src.loc;
	}

	State &unpack(State &buf, PackedState &pkd) const {
		buf.loc = pkd.loc;
		return buf;
	}

	void dumpstate(FILE *out, State &s) const {
		std::pair<int,int> coord = map->coord(s.loc);
		fprintf(out, "%u, %u\n", coord.first, coord.second);
	}

	int start, finish;
	GridMap *map;

	// rev holds the index of the reverse of each operator
	int rev[8];

private:

	// manhattan returns the Manhattan distance.
	Cost manhattan(int l0, int l1) const {
		std::pair<int,int> c0 = map->coord(l0), c1 = map->coord(l1);
		return Cost(abs(c0.first - c1.first) + abs(c0.second - c1.second), 0);
	}

	// octiledist returns an admissible heuristic estimate for eight-way grids.
	Cost octiledist(int l0, int l1) const {
		std::pair<int,int> c0 = map->coord(l0), c1 = map->coord(l1);
		int dx = abs(c0.first - c1.first);
		int dy = abs(c0.second - c1.second);
		int diag = dx < dy ? dx : dy;
		int straight = dx < dy ? dy : dx;
		return Cost(straight - diag, diag);
	}

	// octilecells returns an admissible distance estimate for eight-way grids.
	Cost octilecells(unsigned int l0, unsigned int l1) const {
		std::pair<int,int> c0 = map->coord(l0), c1 = map->coord(l1);
		int dx = abs(c0.first - c1.first);
		int dy = abs(c0.second - c1.second);
		return Cost(dx < dy ? dy : dx, 0);
	}

	// reverseops computes the reverse operators
	void reverseops(void);
};

#endif	// _GRIDPATH_HPP_
<commit_msg>gridnav: Cost::double() is const.<commit_after>#ifndef _GRIDPATH_HPP_
#define _GRIDPATH_HPP_

#include "gridmap.hpp"
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cassert>

struct GridNav {

	struct Cost {
		Cost(void) { }

		explicit Cost(int u, int s = 0) : units(u), sqrts(s) { compute(); }

		Cost &operator=(const Cost &o) {
			units = o.units;
			sqrts = o.sqrts;
			val = o.val;
			return *this;
		}

		Cost &operator+=(const Cost &o) {
			units += o.units;
			sqrts += o.sqrts;
			compute();
			return *this;
		}

		Cost &operator-=(const Cost &o) {
			units -= o.units;
			sqrts -= o.sqrts;
			compute();
			return *this;
		}

		operator double() const { return val; }

		Cost operator+(const Cost &o) const {
			return Cost(units + o.units, sqrts + o.sqrts);
		}

		Cost operator-(const Cost &o) const {
			return Cost(units - o.units, sqrts - o.sqrts);
		}

		bool operator<(const Cost &o) const {
			return val < o.val;
		}

		bool operator>(const Cost &o) const {
			return val > o.val;
		}

		bool operator==(const Cost &o) const {
			return units == o.units && sqrts == o.sqrts;
		}

		bool operator!=(const Cost &o) const {
			return !(*this == o);
		}

		bool operator>=(const Cost &o) const {
			return !(*this < o);
		}

		bool operator<=(const Cost &o) const {
			return !(*this > o);
		}

	private:

		void compute(void) {
			val = units + sqrts * sqrt(2);
		}

		int units, sqrts;
		double val;
	};

	typedef int Oper;	// Index into the ops arrays.
	enum { Nop = -1 };

	GridNav(GridMap*, unsigned int, unsigned int,
		unsigned int, unsigned int);

	struct State {
		State &operator=(const State &o) {
 			loc = o.loc;
			nops = -1;
 			return *this;
		}

		State(void) :nops(-1) { }

		State (const State &o) : loc(o.loc), nops(-1) { }

		State(unsigned int l) : loc(l), nops(-1) { }

	private:
		friend struct GridNav;
		int loc;
		int nops;
		Oper ops[8];
	};

	struct PackedState {
		int loc;

		unsigned long hash(void) { return loc; }

		bool eq(const PackedState &other) const {
			return other.loc == loc;
		}
	};

	State initialstate(void);

	Cost h(State &s) const {
		if (map->nmvs > 4)
			return octiledist(s.loc, finish);
		return manhattan(s.loc, finish);
	}

	Cost d(State &s) const {
		if (map->nmvs > 4)
			return octilecells(s.loc, finish);
		return manhattan(s.loc, finish);
	}

	bool isgoal(State &s) const {
		return s.loc == finish;
	}

	unsigned int nops(State &s) const {
		if (s.nops > 0)
			return s.nops;

		s.nops = 0;
		for (unsigned int i = 0; i < map->nmvs; i++) {
			if (map->ok(s.loc, map->mvs[i]))
				s.ops[s.nops++] = i;
		}
		return s.nops;
	}

	Oper nthop(State &s, unsigned int n) const {
		return s.ops[n];
	}

	struct Transition {
		Cost cost;
		Oper revop;
		State state;

		Transition(GridNav &d, State &s, Oper op) :
				revop(d.rev[op]),
				state(s.loc + d.map->mvs[op].delta) {
			assert (state.loc < (int) d.map->sz);
			if (d.map->mvs[op].cost == 1.0)
				cost = Cost(1, 0);
			else
				cost = Cost(0, 1);
		}
	};

	void pack(PackedState &dst, State &src) const {
		dst.loc = src.loc;
	}

	State &unpack(State &buf, PackedState &pkd) const {
		buf.loc = pkd.loc;
		return buf;
	}

	void dumpstate(FILE *out, State &s) const {
		std::pair<int,int> coord = map->coord(s.loc);
		fprintf(out, "%u, %u\n", coord.first, coord.second);
	}

	int start, finish;
	GridMap *map;

	// rev holds the index of the reverse of each operator
	int rev[8];

private:

	// manhattan returns the Manhattan distance.
	Cost manhattan(int l0, int l1) const {
		std::pair<int,int> c0 = map->coord(l0), c1 = map->coord(l1);
		return Cost(abs(c0.first - c1.first) + abs(c0.second - c1.second), 0);
	}

	// octiledist returns an admissible heuristic estimate for eight-way grids.
	Cost octiledist(int l0, int l1) const {
		std::pair<int,int> c0 = map->coord(l0), c1 = map->coord(l1);
		int dx = abs(c0.first - c1.first);
		int dy = abs(c0.second - c1.second);
		int diag = dx < dy ? dx : dy;
		int straight = dx < dy ? dy : dx;
		return Cost(straight - diag, diag);
	}

	// octilecells returns an admissible distance estimate for eight-way grids.
	Cost octilecells(unsigned int l0, unsigned int l1) const {
		std::pair<int,int> c0 = map->coord(l0), c1 = map->coord(l1);
		int dx = abs(c0.first - c1.first);
		int dy = abs(c0.second - c1.second);
		return Cost(dx < dy ? dy : dx, 0);
	}

	// reverseops computes the reverse operators
	void reverseops(void);
};

#endif	// _GRIDPATH_HPP_
<|endoftext|>


<commit_before>/********************************************************************************
*                                                                               *
*                                   IPC test                                    *
*                                                                               *
*********************************************************************************
* Copyright (C) 2003 by Niall Douglas.   All Rights Reserved.                   *
*********************************************************************************
* This code is free software; you can redistribute it and/or modify it under    *
* the terms of the GNU Library General Public License v2.1 as published by the  *
* Free Software Foundation EXCEPT that clause 3 does not apply ie; you may not  *
* "upgrade" this code to the GPL without my prior written permission.           *
* Please consult the file "License_Addendum2.txt" accompanying this file.       *
*                                                                               *
* This code 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.                          *
*********************************************************************************
* $Id:                                                                          *
********************************************************************************/

#include "fx.h"
#include "../Tn/TFileBySyncDev.cxx"

class TestChannel : public FXIPCChannel
{
	FXIPCMsgRegistry myregistry;
public:
	TestChannel(FXIODeviceS *dev) : FXIPCChannel(myregistry, dev) { }
protected:
	HandledCode msgReceived(FXIPCMsg *rawmsg)
	{
		return NotHandled;
	}
};

int main(int argc, char *argv[])
{
	FXProcess myprocess(argc, argv);
	char devtype[8], server[8];
	bool amServer;
	int choice=0;
	do
	{
		fxmessage("YOU MUST RUN TWO INSTANCES OF ME AT THE SAME TIME!!!\nBe server (1) or client (2):\n");
		scanf("%s", server);
		amServer=('1'==server[0]);
	} while('1'!=server[0] && '2'!=server[0]);
	fxmessage(amServer ? "Server\n" : "Client\n");
	do
	{
		fxmessage("What should I use for the transport? (S: Socket, P: Pipe\n"
			"    E: Encrypted Socket):\n");
		scanf("%s", devtype);
		if('s'==devtype[0] || 'S'==devtype[0]) choice=1;
		else if('p'==devtype[0] || 'P'==devtype[0]) choice=2;
		else if('e'==devtype[0] || 'E'==devtype[0]) choice=3;
	} while(!choice);
	FXPtrHold<FXIODeviceS> realtransport;
	FXPtrHold<FXIODeviceS> transport;
	if(1==choice || 3==choice)
	{
		if(1==choice) fxmessage("Socket\n");
		if(amServer)
		{
			FXBlkSocket server(FXBlkSocket::Stream, (FXushort) 12345);
			server.create(IO_ReadWrite);
			transport=server.waitForConnection();
		}
		else
		{
			FXERRHM(transport=new FXBlkSocket(FXHOSTADDRESS_LOCALHOST, 12345));
			transport->open(IO_ReadWrite);
		}
	}
	if(2==choice)
	{
		fxmessage("Pipe\n");
		FXERRHM(transport=new FXPipe("TestIPC", true));
		if(amServer)
			transport->create(IO_ReadWrite);
		else
			transport->open(IO_ReadWrite);
	}
	if(3==choice)
	{
		fxmessage("Encrypted socket\n");
		realtransport=transport;
		transport=0;
		FXERRHM(transport=new FXSSLDevice(realtransport));
		if(amServer)
			transport->create(IO_ReadWrite);
		else
			transport->open(IO_ReadWrite);
	}

	TestChannel ch(transport);
	ch.setUnreliable(false);
	ch.setCompression(false);
	ch.setPrintStatistics(false);
	FXERRH_TRY
	{
		const int round=4096; // 4066 for roundness test
		if(amServer)
		{
			FXMemMap testfile("BigFile2.txt");
			testfile.open(IO_ReadWrite);
			testfile.truncate(4*4096*round);	// 4Mb
			char *data=(char *) testfile.mapIn();
			FXuint before=FXProcess::getMsCount();
			memset(data, 'N', (size_t) testfile.size());
			testfile.flush();
			FXuint after=FXProcess::getMsCount();
			fxmessage("Wrote raw file at %fKb/sec\n", (1000.0*testfile.size()/(after-before))/1024);
			before=FXProcess::getMsCount();
			FXuint foo=0;
			for(FXfval n=0; n<testfile.size(); n+=4)
			{
				foo+=*(FXuint *)&data[n];
			}
			after=FXProcess::getMsCount();
			fxmessage("Read raw file at %fKb/sec\n", (1000.0*testfile.size()/(after-before))/1024);
			int cnt=0;
			for(char *ptr=data; ptr<data+testfile.size()-64;)
			{
				sprintf(ptr, "There are %d bottles on the wall!\r\n", cnt++);
				ptr=strchr(ptr,0);
			}
			fxmessage("Running server ...\n");
			Tn::TFileBySyncDev server(true, ch, &testfile);
			server.setPrintStatistics(false);
			ch.start(true);
			ch.wait();
		}
		else
		{
			Tn::TFileBySyncDev client(false, ch);
			client.setPrintStatistics(false);
			ch.start(true);
			Generic::BoundFunctorV *cancelclient=ch.addCleanupCall(Generic::BindObjN(client, &Tn::TFileBySyncDev::invokeConnectionLost), true);
			client.open(IO_ReadWrite);
			char buffer[65536];
			FXuval read=0, justread;
			FXuint before=FXProcess::getMsCount();
			do
			{
				read+=justread=client.readBlock(buffer, 65536);
			} while(justread);
			FXuint after=FXProcess::getMsCount();
			fxmessage("Read through TFileBySyncDev at %fKb/sec\n", (1000.0*read/(after-before))/1024);
			fxmessage("*** Moving to 4096\n");
			client.at(round);
			before=FXProcess::getMsCount();
			for(FXuint n=0; n<read/65536; n++)
			{
				client.writeBlock(buffer, 65536);
			}
			fxmessage("*** Flushing output\n");
			client.flush();
			//fxmessage("*** Synchronising\n");
			//client.at(0);
			//client.readBlock(buffer, 1);
			after=FXProcess::getMsCount();
			fxmessage("Wrote through TFileBySyncDev at %fKb/sec\n", (1000.0*read/(after-before))/1024);
			client.close();
			ch.requestClose();
			ch.wait();
			ch.removeCleanupCall(cancelclient);
		}
	}
	FXERRH_CATCH(FXException &e)
	{
		fxmessage("\n\nException %s\n", e.report().text());
		ch.requestClose();
		ch.wait();
		return 1;
	}
	FXERRH_ENDTRY;

	printf("\n\nTests complete!\n");
#ifdef WIN32
	getchar();
#endif
	return 0;
}
<commit_msg>Increased size of file transfer<commit_after>/********************************************************************************
*                                                                               *
*                                   IPC test                                    *
*                                                                               *
*********************************************************************************
* Copyright (C) 2003 by Niall Douglas.   All Rights Reserved.                   *
*********************************************************************************
* This code is free software; you can redistribute it and/or modify it under    *
* the terms of the GNU Library General Public License v2.1 as published by the  *
* Free Software Foundation EXCEPT that clause 3 does not apply ie; you may not  *
* "upgrade" this code to the GPL without my prior written permission.           *
* Please consult the file "License_Addendum2.txt" accompanying this file.       *
*                                                                               *
* This code 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.                          *
*********************************************************************************
* $Id:                                                                          *
********************************************************************************/

#include "fx.h"
#include "../Tn/TFileBySyncDev.cxx"

class TestChannel : public FXIPCChannel
{
	FXIPCMsgRegistry myregistry;
public:
	TestChannel(FXIODeviceS *dev) : FXIPCChannel(myregistry, dev) { }
protected:
	HandledCode msgReceived(FXIPCMsg *rawmsg)
	{
		return NotHandled;
	}
};

int main(int argc, char *argv[])
{
	FXProcess myprocess(argc, argv);
	char devtype[8], server[8];
	bool amServer;
	int choice=0;
	do
	{
		fxmessage("YOU MUST RUN TWO INSTANCES OF ME AT THE SAME TIME!!!\nBe server (1) or client (2):\n");
		scanf("%s", server);
		amServer=('1'==server[0]);
	} while('1'!=server[0] && '2'!=server[0]);
	fxmessage(amServer ? "Server\n" : "Client\n");
	do
	{
		fxmessage("What should I use for the transport? (S: Socket, P: Pipe\n"
			"    E: Encrypted Socket):\n");
		scanf("%s", devtype);
		if('s'==devtype[0] || 'S'==devtype[0]) choice=1;
		else if('p'==devtype[0] || 'P'==devtype[0]) choice=2;
		else if('e'==devtype[0] || 'E'==devtype[0]) choice=3;
	} while(!choice);
	FXPtrHold<FXIODeviceS> realtransport;
	FXPtrHold<FXIODeviceS> transport;
	if(1==choice || 3==choice)
	{
		if(1==choice) fxmessage("Socket\n");
		if(amServer)
		{
			FXBlkSocket server(FXBlkSocket::Stream, (FXushort) 12345);
			server.create(IO_ReadWrite);
			transport=server.waitForConnection();
		}
		else
		{
			FXERRHM(transport=new FXBlkSocket(FXHOSTADDRESS_LOCALHOST, 12345));
			transport->open(IO_ReadWrite);
		}
	}
	if(2==choice)
	{
		fxmessage("Pipe\n");
		FXERRHM(transport=new FXPipe("TestIPC", true));
		if(amServer)
			transport->create(IO_ReadWrite);
		else
			transport->open(IO_ReadWrite);
	}
	if(3==choice)
	{
		fxmessage("Encrypted socket\n");
		realtransport=transport;
		transport=0;
		FXERRHM(transport=new FXSSLDevice(realtransport));
		if(amServer)
			transport->create(IO_ReadWrite);
		else
			transport->open(IO_ReadWrite);
	}

	TestChannel ch(transport);
	ch.setUnreliable(false);
	ch.setCompression(false);
	ch.setPrintStatistics(false);
	FXERRH_TRY
	{
		const int round=4096; // 4066 for roundness test
		if(amServer)
		{
			FXMemMap testfile("BigFile2.txt");
			testfile.open(IO_ReadWrite);
			testfile.truncate(16*4096*round);	// 4Mb
			char *data=(char *) testfile.mapIn();
			FXuint before=FXProcess::getMsCount();
			memset(data, 'N', (size_t) testfile.size());
			testfile.flush();
			FXuint after=FXProcess::getMsCount();
			fxmessage("Wrote raw file at %fKb/sec\n", (1000.0*testfile.size()/(after-before))/1024);
			before=FXProcess::getMsCount();
			FXuint foo=0;
			for(FXfval n=0; n<testfile.size(); n+=4)
			{
				foo+=*(FXuint *)&data[n];
			}
			after=FXProcess::getMsCount();
			fxmessage("Read raw file at %fKb/sec\n", (1000.0*testfile.size()/(after-before))/1024);
			int cnt=0;
			for(char *ptr=data; ptr<data+testfile.size()-64;)
			{
				sprintf(ptr, "There are %d bottles on the wall!\r\n", cnt++);
				ptr=strchr(ptr,0);
			}
			fxmessage("Running server ...\n");
			Tn::TFileBySyncDev server(true, ch, &testfile);
			server.setPrintStatistics(false);
			ch.start(true);
			ch.wait();
		}
		else
		{
			Tn::TFileBySyncDev client(false, ch);
			client.setPrintStatistics(false);
			ch.start(true);
			Generic::BoundFunctorV *cancelclient=ch.addCleanupCall(Generic::BindObjN(client, &Tn::TFileBySyncDev::invokeConnectionLost), true);
			client.open(IO_ReadWrite);
			char buffer[65536];
			FXuval read=0, justread;
			FXuint before=FXProcess::getMsCount();
			do
			{
				read+=justread=client.readBlock(buffer, 65536);
			} while(justread);
			FXuint after=FXProcess::getMsCount();
			fxmessage("Read through TFileBySyncDev at %fKb/sec\n", (1000.0*read/(after-before))/1024);
			fxmessage("*** Moving to 4096\n");
			client.at(round);
			before=FXProcess::getMsCount();
			for(FXuint n=0; n<read/65536; n++)
			{
				client.writeBlock(buffer, 65536);
			}
			fxmessage("*** Flushing output\n");
			client.flush();
			//fxmessage("*** Synchronising\n");
			//client.at(0);
			//client.readBlock(buffer, 1);
			after=FXProcess::getMsCount();
			fxmessage("Wrote through TFileBySyncDev at %fKb/sec\n", (1000.0*read/(after-before))/1024);
			client.close();
			ch.requestClose();
			ch.wait();
			ch.removeCleanupCall(cancelclient);
		}
	}
	FXERRH_CATCH(FXException &e)
	{
		fxmessage("\n\nException %s\n", e.report().text());
		ch.requestClose();
		ch.wait();
		return 1;
	}
	FXERRH_ENDTRY;

	printf("\n\nTests complete!\n");
#ifdef WIN32
	getchar();
#endif
	return 0;
}
<|endoftext|>


<commit_before>
// ProxyPlayer.hpp
// This will invoke another process and waits for a return code.

#ifndef __PROXY_PLAYER_HPP__
#define __PROXY_PLAYER_HPP__

#include "Player.hpp"
#include <string>
#include <sstream>

#ifdef _WIN32
#undef UNICODE
<<<<<<< HEAD
#define NOMINMAX
#include <Windows.h>
<<<<<<< HEAD
||||||| parent of 6bf7a07... Fix ProxyPlayer.hpp for MinGW compilation
#define NOMINMAX
#include <Windows.h>
#define EXE_SUFFIX ".exe"
#else
#include <cstdlib>
#define EXE_SUFFIX ""
#endif
=======
#ifdef NOMINMAX
#undef NOMINMAX
#endif
#define NOMINMAX 1
#include <windows.h>
#define EXE_SUFFIX ".exe"
#else
#include <cstdlib>
#define EXE_SUFFIX ""
#endif
>>>>>>> 6bf7a07... Fix ProxyPlayer.hpp for MinGW compilation
||||||| parent of 36eb91b... Platform-agnostic implementation of ProxyPlayer (using system)
=======
#define EXE_SUFFIX ".exe"
#else
#include <cstdlib>
#define EXE_SUFFIX ""
#endif
>>>>>>> 36eb91b... Platform-agnostic implementation of ProxyPlayer (using system)

class ProxyPlayer : public Player
{
public:
	// Initialize with process (without .exe) and identifier of opponent.
	ProxyPlayer(std::string const &process, std::string const &script = "", size_t opponent = -1)
		: mProcess(process), mScript(script), Player(opponent) {}

public:
	// Invoke other process.
	virtual Action fight()
	{
		DWORD choice = executeWithArguments(getArguments(3));
		switch (choice)
		{
		case 48: return load();
		case 49: return bullet();
		case 50: return plasma();
		case 45: return metal();
		case 61: return thermal();
		default: return (Action)(-1);
		}
	}

	// Notify external program of result.
	virtual void declared(Result result)
	{
		std::string arguments;
		switch (result)
		{
		case WIN:  arguments = getArguments(1);
		case LOSS: arguments = getArguments(2);
		default:   arguments = getArguments(0);
		}
		executeWithArguments(arguments);
	};

private:
	// External process name
	std::string mProcess;

	// External script name (for non binary submissions)
	std::string mScript;

	// Generates argument given game status.
	std::string getArguments(size_t status)
	{
		std::stringstream sst;
		sst << getOpponent()
			<< " " << getTurn()
			<< " " << status
			<< " " << getAmmo()
			<< " " << getAmmoOpponent();
		if (getTurn() > 0)
		{
			sst << " " << toActionString(getHistory())
				<< " " << toActionString(getHistoryOpponent());
		};
		return sst.str();
	}

	// Execute process with given arguments.
	DWORD executeWithArguments(std::string const &arguments) const
	{
#ifdef _WIN32
		STARTUPINFO startup = { sizeof(startup) };
		PROCESS_INFORMATION process;
		LPSTR lpApplicationName;
		LPSTR lpCommandLine;

		lpApplicationName = const_cast<char *>(mProcess.c_str());
		if (mScript.length() == 0)
		{
			// Binary Proxy Player
			// name.exe arguments
			lpCommandLine = const_cast<char *>(arguments.c_str());
		}
		else
		{
			// Script Proxy Player
			// python.exe script.py arguments
			std::string actualArguments = mScript;
			actualArguments.append(1, ' ');
			actualArguments.append(arguments);
		}

		startup.cb = sizeof(startup);
		BOOL result = CreateProcess(lpApplicationName, lpCommandLine,
			NULL, NULL, TRUE, 0, NULL, NULL, &startup, &process);

		if (!result)
		{
			return -1;
		}
		else
		{
			// Wait for process to terminate and sanitize return code.
			DWORD exitCode;
			WaitForSingleObject(process.hProcess, INFINITE);
			GetExitCodeProcess(process.hProcess, &exitCode);
			return exitCode;
		}
#else
		return std::system((mProcess + " " + mScript + " " + arguments).c_str());
#endif
	}
};

#define STRINGIFY(x) #x

// Example: BINARY_PLAYER(CustomPlayer)
// Effects: Invoke CustomPlayer.exe <arguments>
#define BINARY_PLAYER(x)                                              \
	class x final : public ProxyPlayer                                \
	{                                                                 \
	public:                                                           \
	    x(size_t opponent = -1) : ProxyPlayer(#x EXE_SUFFIX, opponent) {} \
	};

// Example: SCRIPT_PLAYER(CustomPlayer, "python", "CustomScriptPlayer.py")
// Effects: Invoke python CustomScriptPlayer.py <arguments>
#define SCRIPT_PLAYER(x, y, z)                                        \
	class x final : public ProxyPlayer                                \
	{                                                                 \
	public:                                                           \
		x(size_t opponent = -1) : ProxyPlayer(y, z, opponent) {}      \
	};

#endif // !__CUSTOM_PLAYER_HPP__
<commit_msg>Use platform-agnostic value for exit code<commit_after>
// ProxyPlayer.hpp
// This will invoke another process and waits for a return code.

#ifndef __PROXY_PLAYER_HPP__
#define __PROXY_PLAYER_HPP__

#include "Player.hpp"
#include <string>
#include <sstream>

#ifdef _WIN32
#undef UNICODE
<<<<<<< HEAD
#define NOMINMAX
#include <Windows.h>
<<<<<<< HEAD
||||||| parent of 6bf7a07... Fix ProxyPlayer.hpp for MinGW compilation
#define NOMINMAX
#include <Windows.h>
#define EXE_SUFFIX ".exe"
#else
#include <cstdlib>
#define EXE_SUFFIX ""
#endif
=======
#ifdef NOMINMAX
#undef NOMINMAX
#endif
#define NOMINMAX 1
#include <windows.h>
#define EXE_SUFFIX ".exe"
#else
#include <cstdlib>
#define EXE_SUFFIX ""
#endif
>>>>>>> 6bf7a07... Fix ProxyPlayer.hpp for MinGW compilation
||||||| parent of 36eb91b... Platform-agnostic implementation of ProxyPlayer (using system)
=======
#define EXE_SUFFIX ".exe"
#else
#include <cstdlib>
#define EXE_SUFFIX ""
#endif
>>>>>>> 36eb91b... Platform-agnostic implementation of ProxyPlayer (using system)

class ProxyPlayer : public Player
{
public:
	// Initialize with process (without .exe) and identifier of opponent.
	ProxyPlayer(std::string const &process, std::string const &script = "", size_t opponent = -1)
		: mProcess(process), mScript(script), Player(opponent) {}

public:
	// Invoke other process.
	virtual Action fight()
	{
		unsigned choice = executeWithArguments(getArguments(3));
		switch (choice)
		{
		case 48: return load();
		case 49: return bullet();
		case 50: return plasma();
		case 45: return metal();
		case 61: return thermal();
		default: return (Action)(-1);
		}
	}

	// Notify external program of result.
	virtual void declared(Result result)
	{
		std::string arguments;
		switch (result)
		{
		case WIN:  arguments = getArguments(1);
		case LOSS: arguments = getArguments(2);
		default:   arguments = getArguments(0);
		}
		executeWithArguments(arguments);
	};

private:
	// External process name
	std::string mProcess;

	// External script name (for non binary submissions)
	std::string mScript;

	// Generates argument given game status.
	std::string getArguments(size_t status)
	{
		std::stringstream sst;
		sst << getOpponent()
			<< " " << getTurn()
			<< " " << status
			<< " " << getAmmo()
			<< " " << getAmmoOpponent();
		if (getTurn() > 0)
		{
			sst << " " << toActionString(getHistory())
				<< " " << toActionString(getHistoryOpponent());
		};
		return sst.str();
	}

	// Execute process with given arguments.
	unsigned executeWithArguments(std::string const &arguments) const
	{
#ifdef _WIN32
		STARTUPINFO startup = { sizeof(startup) };
		PROCESS_INFORMATION process;
		LPSTR lpApplicationName;
		LPSTR lpCommandLine;

		lpApplicationName = const_cast<char *>(mProcess.c_str());
		if (mScript.length() == 0)
		{
			// Binary Proxy Player
			// name.exe arguments
			lpCommandLine = const_cast<char *>(arguments.c_str());
		}
		else
		{
			// Script Proxy Player
			// python.exe script.py arguments
			std::string actualArguments = mScript;
			actualArguments.append(1, ' ');
			actualArguments.append(arguments);
		}

		startup.cb = sizeof(startup);
		BOOL result = CreateProcess(lpApplicationName, lpCommandLine,
			NULL, NULL, TRUE, 0, NULL, NULL, &startup, &process);

		if (!result)
		{
			return -1;
		}
		else
		{
			// Wait for process to terminate and sanitize return code.
			DWORD exitCode;
			WaitForSingleObject(process.hProcess, INFINITE);
			GetExitCodeProcess(process.hProcess, &exitCode);
			return exitCode;
		}
#else
		return std::system((mProcess + " " + mScript + " " + arguments).c_str());
#endif
	}
};

#define STRINGIFY(x) #x

// Example: BINARY_PLAYER(CustomPlayer)
// Effects: Invoke CustomPlayer.exe <arguments>
#define BINARY_PLAYER(x)                                              \
	class x final : public ProxyPlayer                                \
	{                                                                 \
	public:                                                           \
	    x(size_t opponent = -1) : ProxyPlayer(#x EXE_SUFFIX, opponent) {} \
	};

// Example: SCRIPT_PLAYER(CustomPlayer, "python", "CustomScriptPlayer.py")
// Effects: Invoke python CustomScriptPlayer.py <arguments>
#define SCRIPT_PLAYER(x, y, z)                                        \
	class x final : public ProxyPlayer                                \
	{                                                                 \
	public:                                                           \
		x(size_t opponent = -1) : ProxyPlayer(y, z, opponent) {}      \
	};

#endif // !__CUSTOM_PLAYER_HPP__
<|endoftext|>