<commit_before>#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/contrib/contrib.hpp>

#include <iostream>

using namespace cv;
using namespace std;

void help()
{
	cout <<
			"\nThis program demonstrates chamfer matching -- computing a distance between an \n"
			"edge template and a query edge image.\n"
			"Call:\n"
			"./chamfermatching [<image edge map> <template edge map>]\n"
			"By default\n"
			"the inputs are ./chamfermatching logo_in_clutter.png logo.png\n"<< endl;
}
int main( int argc, char** argv )
{
    if( argc != 1 && argc != 3 )
    {
        help();
        return 0;
    }
    Mat img = imread(argc == 3 ? argv[1] : "logo_in_clutter.png", 0);
    Mat cimg;
    cvtColor(img, cimg, CV_GRAY2BGR);
    Mat tpl = imread(argc == 3 ? argv[2] : "logo.png", 0);

    // if the image and the template are not edge maps but normal grayscale images,
    // you might want to uncomment the lines below to produce the maps. You can also
    // run Sobel instead of Canny.

    // Canny(img, img, 5, 50, 3);
    // Canny(tpl, tpl, 5, 50, 3);

    vector<vector<Point> > results;
    vector<float> costs;
    int best = chamerMatching( img, tpl, results, costs );
    if( best < 0 )
    {
        cout << "not found;\n";
        return 0;
    }

    size_t i, n = results[best].size();
    for( i = 0; i < n; i++ )
    {
        Point pt = results[best][i];
        if( pt.inside(Rect(0, 0, cimg.cols, cimg.rows)) )
           cimg.at<Vec3b>(pt) = Vec3b(0, 255, 0);
    }
    imshow("result", cimg);
    waitKey();
    return 0;
}
<commit_msg>oops, typo corrected<commit_after>#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/contrib/contrib.hpp>

#include <iostream>

using namespace cv;
using namespace std;

void help()
{
	cout <<
			"\nThis program demonstrates chamfer matching -- computing a distance between an \n"
			"edge template and a query edge image.\n"
			"Call:\n"
			"./chamfer [<image edge map> <template edge map>]\n"
			"By default\n"
			"the inputs are ./chamfer logo_in_clutter.png logo.png\n"<< endl;
}
int main( int argc, char** argv )
{
    if( argc != 1 && argc != 3 )
    {
        help();
        return 0;
    }
    Mat img = imread(argc == 3 ? argv[1] : "logo_in_clutter.png", 0);
    Mat cimg;
    cvtColor(img, cimg, CV_GRAY2BGR);
    Mat tpl = imread(argc == 3 ? argv[2] : "logo.png", 0);

    // if the image and the template are not edge maps but normal grayscale images,
    // you might want to uncomment the lines below to produce the maps. You can also
    // run Sobel instead of Canny.

    // Canny(img, img, 5, 50, 3);
    // Canny(tpl, tpl, 5, 50, 3);

    vector<vector<Point> > results;
    vector<float> costs;
    int best = chamerMatching( img, tpl, results, costs );
    if( best < 0 )
    {
        cout << "not found;\n";
        return 0;
    }

    size_t i, n = results[best].size();
    for( i = 0; i < n; i++ )
    {
        Point pt = results[best][i];
        if( pt.inside(Rect(0, 0, cimg.cols, cimg.rows)) )
           cimg.at<Vec3b>(pt) = Vec3b(0, 255, 0);
    }
    imshow("result", cimg);
    waitKey();
    return 0;
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2009, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#ifndef TORRENT_I2P_STREAM_HPP_INCLUDED
#define TORRENT_I2P_STREAM_HPP_INCLUDED

#include "libtorrent/config.hpp"

#if TORRENT_USE_I2P

#include <list>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
#include <boost/bind.hpp>
#include "libtorrent/proxy_base.hpp"
#include "libtorrent/session_settings.hpp"

namespace libtorrent {

	namespace i2p_error {

		enum i2p_error_code
		{
			no_error = 0,
			parse_failed,
			cant_reach_peer,
			i2p_error,
			invalid_key,
			invalid_id,
			timeout,
			key_not_found,
			num_errors
		};
	}

struct TORRENT_EXPORT i2p_error_category : boost::system::error_category
{
	virtual const char* name() const;
	virtual std::string message(int ev) const;
	virtual boost::system::error_condition default_error_condition(int ev) const
	{ return boost::system::error_condition(ev, *this); }
};

extern i2p_error_category i2p_category;

class i2p_stream : public proxy_base
{
public:

	explicit i2p_stream(io_service& io_service)
		: proxy_base(io_service)
		, m_id(0)
		, m_command(cmd_create_session)
		, m_state(0)
	{}

	enum command_t
	{
		cmd_none,
		cmd_create_session,
		cmd_connect,
		cmd_accept,
		cmd_name_lookup,
		cmd_incoming
	};

	void set_command(command_t c) { m_command = c; }

	void set_session_id(char const* id) { m_id = id; }

	void set_destination(std::string const& d) { m_dest = d; }
	std::string const& destination() { return m_dest; }

	typedef boost::function<void(error_code const&)> handler_type;

	template <class Handler>
	void async_connect(endpoint_type const& endpoint, Handler const& handler)
	{
		// since we don't support regular endpoints, just ignore the one
		// provided and use m_dest.

		// the connect is split up in the following steps:
		// 1. resolve name of proxy server
		// 2. connect to SAM bridge
		// 4 send command message (CONNECT/ACCEPT)

		// to avoid unnecessary copying of the handler,
		// store it in a shaed_ptr
		boost::shared_ptr<handler_type> h(new handler_type(handler));

		tcp::resolver::query q(m_hostname, to_string(m_port).elems);
		m_resolver.async_resolve(q, boost::bind(
			&i2p_stream::do_connect, this, _1, _2, h));
	}

	std::string name_lookup() const { return m_name_lookup; }
	void set_name_lookup(char const* name) { m_name_lookup = name; }

	void send_name_lookup(boost::shared_ptr<handler_type> h);

private:

	bool handle_error(error_code const& e, boost::shared_ptr<handler_type> const& h);
	void do_connect(error_code const& e, tcp::resolver::iterator i
		, boost::shared_ptr<handler_type> h);
	void connected(error_code const& e, boost::shared_ptr<handler_type> h);
	void start_read_line(error_code const& e, boost::shared_ptr<handler_type> h);
	void read_line(error_code const& e, boost::shared_ptr<handler_type> h);
	void send_connect(boost::shared_ptr<handler_type> h);
	void send_accept(boost::shared_ptr<handler_type> h);
	void send_session_create(boost::shared_ptr<handler_type> h);

	// send and receive buffer
	std::vector<char> m_buffer;
	char const* m_id;
	int m_command; // 0 = connect, 1 = accept
	std::string m_dest;
	std::string m_name_lookup;

	enum state_t
	{
		read_hello_response,
		read_connect_response,
		read_accept_response,
		read_session_create_response,
		read_name_lookup_response
	};

	int m_state;
};

class i2p_connection
{
public:
	i2p_connection(io_service& ios);
	~i2p_connection();

	proxy_settings const& proxy() const { return m_sam_router; }

	bool is_open() const
	{
		return m_sam_socket
			&& m_sam_socket->is_open()
			&& m_state != sam_connecting;
	}
	void open(proxy_settings const& s, i2p_stream::handler_type const& h);
	void close(error_code&);

	char const* session_id() const { return m_session_id.c_str(); }
	std::string const& local_endpoint() const { return m_i2p_local_endpoint; }

	typedef boost::function<void(error_code const&, char const*)> name_lookup_handler;
	void async_name_lookup(char const* name, name_lookup_handler handler);

private:

	void on_sam_connect(error_code const& ec, i2p_stream::handler_type const& h);
	void do_name_lookup(std::string const& name
		, name_lookup_handler const& h);
	void on_name_lookup(error_code const& ec
		, name_lookup_handler handler);

	void set_local_endpoint(error_code const& ec, char const* dest);

	// to talk to i2p SAM bridge
	boost::shared_ptr<i2p_stream> m_sam_socket;
	proxy_settings m_sam_router;

	// our i2p endpoint key
	std::string m_i2p_local_endpoint;
	std::string m_session_id;

	std::list<std::pair<std::string, name_lookup_handler> > m_name_lookup;

	enum state_t
	{
		sam_connecting,
		sam_name_lookup,
		sam_idle
	};

	state_t m_state;

	io_service& m_io_service;
};

}
#endif // TORRENT_USE_I2P

#endif

<commit_msg>some more missing includes<commit_after>/*

Copyright (c) 2009, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#ifndef TORRENT_I2P_STREAM_HPP_INCLUDED
#define TORRENT_I2P_STREAM_HPP_INCLUDED

#include "libtorrent/config.hpp"

#if TORRENT_USE_I2P

#include <list>
#include <string>
#include <vector>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include "libtorrent/proxy_base.hpp"
#include "libtorrent/session_settings.hpp"

namespace libtorrent {

	namespace i2p_error {

		enum i2p_error_code
		{
			no_error = 0,
			parse_failed,
			cant_reach_peer,
			i2p_error,
			invalid_key,
			invalid_id,
			timeout,
			key_not_found,
			num_errors
		};
	}

struct TORRENT_EXPORT i2p_error_category : boost::system::error_category
{
	virtual const char* name() const;
	virtual std::string message(int ev) const;
	virtual boost::system::error_condition default_error_condition(int ev) const
	{ return boost::system::error_condition(ev, *this); }
};

extern i2p_error_category i2p_category;

class i2p_stream : public proxy_base
{
public:

	explicit i2p_stream(io_service& io_service)
		: proxy_base(io_service)
		, m_id(0)
		, m_command(cmd_create_session)
		, m_state(0)
	{}

	enum command_t
	{
		cmd_none,
		cmd_create_session,
		cmd_connect,
		cmd_accept,
		cmd_name_lookup,
		cmd_incoming
	};

	void set_command(command_t c) { m_command = c; }

	void set_session_id(char const* id) { m_id = id; }

	void set_destination(std::string const& d) { m_dest = d; }
	std::string const& destination() { return m_dest; }

	typedef boost::function<void(error_code const&)> handler_type;

	template <class Handler>
	void async_connect(endpoint_type const& endpoint, Handler const& handler)
	{
		// since we don't support regular endpoints, just ignore the one
		// provided and use m_dest.

		// the connect is split up in the following steps:
		// 1. resolve name of proxy server
		// 2. connect to SAM bridge
		// 4 send command message (CONNECT/ACCEPT)

		// to avoid unnecessary copying of the handler,
		// store it in a shaed_ptr
		boost::shared_ptr<handler_type> h(new handler_type(handler));

		tcp::resolver::query q(m_hostname, to_string(m_port).elems);
		m_resolver.async_resolve(q, boost::bind(
			&i2p_stream::do_connect, this, _1, _2, h));
	}

	std::string name_lookup() const { return m_name_lookup; }
	void set_name_lookup(char const* name) { m_name_lookup = name; }

	void send_name_lookup(boost::shared_ptr<handler_type> h);

private:

	bool handle_error(error_code const& e, boost::shared_ptr<handler_type> const& h);
	void do_connect(error_code const& e, tcp::resolver::iterator i
		, boost::shared_ptr<handler_type> h);
	void connected(error_code const& e, boost::shared_ptr<handler_type> h);
	void start_read_line(error_code const& e, boost::shared_ptr<handler_type> h);
	void read_line(error_code const& e, boost::shared_ptr<handler_type> h);
	void send_connect(boost::shared_ptr<handler_type> h);
	void send_accept(boost::shared_ptr<handler_type> h);
	void send_session_create(boost::shared_ptr<handler_type> h);

	// send and receive buffer
	std::vector<char> m_buffer;
	char const* m_id;
	int m_command; // 0 = connect, 1 = accept
	std::string m_dest;
	std::string m_name_lookup;

	enum state_t
	{
		read_hello_response,
		read_connect_response,
		read_accept_response,
		read_session_create_response,
		read_name_lookup_response
	};

	int m_state;
};

class i2p_connection
{
public:
	i2p_connection(io_service& ios);
	~i2p_connection();

	proxy_settings const& proxy() const { return m_sam_router; }

	bool is_open() const
	{
		return m_sam_socket
			&& m_sam_socket->is_open()
			&& m_state != sam_connecting;
	}
	void open(proxy_settings const& s, i2p_stream::handler_type const& h);
	void close(error_code&);

	char const* session_id() const { return m_session_id.c_str(); }
	std::string const& local_endpoint() const { return m_i2p_local_endpoint; }

	typedef boost::function<void(error_code const&, char const*)> name_lookup_handler;
	void async_name_lookup(char const* name, name_lookup_handler handler);

private:

	void on_sam_connect(error_code const& ec, i2p_stream::handler_type const& h);
	void do_name_lookup(std::string const& name
		, name_lookup_handler const& h);
	void on_name_lookup(error_code const& ec
		, name_lookup_handler handler);

	void set_local_endpoint(error_code const& ec, char const* dest);

	// to talk to i2p SAM bridge
	boost::shared_ptr<i2p_stream> m_sam_socket;
	proxy_settings m_sam_router;

	// our i2p endpoint key
	std::string m_i2p_local_endpoint;
	std::string m_session_id;

	std::list<std::pair<std::string, name_lookup_handler> > m_name_lookup;

	enum state_t
	{
		sam_connecting,
		sam_name_lookup,
		sam_idle
	};

	state_t m_state;

	io_service& m_io_service;
};

}
#endif // TORRENT_USE_I2P

#endif

<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#ifndef TORRENT_PROXY_BASE_HPP_INCLUDED
#define TORRENT_PROXY_BASE_HPP_INCLUDED

#include "libtorrent/io.hpp"
#include "libtorrent/socket.hpp"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp>
#include <asio/read.hpp>
#include <asio/write.hpp>

namespace libtorrent {

class proxy_base : boost::noncopyable
{
public:

	typedef stream_socket::lowest_layer_type lowest_layer_type;
	typedef stream_socket::endpoint_type endpoint_type;
	typedef stream_socket::protocol_type protocol_type;

	explicit proxy_base(asio::io_service& io_service)
		: m_sock(io_service)
		, m_resolver(io_service)
	{}

	void set_proxy(std::string hostname, int port)
	{
		m_hostname = hostname;
		m_port = port;
	}

	template <class Mutable_Buffers, class Handler>
	void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_read_some(buffers, handler);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
	{
		return m_sock.read_some(buffers, ec);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers)
	{
		return m_sock.read_some(buffers);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc)
	{
		m_sock.io_control(ioc);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc, asio::error_code& ec)
	{
		m_sock.io_control(ioc, ec);
	}

	template <class Const_Buffers, class Handler>
	void async_write_some(Const_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_write_some(buffers, handler);
	}

	void bind(endpoint_type const& endpoint)
	{
		m_sock.bind(endpoint);
	}

	template <class Error_Handler>
	void bind(endpoint_type const& endpoint, Error_Handler const& error_handler)
	{
		m_sock.bind(endpoint, error_handler);
	}

	void open(protocol_type const& p)
	{
		m_sock.open(p);
	}

	template <class Error_Handler>
	void open(protocol_type const& p, Error_Handler const& error_handler)
	{
		m_sock.open(p, error_handler);
	}

	void close()
	{
		m_remote_endpoint = endpoint_type();
		m_sock.close();
	}

	template <class Error_Handler>
	void close(Error_Handler const& error_handler)
	{
		m_sock.close(error_handler);
	}

	endpoint_type remote_endpoint()
	{
		return m_remote_endpoint;
	}

	template <class Error_Handler>
	endpoint_type remote_endpoint(Error_Handler const& error_handler)
	{
		return m_remote_endpoint;
	}

	endpoint_type local_endpoint()
	{
		return m_sock.local_endpoint();
	}

	template <class Error_Handler>
	endpoint_type local_endpoint(Error_Handler const& error_handler)
	{
		return m_sock.local_endpoint(error_handler);
	}

	asio::io_service& io_service()
	{
		return m_sock.io_service();
	}

	lowest_layer_type& lowest_layer()
	{
		return m_sock.lowest_layer();
	}

protected:

	stream_socket m_sock;
	std::string m_hostname;
	int m_port;

	endpoint_type m_remote_endpoint;

	tcp::resolver m_resolver;
};

}

#endif

<commit_msg>cleaned up unnecessary template functions<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#ifndef TORRENT_PROXY_BASE_HPP_INCLUDED
#define TORRENT_PROXY_BASE_HPP_INCLUDED

#include "libtorrent/io.hpp"
#include "libtorrent/socket.hpp"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp>
#include <asio/read.hpp>
#include <asio/write.hpp>

namespace libtorrent {

class proxy_base : boost::noncopyable
{
public:

	typedef stream_socket::lowest_layer_type lowest_layer_type;
	typedef stream_socket::endpoint_type endpoint_type;
	typedef stream_socket::protocol_type protocol_type;

	explicit proxy_base(asio::io_service& io_service)
		: m_sock(io_service)
		, m_resolver(io_service)
	{}

	void set_proxy(std::string hostname, int port)
	{
		m_hostname = hostname;
		m_port = port;
	}

	template <class Mutable_Buffers, class Handler>
	void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_read_some(buffers, handler);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec)
	{
		return m_sock.read_some(buffers, ec);
	}

	template <class Mutable_Buffers>
	std::size_t read_some(Mutable_Buffers const& buffers)
	{
		return m_sock.read_some(buffers);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc)
	{
		m_sock.io_control(ioc);
	}

	template <class IO_Control_Command>
	void io_control(IO_Control_Command& ioc, asio::error_code& ec)
	{
		m_sock.io_control(ioc, ec);
	}

	template <class Const_Buffers, class Handler>
	void async_write_some(Const_Buffers const& buffers, Handler const& handler)
	{
		m_sock.async_write_some(buffers, handler);
	}

	void bind(endpoint_type const& endpoint)
	{
		m_sock.bind(endpoint);
	}

	void bind(endpoint_type const& endpoint, asio::error_code& ec)
	{
		m_sock.bind(endpoint, ec);
	}

	void open(protocol_type const& p)
	{
		m_sock.open(p);
	}

	void open(protocol_type const& p, asio::error_code& ec)
	{
		m_sock.open(p, ec);
	}

	void close()
	{
		m_remote_endpoint = endpoint_type();
		m_sock.close();
	}

	void close(asio::error_code& ec)
	{
		m_sock.close(ec);
	}

	endpoint_type remote_endpoint()
	{
		return m_remote_endpoint;
	}

	endpoint_type remote_endpoint(asio::error_code& ec)
	{
		return m_remote_endpoint;
	}

	endpoint_type local_endpoint()
	{
		return m_sock.local_endpoint();
	}

	endpoint_type local_endpoint(asio::error_code& ec)
	{
		return m_sock.local_endpoint(ec);
	}

	asio::io_service& io_service()
	{
		return m_sock.io_service();
	}

	lowest_layer_type& lowest_layer()
	{
		return m_sock.lowest_layer();
	}

protected:

	stream_socket m_sock;
	std::string m_hostname;
	int m_port;

	endpoint_type m_remote_endpoint;

	tcp::resolver m_resolver;
};

}

#endif

<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#ifndef TORRENT_UDP_SOCKET_HPP_INCLUDED
#define TORRENT_UDP_SOCKET_HPP_INCLUDED

#include "libtorrent/socket.hpp"
#include "libtorrent/io_service.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/buffer.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/deadline_timer.hpp"

#include <deque>
#include <boost/function/function4.hpp>

namespace libtorrent
{
	class connection_queue;

	class udp_socket
	{
	public:
		// TODO: instead of these callbacks, support observers
		typedef boost::function<void(error_code const& ec
			, udp::endpoint const&, char const* buf, int size)> callback_t;
		typedef boost::function<void(error_code const& ec
			, char const*, char const* buf, int size)> callback2_t;
		typedef boost::function<void()> drain_callback_t;

		udp_socket(io_service& ios, callback_t const& c, callback2_t const& c2
			, drain_callback_t const& dc, connection_queue& cc);
		~udp_socket();

		enum flags_t { dont_drop = 1, peer_connection = 2 };

		bool is_open() const
		{
			return m_ipv4_sock.is_open()
#if TORRENT_USE_IPV6
				|| m_ipv6_sock.is_open()
#endif
				;
		}
		io_service& get_io_service() { return m_ipv4_sock.get_io_service(); }

		// this is only valid when using a socks5 proxy
		void send_hostname(char const* hostname, int port, char const* p, int len, error_code& ec);

		void send(udp::endpoint const& ep, char const* p, int len, error_code& ec, int flags = 0);
		void bind(udp::endpoint const& ep, error_code& ec);
		void bind(int port);
		void close();
		int local_port() const { return m_bind_port; }

		void set_proxy_settings(proxy_settings const& ps);
		proxy_settings const& get_proxy_settings() { return m_proxy_settings; }

		bool is_closed() const { return m_abort; }
		tcp::endpoint local_endpoint(error_code& ec) const
		{
			udp::endpoint ep = m_ipv4_sock.local_endpoint(ec);
			return tcp::endpoint(ep.address(), ep.port());
		}

		void set_buf_size(int s);

		template <class SocketOption>
		void set_option(SocketOption const& opt, error_code& ec)
		{
			m_ipv4_sock.set_option(opt, ec);
#if TORRENT_USE_IPV6
			m_ipv6_sock.set_option(opt, ec);
#endif
		}

		template <class SocketOption>
		void get_option(SocketOption& opt, error_code& ec)
		{
			m_ipv4_sock.get_option(opt, ec);
		}

		udp::endpoint proxy_addr() const { return m_proxy_addr; }

	protected:

		struct queued_packet
		{
			udp::endpoint ep;
			char* hostname;
			buffer buf;
			int flags;
		};

		// number of outstanding UDP socket operations
		// using the UDP socket buffer
		int num_outstanding() const
		{
			return m_v4_outstanding
#if TORRENT_USE_IPV6
			  	+ m_v6_outstanding
#endif
				;
		}

	private:
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
	// necessary for logging member offsets
	public:
#endif

		// callback for regular incoming packets
		callback_t m_callback;

		// callback for proxied incoming packets with a domain
		// name as source
		callback2_t m_callback2;

		// called every time we drain the udp sockets
		drain_callback_t m_drained_callback;

		void setup_read(udp::socket* s);
		void on_read(udp::socket* s);
		void on_read_impl(udp::socket* sock, udp::endpoint const& ep
			, error_code const& e, std::size_t bytes_transferred);
		void on_name_lookup(error_code const& e, tcp::resolver::iterator i);
		void on_timeout();
		void on_connect(int ticket);
		void on_connected(error_code const& ec);
		void handshake1(error_code const& e);
		void handshake2(error_code const& e);
		void handshake3(error_code const& e);
		void handshake4(error_code const& e);
		void socks_forward_udp();
		void connect1(error_code const& e);
		void connect2(error_code const& e);
		void hung_up(error_code const& e);

		void wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec);
		void wrap(char const* hostname, int port, char const* p, int len, error_code& ec);
		void unwrap(error_code const& e, char const* buf, int size);

		bool maybe_clear_callback();

#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
#if defined BOOST_HAS_PTHREADS
		mutable pthread_t m_thread;
#endif
		bool is_single_thread() const
		{
#if defined BOOST_HAS_PTHREADS
			if (m_thread == 0)
				m_thread = pthread_self();
			return m_thread == pthread_self();
#endif
			return true;
		}
#endif

		udp::socket m_ipv4_sock;
		int m_buf_size;
		char* m_buf;

#if TORRENT_USE_IPV6
		udp::socket m_ipv6_sock;
#endif

		boost::uint16_t m_bind_port;
		boost::uint8_t m_v4_outstanding;
#if TORRENT_USE_IPV6
		boost::uint8_t m_v6_outstanding;
#endif

		tcp::socket m_socks5_sock;
		int m_connection_ticket;
		proxy_settings m_proxy_settings;
		connection_queue& m_cc;
		tcp::resolver m_resolver;
		char m_tmp_buf[270];
		bool m_queue_packets;
		bool m_tunnel_packets;
		bool m_abort;
		udp::endpoint m_proxy_addr;
		// while we're connecting to the proxy
		// we have to queue the packets, we'll flush
		// them once we're connected
		std::deque<queued_packet> m_queue;

		// counts the number of outstanding async
		// operations hanging on this socket
		int m_outstanding_ops;

#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
		bool m_started;
		int m_magic;
		int m_outstanding_when_aborted;
#endif
	};

	struct rate_limited_udp_socket : public udp_socket
	{
		rate_limited_udp_socket(io_service& ios, callback_t const& c
			, callback2_t const& c2, drain_callback_t const& dc, connection_queue& cc);
		void set_rate_limit(int limit) { m_rate_limit = limit; }
		bool can_send() const { return int(m_queue.size()) >= m_queue_size_limit; }
		bool send(udp::endpoint const& ep, char const* p, int len, error_code& ec, int flags = 0);
		void close();

	private:
		void on_tick(error_code const& e);

		deadline_timer m_timer;
		int m_queue_size_limit;
		int m_rate_limit;
		int m_quota;
		ptime m_last_tick;
		std::deque<queued_packet> m_queue;
	};
}

#endif

<commit_msg>fix build issue<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#ifndef TORRENT_UDP_SOCKET_HPP_INCLUDED
#define TORRENT_UDP_SOCKET_HPP_INCLUDED

#include "libtorrent/socket.hpp"
#include "libtorrent/io_service.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/buffer.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/deadline_timer.hpp"

#include <deque>
#include <boost/function/function4.hpp>
#include <boost/function/function0.hpp>

namespace libtorrent
{
	class connection_queue;

	class udp_socket
	{
	public:
		// TODO: instead of these callbacks, support observers
		typedef boost::function<void(error_code const& ec
			, udp::endpoint const&, char const* buf, int size)> callback_t;
		typedef boost::function<void(error_code const& ec
			, char const*, char const* buf, int size)> callback2_t;
		typedef boost::function<void()> drain_callback_t;

		udp_socket(io_service& ios, callback_t const& c, callback2_t const& c2
			, drain_callback_t const& dc, connection_queue& cc);
		~udp_socket();

		enum flags_t { dont_drop = 1, peer_connection = 2 };

		bool is_open() const
		{
			return m_ipv4_sock.is_open()
#if TORRENT_USE_IPV6
				|| m_ipv6_sock.is_open()
#endif
				;
		}
		io_service& get_io_service() { return m_ipv4_sock.get_io_service(); }

		// this is only valid when using a socks5 proxy
		void send_hostname(char const* hostname, int port, char const* p, int len, error_code& ec);

		void send(udp::endpoint const& ep, char const* p, int len, error_code& ec, int flags = 0);
		void bind(udp::endpoint const& ep, error_code& ec);
		void bind(int port);
		void close();
		int local_port() const { return m_bind_port; }

		void set_proxy_settings(proxy_settings const& ps);
		proxy_settings const& get_proxy_settings() { return m_proxy_settings; }

		bool is_closed() const { return m_abort; }
		tcp::endpoint local_endpoint(error_code& ec) const
		{
			udp::endpoint ep = m_ipv4_sock.local_endpoint(ec);
			return tcp::endpoint(ep.address(), ep.port());
		}

		void set_buf_size(int s);

		template <class SocketOption>
		void set_option(SocketOption const& opt, error_code& ec)
		{
			m_ipv4_sock.set_option(opt, ec);
#if TORRENT_USE_IPV6
			m_ipv6_sock.set_option(opt, ec);
#endif
		}

		template <class SocketOption>
		void get_option(SocketOption& opt, error_code& ec)
		{
			m_ipv4_sock.get_option(opt, ec);
		}

		udp::endpoint proxy_addr() const { return m_proxy_addr; }

	protected:

		struct queued_packet
		{
			udp::endpoint ep;
			char* hostname;
			buffer buf;
			int flags;
		};

		// number of outstanding UDP socket operations
		// using the UDP socket buffer
		int num_outstanding() const
		{
			return m_v4_outstanding
#if TORRENT_USE_IPV6
			  	+ m_v6_outstanding
#endif
				;
		}

	private:
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
	// necessary for logging member offsets
	public:
#endif

		// callback for regular incoming packets
		callback_t m_callback;

		// callback for proxied incoming packets with a domain
		// name as source
		callback2_t m_callback2;

		// called every time we drain the udp sockets
		drain_callback_t m_drained_callback;

		void setup_read(udp::socket* s);
		void on_read(udp::socket* s);
		void on_read_impl(udp::socket* sock, udp::endpoint const& ep
			, error_code const& e, std::size_t bytes_transferred);
		void on_name_lookup(error_code const& e, tcp::resolver::iterator i);
		void on_timeout();
		void on_connect(int ticket);
		void on_connected(error_code const& ec);
		void handshake1(error_code const& e);
		void handshake2(error_code const& e);
		void handshake3(error_code const& e);
		void handshake4(error_code const& e);
		void socks_forward_udp();
		void connect1(error_code const& e);
		void connect2(error_code const& e);
		void hung_up(error_code const& e);

		void wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec);
		void wrap(char const* hostname, int port, char const* p, int len, error_code& ec);
		void unwrap(error_code const& e, char const* buf, int size);

		bool maybe_clear_callback();

#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
#if defined BOOST_HAS_PTHREADS
		mutable pthread_t m_thread;
#endif
		bool is_single_thread() const
		{
#if defined BOOST_HAS_PTHREADS
			if (m_thread == 0)
				m_thread = pthread_self();
			return m_thread == pthread_self();
#endif
			return true;
		}
#endif

		udp::socket m_ipv4_sock;
		int m_buf_size;
		char* m_buf;

#if TORRENT_USE_IPV6
		udp::socket m_ipv6_sock;
#endif

		boost::uint16_t m_bind_port;
		boost::uint8_t m_v4_outstanding;
#if TORRENT_USE_IPV6
		boost::uint8_t m_v6_outstanding;
#endif

		tcp::socket m_socks5_sock;
		int m_connection_ticket;
		proxy_settings m_proxy_settings;
		connection_queue& m_cc;
		tcp::resolver m_resolver;
		char m_tmp_buf[270];
		bool m_queue_packets;
		bool m_tunnel_packets;
		bool m_abort;
		udp::endpoint m_proxy_addr;
		// while we're connecting to the proxy
		// we have to queue the packets, we'll flush
		// them once we're connected
		std::deque<queued_packet> m_queue;

		// counts the number of outstanding async
		// operations hanging on this socket
		int m_outstanding_ops;

#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
		bool m_started;
		int m_magic;
		int m_outstanding_when_aborted;
#endif
	};

	struct rate_limited_udp_socket : public udp_socket
	{
		rate_limited_udp_socket(io_service& ios, callback_t const& c
			, callback2_t const& c2, drain_callback_t const& dc, connection_queue& cc);
		void set_rate_limit(int limit) { m_rate_limit = limit; }
		bool can_send() const { return int(m_queue.size()) >= m_queue_size_limit; }
		bool send(udp::endpoint const& ep, char const* p, int len, error_code& ec, int flags = 0);
		void close();

	private:
		void on_tick(error_code const& e);

		deadline_timer m_timer;
		int m_queue_size_limit;
		int m_rate_limit;
		int m_quota;
		ptime m_last_tick;
		std::deque<queued_packet> m_queue;
	};
}

#endif

<|endoftext|>


<commit_before>#include "../easylogging++.h"

SUB(timeWaster,(int x,int y))
    for (int i = 0; i < x; i++) {
      for (int j = 0; j < y; j++) {
         //do nothing just waste time
         if (i == 10000000 && j==99) {
             INFO("i reached 10000000");
             RETURN();
         }
      }
    }
END_SUB

int main(void) {
   timeWaster(10000000,100);
   return 0;
}
<commit_msg>v2.1 fixes time issue<commit_after>#include "../easylogging++.h"

SUB(timeWaster,(int x))
    for (int i = 0; i < x; i++) {
      sleep(1);
    }
END_SUB

int main(void) {
   timeWaster(100);
   return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <filament/Engine.h>
#include <filament/IndexBuffer.h>
#include <filament/LightManager.h>
#include <filament/Material.h>
#include <filament/MaterialInstance.h>
#include <filament/RenderableManager.h>
#include <filament/Scene.h>
#include <filament/TransformManager.h>
#include <filament/VertexBuffer.h>
#include <filament/View.h>

#include <math/vec3.h>

#include <utils/Entity.h>
#include <utils/EntityManager.h>

#include "filamesh.h"
#include "filaweb.h"

using namespace filament;
using namespace math;
using namespace std;
using namespace utils;

using MagFilter = TextureSampler::MagFilter;
using WrapMode = TextureSampler::WrapMode;
using Format = Texture::InternalFormat;

struct SuzanneApp {
    Filamesh filamesh;
    Material* mat;
    MaterialInstance* mi;
    Camera* cam;
    Entity sun;
    Entity ptlight[4];
};

static constexpr uint8_t MATERIAL_LIT_PACKAGE[] = {
    #include "generated/material/texturedLit.inc"
};

static SuzanneApp app;

static Texture* setTextureParameter(Engine& engine, filaweb::Asset& asset, string name,
        TextureSampler const &sampler, Format internalFormat) {

    const auto destructor = [](void* buffer, size_t size, void* user) {
        auto asset = (filaweb::Asset*) user;
        asset->data.reset();
    };

    Texture::PixelBufferDescriptor pb(
            asset.data.get(), asset.nbytes, Texture::Format::RGBA, Texture::Type::UBYTE,
            destructor, &asset);

    // TODO: Since we use a Canvas 2D to decode textures, they are always 4-component. We should
    // manually reshape the data here to improve footprint.
    if (internalFormat == Format::R8) {
        internalFormat = Format::RGBA8;
    }

    auto texture = Texture::Builder()
            .width(asset.width)
            .height(asset.height)
            .sampler(Texture::Sampler::SAMPLER_2D)
            .format(internalFormat)
            .build(engine);

    texture->setImage(engine, 0, std::move(pb));
    app.mi->setParameter(name.c_str(), texture, sampler);
    return texture;
}

void setup(Engine* engine, View* view, Scene* scene) {

    // Create material.
    app.mat = Material::Builder()
            .package((void*) MATERIAL_LIT_PACKAGE, sizeof(MATERIAL_LIT_PACKAGE))
            .build(*engine);
    app.mi = app.mat->createInstance();
    app.mi->setParameter("clearCoat", 0.0f);

    // Move raw asset data from JavaScript to C++ static storage. Their held data will be freed via
    // BufferDescriptor callbacks after Filament creates the corresponding GPU objects.
    static auto mesh = filaweb::getRawFile("mesh");
    static auto albedo = filaweb::getTexture("albedo");
    static auto metallic = filaweb::getTexture("metallic");
    static auto roughness = filaweb::getTexture("roughness");
    static auto normal = filaweb::getTexture("normal");
    static auto ao = filaweb::getTexture("ao");

    // Create mesh.
    printf("%s: %d bytes\n", "mesh", mesh.nbytes);
    const uint8_t* mdata = mesh.data.get();
    const auto destructor = [](void* buffer, size_t size, void* user) {
        auto asset = (filaweb::Asset*) user;
        asset->data.reset();
    };
    app.filamesh = decodeMesh(*engine, mdata, 0, app.mi, destructor, &mesh);
    scene->addEntity(app.filamesh->renderable);

    // Create textures.
    TextureSampler sampler(MagFilter::LINEAR, WrapMode::CLAMP_TO_EDGE);
    auto setTexture = [engine, sampler] (filaweb::Asset& asset, const char* name, Format format) {
        printf("%s: %d x %d\n", name, asset.width, asset.height);
        setTextureParameter(*engine, asset, name, sampler, format);
    };
    setTexture(albedo, "albedo", Format::SRGB8_A8);
    setTexture(metallic, "metallic", Format::R8);
    setTexture(roughness, "roughness", Format::R8);
    setTexture(normal, "normal", Format::RGBA8);
    setTexture(ao, "ao", Format::R8);

    // Create the sun.
    auto& em = EntityManager::get();
    app.sun = em.create();
    LightManager::Builder(LightManager::Type::SUN)
            .color(Color::toLinear<ACCURATE>({ 0.98f, 0.92f, 0.89f }))
            .intensity(110000)
            .direction({ 0.7, -1, -0.8 })
            .sunAngularRadius(1.2f)
            .castShadows(true)
            .build(*engine, app.sun);
    scene->addEntity(app.sun);

    // Create point lights.
    LightManager::Builder(LightManager::Type::POINT)
            .color(Color::toLinear<ACCURATE>({0.98f, 0.92f, 0.89f}))
            .intensity(LightManager::EFFICIENCY_LED, 300.0f)
            .position({0.0f, -0.2f, -3.0f})
            .falloff(4.0f)
            .build(*engine, app.ptlight[0]);
    LightManager::Builder(LightManager::Type::POINT)
            .color(Color::toLinear<ACCURATE>({0.98f, 0.12f, 0.19f}))
            .intensity(LightManager::EFFICIENCY_LED, 200.0f)
            .position({0.6f, 0.6f, -3.2f})
            .falloff(2.0f)
            .build(*engine, app.ptlight[1]);
    LightManager::Builder(LightManager::Type::POINT)
            .color(Color::toLinear<ACCURATE>({0.18f, 0.12f, 0.89f}))
            .intensity(LightManager::EFFICIENCY_LED, 200.0f)
            .position({-0.6f, 0.6f, -3.2f})
            .falloff(2.0f)
            .build(*engine, app.ptlight[2]);
    LightManager::Builder(LightManager::Type::POINT)
            .color(Color::toLinear<ACCURATE>({0.88f, 0.82f, 0.29f}))
            .intensity(LightManager::EFFICIENCY_LED, 200.0f)
            .position({0.0f, 1.5f, -3.5f})
            .falloff(2.0f)
            .build(*engine, app.ptlight[3]);
    scene->addEntity(app.ptlight[0]);
    scene->addEntity(app.ptlight[1]);
    scene->addEntity(app.ptlight[2]);
    scene->addEntity(app.ptlight[3]);

    //  Create sky box and image-based light source.
    auto skylight = filaweb::getSkyLight(*engine, "syferfontein_18d_clear_2k");
    scene->setIndirectLight(skylight.indirectLight);
    scene->setSkybox(skylight.skybox);

    app.cam = engine->createCamera();
    app.cam->setExposure(16.0f, 1 / 125.0f, 100.0f);
    app.cam->lookAt(float3{0}, float3{0, 0, -4});
    view->setCamera(app.cam);
    view->setClearColor({0.1, 0.125, 0.25, 1.0});
};

void animate(Engine* engine, View* view, double now) {
    using Fov = Camera::Fov;
    const uint32_t width = view->getViewport().width;
    const uint32_t height = view->getViewport().height;
    double ratio = double(width) / height;
    app.cam->setProjection(45.0, ratio, 0.1, 50.0, ratio < 1 ? Fov::HORIZONTAL : Fov::VERTICAL);
    auto& tcm = engine->getTransformManager();
    tcm.setTransform(tcm.getInstance(app.filamesh->renderable),
        mat4f{mat3f{1.0}, float3{0.0f, 0.0f, -4.0f}} *
        mat4f::rotate(now, math::float3{0, 1, 0}));
};

void gui(filament::Engine* engine, filament::View*) {
};

// This is called only after the JavaScript layer has created a WebGL 2.0 context and all assets
// have been downloaded.
extern "C" void launch() {
    filaweb::Application::get()->run(setup, gui, animate);
}

// The main() entry point is implicitly called after JIT compilation, but potentially before the
// WebGL context has been created or assets have finished loading.
int main() { }

<commit_msg>Suzanne fixup: create entities for point lights. (#206)<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <filament/Engine.h>
#include <filament/IndexBuffer.h>
#include <filament/LightManager.h>
#include <filament/Material.h>
#include <filament/MaterialInstance.h>
#include <filament/RenderableManager.h>
#include <filament/Scene.h>
#include <filament/TransformManager.h>
#include <filament/VertexBuffer.h>
#include <filament/View.h>

#include <math/vec3.h>

#include <utils/Entity.h>
#include <utils/EntityManager.h>

#include "filamesh.h"
#include "filaweb.h"

using namespace filament;
using namespace math;
using namespace std;
using namespace utils;

using MagFilter = TextureSampler::MagFilter;
using WrapMode = TextureSampler::WrapMode;
using Format = Texture::InternalFormat;

struct SuzanneApp {
    Filamesh filamesh;
    Material* mat;
    MaterialInstance* mi;
    Camera* cam;
    Entity sun;
    Entity ptlight[4];
};

static constexpr uint8_t MATERIAL_LIT_PACKAGE[] = {
    #include "generated/material/texturedLit.inc"
};

static SuzanneApp app;

static Texture* setTextureParameter(Engine& engine, filaweb::Asset& asset, string name,
        TextureSampler const &sampler, Format internalFormat) {

    const auto destructor = [](void* buffer, size_t size, void* user) {
        auto asset = (filaweb::Asset*) user;
        asset->data.reset();
    };

    Texture::PixelBufferDescriptor pb(
            asset.data.get(), asset.nbytes, Texture::Format::RGBA, Texture::Type::UBYTE,
            destructor, &asset);

    // TODO: Since we use a Canvas 2D to decode textures, they are always 4-component. We should
    // manually reshape the data here to improve footprint.
    if (internalFormat == Format::R8) {
        internalFormat = Format::RGBA8;
    }

    auto texture = Texture::Builder()
            .width(asset.width)
            .height(asset.height)
            .sampler(Texture::Sampler::SAMPLER_2D)
            .format(internalFormat)
            .build(engine);

    texture->setImage(engine, 0, std::move(pb));
    app.mi->setParameter(name.c_str(), texture, sampler);
    return texture;
}

void setup(Engine* engine, View* view, Scene* scene) {

    // Create material.
    app.mat = Material::Builder()
            .package((void*) MATERIAL_LIT_PACKAGE, sizeof(MATERIAL_LIT_PACKAGE))
            .build(*engine);
    app.mi = app.mat->createInstance();
    app.mi->setParameter("clearCoat", 0.0f);

    // Move raw asset data from JavaScript to C++ static storage. Their held data will be freed via
    // BufferDescriptor callbacks after Filament creates the corresponding GPU objects.
    static auto mesh = filaweb::getRawFile("mesh");
    static auto albedo = filaweb::getTexture("albedo");
    static auto metallic = filaweb::getTexture("metallic");
    static auto roughness = filaweb::getTexture("roughness");
    static auto normal = filaweb::getTexture("normal");
    static auto ao = filaweb::getTexture("ao");

    // Create mesh.
    printf("%s: %d bytes\n", "mesh", mesh.nbytes);
    const uint8_t* mdata = mesh.data.get();
    const auto destructor = [](void* buffer, size_t size, void* user) {
        auto asset = (filaweb::Asset*) user;
        asset->data.reset();
    };
    app.filamesh = decodeMesh(*engine, mdata, 0, app.mi, destructor, &mesh);
    scene->addEntity(app.filamesh->renderable);

    // Create textures.
    TextureSampler sampler(MagFilter::LINEAR, WrapMode::CLAMP_TO_EDGE);
    auto setTexture = [engine, sampler] (filaweb::Asset& asset, const char* name, Format format) {
        printf("%s: %d x %d\n", name, asset.width, asset.height);
        setTextureParameter(*engine, asset, name, sampler, format);
    };
    setTexture(albedo, "albedo", Format::SRGB8_A8);
    setTexture(metallic, "metallic", Format::R8);
    setTexture(roughness, "roughness", Format::R8);
    setTexture(normal, "normal", Format::RGBA8);
    setTexture(ao, "ao", Format::R8);

    // Create the sun.
    auto& em = EntityManager::get();
    app.sun = em.create();
    LightManager::Builder(LightManager::Type::SUN)
            .color(Color::toLinear<ACCURATE>({ 0.98f, 0.92f, 0.89f }))
            .intensity(110000)
            .direction({ 0.7, -1, -0.8 })
            .sunAngularRadius(1.2f)
            .castShadows(true)
            .build(*engine, app.sun);
    scene->addEntity(app.sun);

    // Create point lights.
    em.create(4, app.ptlight);
    LightManager::Builder(LightManager::Type::POINT)
            .color(Color::toLinear<ACCURATE>({0.98f, 0.92f, 0.89f}))
            .intensity(LightManager::EFFICIENCY_LED, 300.0f)
            .position({0.0f, -0.2f, -3.0f})
            .falloff(4.0f)
            .build(*engine, app.ptlight[0]);
    LightManager::Builder(LightManager::Type::POINT)
            .color(Color::toLinear<ACCURATE>({0.98f, 0.12f, 0.19f}))
            .intensity(LightManager::EFFICIENCY_LED, 200.0f)
            .position({0.6f, 0.6f, -3.2f})
            .falloff(2.0f)
            .build(*engine, app.ptlight[1]);
    LightManager::Builder(LightManager::Type::POINT)
            .color(Color::toLinear<ACCURATE>({0.18f, 0.12f, 0.89f}))
            .intensity(LightManager::EFFICIENCY_LED, 200.0f)
            .position({-0.6f, 0.6f, -3.2f})
            .falloff(2.0f)
            .build(*engine, app.ptlight[2]);
    LightManager::Builder(LightManager::Type::POINT)
            .color(Color::toLinear<ACCURATE>({0.88f, 0.82f, 0.29f}))
            .intensity(LightManager::EFFICIENCY_LED, 200.0f)
            .position({0.0f, 1.5f, -3.5f})
            .falloff(2.0f)
            .build(*engine, app.ptlight[3]);
    scene->addEntity(app.ptlight[0]);
    scene->addEntity(app.ptlight[1]);
    scene->addEntity(app.ptlight[2]);
    scene->addEntity(app.ptlight[3]);

    //  Create sky box and image-based light source.
    auto skylight = filaweb::getSkyLight(*engine, "syferfontein_18d_clear_2k");
    scene->setIndirectLight(skylight.indirectLight);
    scene->setSkybox(skylight.skybox);

    app.cam = engine->createCamera();
    app.cam->setExposure(16.0f, 1 / 125.0f, 100.0f);
    app.cam->lookAt(float3{0}, float3{0, 0, -4});
    view->setCamera(app.cam);
    view->setClearColor({0.1, 0.125, 0.25, 1.0});
};

void animate(Engine* engine, View* view, double now) {
    using Fov = Camera::Fov;
    const uint32_t width = view->getViewport().width;
    const uint32_t height = view->getViewport().height;
    double ratio = double(width) / height;
    app.cam->setProjection(45.0, ratio, 0.1, 50.0, ratio < 1 ? Fov::HORIZONTAL : Fov::VERTICAL);
    auto& tcm = engine->getTransformManager();
    tcm.setTransform(tcm.getInstance(app.filamesh->renderable),
        mat4f{mat3f{1.0}, float3{0.0f, 0.0f, -4.0f}} *
        mat4f::rotate(now, math::float3{0, 1, 0}));
};

void gui(filament::Engine* engine, filament::View*) {
};

// This is called only after the JavaScript layer has created a WebGL 2.0 context and all assets
// have been downloaded.
extern "C" void launch() {
    filaweb::Application::get()->run(setup, gui, animate);
}

// The main() entry point is implicitly called after JIT compilation, but potentially before the
// WebGL context has been created or assets have finished loading.
int main() { }

<|endoftext|>


<commit_before>//****************************************************************************
// Copyright � 2015, Jan Erik Breimo.
// Created 2015-07-10 by Jan Erik Breimo
//
// This file is distributed under the Simplified BSD License.
// License text is included with the source distribution.
//****************************************************************************
#pragma once
#include <cstdint>

/** @file
  * @brief Defines constants and macros shared by all the other files
  *     in @a JEBString.
  */

/// @cond

#ifdef _WIN32
    #ifdef NROADREFTOOLS_EXPORTS
        #define YSTRING_API __declspec(dllexport)
    #else
        #define YSTRING_API
        #ifdef _DEBUG
            #pragma comment (lib, "Ystring.lib")
        #else
            #pragma comment (lib, "Ystring.lib")
        #endif
    #endif
#else
    #define YSTRING_API
#endif

/// @endcond

/** @brief The top-level namespace for all functions and classes
  *     in @a Ystring.
  */
namespace Ystring
{
    static const uint32_t UNICODE_MAX = (1 << 20) - 1;
    static const uint32_t INVALID_CHAR = 0xFFFFFFFFul;
}
<commit_msg>FIX: Copy/paste error.<commit_after>//****************************************************************************
// Copyright � 2015, Jan Erik Breimo.
// Created 2015-07-10 by Jan Erik Breimo
//
// This file is distributed under the Simplified BSD License.
// License text is included with the source distribution.
//****************************************************************************
#pragma once
#include <cstdint>

/** @file
  * @brief Defines constants and macros shared by all the other files
  *     in @a JEBString.
  */

/// @cond

#ifdef _WIN32
    #ifdef YSTRING_EXPORTS
        #define YSTRING_API __declspec(dllexport)
    #else
        #define YSTRING_API
        #ifdef _DEBUG
            #pragma comment (lib, "Ystring.lib")
        #else
            #pragma comment (lib, "Ystring.lib")
        #endif
    #endif
#else
    #define YSTRING_API
#endif

/// @endcond

/** @brief The top-level namespace for all functions and classes
  *     in @a Ystring.
  */
namespace Ystring
{
    static const uint32_t UNICODE_MAX = (1 << 20) - 1;
    static const uint32_t INVALID_CHAR = 0xFFFFFFFFul;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "JsonParser.h"

#include <functional>
#include <cctype>
#include <locale>

namespace et {
namespace core {

JSON::Parser::Parser(const std::string &textFile)
{
	MoveToNonWhitespace(textFile);
	if (!m_Completed && ReadToken(textFile) == JT_BeginObject)
	{
		m_Root = ParseObject(textFile);
		return;
	}
	LOG("Expected '{' token, parsing JSON failed", Warning);
}

JSON::Parser::~Parser()
{
	delete m_Root;
	m_Root = nullptr;
}

void JSON::Parser::MoveToNonWhitespace(const std::string &textFile)
{
	if (!std::isspace(textFile[m_ReadIdx]))return;
	auto it = std::find_if(textFile.begin()+m_ReadIdx, textFile.end(), [](const uint8 c) { return !std::isspace(c); });
	if (it == textFile.end())
	{
		m_Completed = true;
		m_ReadIdx = 0;
		return;
	}
	m_ReadIdx = (uint32)(it - textFile.begin());
}

JSON::Parser::Token JSON::Parser::ReadToken(const std::string &textFile)
{
	switch (textFile[m_ReadIdx++])
	{
	case '{': return JT_BeginObject;
	case '}': return JT_EndObject;
	case '[': return JT_BeginArray;
	case ']': return JT_EndArray;
	case '"': return JT_String;
	case ',': return JT_Delim;
	case ':': return JT_Value;
	case 't': if (m_ReadIdx + 4 > (uint32)textFile.size()) { m_Completed = true; return JT_Undefined; }
		if (textFile.substr(m_ReadIdx, 3) == "rue")
		{
			m_ReadIdx += 3;
			return JT_True;
		}
		return JT_Undefined;
	case 'f': if (m_ReadIdx + 5 > (uint32)textFile.size()) { m_Completed = true; return JT_Undefined; }
		if (textFile.substr(m_ReadIdx, 4) == "alse")
		{
			m_ReadIdx += 4;
			return JT_False;
		}
		return JT_Undefined;
	case 'n': if (m_ReadIdx + 4 > (uint32)textFile.size()) { m_Completed = true; return JT_Undefined; }
		if (textFile.substr(m_ReadIdx, 3) == "ull")
		{
			m_ReadIdx += 3;
			return JT_Null;
		}
		return JT_Undefined;
	default:
		m_ReadIdx--;
		if (textFile[m_ReadIdx] == '-' || std::isdigit(textFile[m_ReadIdx])) return JT_Numeric;
		return JT_Undefined;
	}
}

JSON::Object* JSON::Parser::ParseObject(const std::string & textFile)
{
	JSON::Object* ret = new JSON::Object;
	bool parseSuccess = false;
	bool parseFail = false;
	bool prevPair = false;
	bool prevDelim = false;
	while (!m_Completed && !parseSuccess && !parseFail)
	{
		MoveToNonWhitespace(textFile);
		if(CheckEOF(textFile))continue;
		Token token = ReadToken(textFile);
		if(!(token == JT_EndObject) && CheckEOF(textFile))continue;
		switch (token)
		{
		case JT_EndObject:
			if(prevDelim)
			{
				LOG("Expected a new Key Value pair after delimiter", Warning);
				parseFail = true;
				continue;
			}
			parseSuccess = true;
			break;
		case JT_String:
		{
			if (prevPair)
			{
				LOG("Expected a delimiter before new key value pair", Warning);
				parseFail = true;
				continue;
			}
			prevDelim = false;
			JSON::Pair keyVal = ParsePair(textFile);
			if (keyVal.second)
			{
				ret->value.push_back(keyVal);
				prevPair = true;
				continue;
			}
			parseFail = true;
			continue;
		}
		case JT_Delim:
			if (!prevPair)
			{
				LOG("Expected a new Key Value pair before delimiter", Warning);
				parseFail = true;
				continue;
			}
			prevPair = false;
			prevDelim = true;
			continue;
		default:
			parseFail = true;
			continue;
		}
	}
	if (!parseSuccess)
	{
		delete ret;
		LOG("Couldn't successfully parse object", Warning);
		return nullptr;
	}
	return ret;
}

JSON::Pair JSON::Parser::ParsePair(const std::string & textFile)
{
	JSON::Pair ret;
	ret.second = nullptr;
	if (ParseString(textFile, ret.first))
	{
		MoveToNonWhitespace(textFile);
		if (!CheckEOF(textFile) && ReadToken(textFile) == JT_Value)
		{
			MoveToNonWhitespace(textFile);
			if (!CheckEOF(textFile)) ret.second = ParseValue(textFile);
		}
	}
	return ret;
}

JSON::Value* JSON::Parser::ParseValue(const std::string & textFile)
{
	MoveToNonWhitespace(textFile);
	if(CheckEOF(textFile))return nullptr;
	Token token = ReadToken(textFile);
	if(CheckEOF(textFile))return nullptr;

	switch (token)
	{
	case JT_String:
	{
		JSON::String* ret = new JSON::String();
		if (!ParseString(textFile, ret->value))
		{
			delete ret;
			return nullptr;
		}
		return ret;
	}
	case JT_Numeric:
		return ParseNumber(textFile);
	case JT_BeginObject:
		return ParseObject(textFile);
	case JT_BeginArray:
		return ParseArray(textFile);
	case JT_True:
	case JT_False:
	{
		JSON::Bool* ret = new JSON::Bool();
		ret->value = token == JT_True;
		return ret;
	}
	case JT_Null:
		return new JSON::Value();
	}

	LOG("Couldn't successfully parse value, unexpected token", Warning);
	return nullptr;
}

bool JSON::Parser::ParseString(const std::string & textFile, std::string &parsed)
{
	while (!m_Completed)
	{
		if (CheckEOF(textFile))return false;
		char next = textFile[m_ReadIdx++];
		if (next == '"')
		{
			//m_ReadIdx++;
			return true;
		}
		else if (next == '\\')
		{
			if (CheckEOF(textFile))return false;
			next = textFile[m_ReadIdx++];
			switch (next)
			{
			case '\"': parsed += '\"'; break;
			case '\\': parsed += '\\'; break;
			case '/': parsed += '/'; break;
			case 'b': parsed += '\b'; break;
			case 'f': parsed += '\f'; break;
			case 'n': parsed += '\n'; break;
			case 'r': parsed += '\r'; break;
			case 't': parsed += '\t'; break;
			case 'u':
			{
				if (m_ReadIdx + 4 > (uint32)textFile.size()) return false;
				std::string hexString = "0x" + textFile.substr(m_ReadIdx, 4);
				parsed += static_cast<char>(std::stoul(hexString, nullptr, 16));
				m_ReadIdx += 4;
			}
			break;
			default:
				LOG("unexpected symbol after escape character while parsing string", Warning);
				return false;
			}
		}
		else
		{
			parsed += next;
		}
	}
	return false;
}

JSON::Array* JSON::Parser::ParseArray(const std::string & textFile)
{
	JSON::Array* ret = new JSON::Array;
	bool parseSuccess = false;
	bool parseFail = false;
	bool prevVal = false;
	bool prevDelim = false;
	while (!m_Completed && !parseSuccess && !parseFail)
	{
		MoveToNonWhitespace(textFile);
		if(CheckEOF(textFile))continue;
		Token token = ReadToken(textFile);
		if(!(token == JT_Delim) && !(token == JT_EndArray) && !(token == JT_Numeric))m_ReadIdx--;
		if(CheckEOF(textFile))continue;
		switch (token)
		{
		case JT_EndArray:
			if(prevDelim)
			{
				LOG("Expected a new Key Value pair after delimiter", Warning);
				parseFail = true;
				continue;
			}
			parseSuccess = true;
			break;
		case JT_Delim:
			if (!prevVal)
			{
				LOG("Expected a new Key Value pair before delimiter", Warning);
				parseFail = true;
				continue;
			}
			prevVal = false;
			prevDelim = true;
			continue;
		default:
			if (!prevVal)
			{
				JSON::Value* val = ParseValue(textFile);
				prevDelim = false;
				if (val)
				{
					ret->value.push_back(val);
					prevVal = true;
					continue;
				}
			}
			else
				LOG("Expected a delimiter before new Key Value pair", Warning);
			parseFail = true;
			continue;
		}
	}
	if (!parseSuccess)
	{
		delete ret;
		LOG("Couldn't successfully parse array", Warning);
		return nullptr;
	}
	return ret;
}

JSON::Number* JSON::Parser::ParseNumber(const std::string & textFile)
{
	uint32 endNumberIdx = m_ReadIdx;
	enum class NumStage
	{
		SIGN,
		NUM,
		FRACTION,
		EXPSIGN,
		EXPONENT
	}stage = NumStage::SIGN;
	bool endFound = false;
	bool isInt = true;
	while (!m_Completed && !endFound)
	{
		if (CheckEOF(textFile))return false;
		char next = textFile[endNumberIdx];
		switch (stage)
		{
		case NumStage::SIGN:
			if (!(std::isdigit(next) || next == '-'))return nullptr;
			if(next == '-') endNumberIdx++;
			stage = NumStage::NUM;
			break;
		case NumStage::NUM:
			if (!(std::isdigit(next) || next == '.' || next == 'e' || next == 'E'))
			{
				endFound = true;
				continue;
			}
			endNumberIdx++;
			if (next == '.')
			{
				stage = NumStage::FRACTION;
			}
			if (next == 'e' || next == 'E')
			{
				stage = NumStage::EXPSIGN;
			}
			break;
		case NumStage::FRACTION:
			isInt = false;
			if (!(std::isdigit(next) || next == 'e' || next == 'E'))
			{
				endFound = true;
				continue;
			}
			endNumberIdx++;
			if (next == 'e' || next == 'E')
			{
				stage = NumStage::EXPSIGN;
			}
			break;
		case NumStage::EXPSIGN:
			if (!(std::isdigit(next) || next == '-' || next == '+'))return nullptr;
			if(next == '-' || next == '+') endNumberIdx++;
			stage = NumStage::EXPONENT;
			break;
		case NumStage::EXPONENT:
			if (!std::isdigit(next))
			{
				endFound = true;
				continue;
			}
			endNumberIdx++;
			break;
		}
	}
	std::string numString = textFile.substr(m_ReadIdx, endNumberIdx - m_ReadIdx);
	double num = std::atof(numString.c_str());
	int64 numInt = std::stol(numString);
	m_ReadIdx = endNumberIdx;
	JSON::Number* ret = new JSON::Number();
	ret->value = num;
	ret->valueInt = numInt;
	ret->isInt = isInt;
	return ret;
}

bool JSON::Parser::CheckEOF(const std::string &textFile)
{
	if (m_Completed || m_ReadIdx >= (uint32)textFile.size())
	{
		m_Completed = true;
		LOG("Reached end of file unexpected", Warning);
		return true;
	}
	return false;
}

} // namespace core
} // namespace et
<commit_msg>JsonParser: fix return type, a bool is no pointer<commit_after>#include "stdafx.h"
#include "JsonParser.h"

#include <functional>
#include <cctype>
#include <locale>

namespace et {
namespace core {

JSON::Parser::Parser(const std::string &textFile)
{
	MoveToNonWhitespace(textFile);
	if (!m_Completed && ReadToken(textFile) == JT_BeginObject)
	{
		m_Root = ParseObject(textFile);
		return;
	}
	LOG("Expected '{' token, parsing JSON failed", Warning);
}

JSON::Parser::~Parser()
{
	delete m_Root;
	m_Root = nullptr;
}

void JSON::Parser::MoveToNonWhitespace(const std::string &textFile)
{
	if (!std::isspace(textFile[m_ReadIdx]))return;
	auto it = std::find_if(textFile.begin()+m_ReadIdx, textFile.end(), [](const uint8 c) { return !std::isspace(c); });
	if (it == textFile.end())
	{
		m_Completed = true;
		m_ReadIdx = 0;
		return;
	}
	m_ReadIdx = (uint32)(it - textFile.begin());
}

JSON::Parser::Token JSON::Parser::ReadToken(const std::string &textFile)
{
	switch (textFile[m_ReadIdx++])
	{
	case '{': return JT_BeginObject;
	case '}': return JT_EndObject;
	case '[': return JT_BeginArray;
	case ']': return JT_EndArray;
	case '"': return JT_String;
	case ',': return JT_Delim;
	case ':': return JT_Value;
	case 't': if (m_ReadIdx + 4 > (uint32)textFile.size()) { m_Completed = true; return JT_Undefined; }
		if (textFile.substr(m_ReadIdx, 3) == "rue")
		{
			m_ReadIdx += 3;
			return JT_True;
		}
		return JT_Undefined;
	case 'f': if (m_ReadIdx + 5 > (uint32)textFile.size()) { m_Completed = true; return JT_Undefined; }
		if (textFile.substr(m_ReadIdx, 4) == "alse")
		{
			m_ReadIdx += 4;
			return JT_False;
		}
		return JT_Undefined;
	case 'n': if (m_ReadIdx + 4 > (uint32)textFile.size()) { m_Completed = true; return JT_Undefined; }
		if (textFile.substr(m_ReadIdx, 3) == "ull")
		{
			m_ReadIdx += 3;
			return JT_Null;
		}
		return JT_Undefined;
	default:
		m_ReadIdx--;
		if (textFile[m_ReadIdx] == '-' || std::isdigit(textFile[m_ReadIdx])) return JT_Numeric;
		return JT_Undefined;
	}
}

JSON::Object* JSON::Parser::ParseObject(const std::string & textFile)
{
	JSON::Object* ret = new JSON::Object;
	bool parseSuccess = false;
	bool parseFail = false;
	bool prevPair = false;
	bool prevDelim = false;
	while (!m_Completed && !parseSuccess && !parseFail)
	{
		MoveToNonWhitespace(textFile);
		if(CheckEOF(textFile))continue;
		Token token = ReadToken(textFile);
		if(!(token == JT_EndObject) && CheckEOF(textFile))continue;
		switch (token)
		{
		case JT_EndObject:
			if(prevDelim)
			{
				LOG("Expected a new Key Value pair after delimiter", Warning);
				parseFail = true;
				continue;
			}
			parseSuccess = true;
			break;
		case JT_String:
		{
			if (prevPair)
			{
				LOG("Expected a delimiter before new key value pair", Warning);
				parseFail = true;
				continue;
			}
			prevDelim = false;
			JSON::Pair keyVal = ParsePair(textFile);
			if (keyVal.second)
			{
				ret->value.push_back(keyVal);
				prevPair = true;
				continue;
			}
			parseFail = true;
			continue;
		}
		case JT_Delim:
			if (!prevPair)
			{
				LOG("Expected a new Key Value pair before delimiter", Warning);
				parseFail = true;
				continue;
			}
			prevPair = false;
			prevDelim = true;
			continue;
		default:
			parseFail = true;
			continue;
		}
	}
	if (!parseSuccess)
	{
		delete ret;
		LOG("Couldn't successfully parse object", Warning);
		return nullptr;
	}
	return ret;
}

JSON::Pair JSON::Parser::ParsePair(const std::string & textFile)
{
	JSON::Pair ret;
	ret.second = nullptr;
	if (ParseString(textFile, ret.first))
	{
		MoveToNonWhitespace(textFile);
		if (!CheckEOF(textFile) && ReadToken(textFile) == JT_Value)
		{
			MoveToNonWhitespace(textFile);
			if (!CheckEOF(textFile)) ret.second = ParseValue(textFile);
		}
	}
	return ret;
}

JSON::Value* JSON::Parser::ParseValue(const std::string & textFile)
{
	MoveToNonWhitespace(textFile);
	if(CheckEOF(textFile))return nullptr;
	Token token = ReadToken(textFile);
	if(CheckEOF(textFile))return nullptr;

	switch (token)
	{
	case JT_String:
	{
		JSON::String* ret = new JSON::String();
		if (!ParseString(textFile, ret->value))
		{
			delete ret;
			return nullptr;
		}
		return ret;
	}
	case JT_Numeric:
		return ParseNumber(textFile);
	case JT_BeginObject:
		return ParseObject(textFile);
	case JT_BeginArray:
		return ParseArray(textFile);
	case JT_True:
	case JT_False:
	{
		JSON::Bool* ret = new JSON::Bool();
		ret->value = token == JT_True;
		return ret;
	}
	case JT_Null:
		return new JSON::Value();
	}

	LOG("Couldn't successfully parse value, unexpected token", Warning);
	return nullptr;
}

bool JSON::Parser::ParseString(const std::string & textFile, std::string &parsed)
{
	while (!m_Completed)
	{
		if (CheckEOF(textFile))return false;
		char next = textFile[m_ReadIdx++];
		if (next == '"')
		{
			//m_ReadIdx++;
			return true;
		}
		else if (next == '\\')
		{
			if (CheckEOF(textFile))return false;
			next = textFile[m_ReadIdx++];
			switch (next)
			{
			case '\"': parsed += '\"'; break;
			case '\\': parsed += '\\'; break;
			case '/': parsed += '/'; break;
			case 'b': parsed += '\b'; break;
			case 'f': parsed += '\f'; break;
			case 'n': parsed += '\n'; break;
			case 'r': parsed += '\r'; break;
			case 't': parsed += '\t'; break;
			case 'u':
			{
				if (m_ReadIdx + 4 > (uint32)textFile.size()) return false;
				std::string hexString = "0x" + textFile.substr(m_ReadIdx, 4);
				parsed += static_cast<char>(std::stoul(hexString, nullptr, 16));
				m_ReadIdx += 4;
			}
			break;
			default:
				LOG("unexpected symbol after escape character while parsing string", Warning);
				return false;
			}
		}
		else
		{
			parsed += next;
		}
	}
	return false;
}

JSON::Array* JSON::Parser::ParseArray(const std::string & textFile)
{
	JSON::Array* ret = new JSON::Array;
	bool parseSuccess = false;
	bool parseFail = false;
	bool prevVal = false;
	bool prevDelim = false;
	while (!m_Completed && !parseSuccess && !parseFail)
	{
		MoveToNonWhitespace(textFile);
		if(CheckEOF(textFile))continue;
		Token token = ReadToken(textFile);
		if(!(token == JT_Delim) && !(token == JT_EndArray) && !(token == JT_Numeric))m_ReadIdx--;
		if(CheckEOF(textFile))continue;
		switch (token)
		{
		case JT_EndArray:
			if(prevDelim)
			{
				LOG("Expected a new Key Value pair after delimiter", Warning);
				parseFail = true;
				continue;
			}
			parseSuccess = true;
			break;
		case JT_Delim:
			if (!prevVal)
			{
				LOG("Expected a new Key Value pair before delimiter", Warning);
				parseFail = true;
				continue;
			}
			prevVal = false;
			prevDelim = true;
			continue;
		default:
			if (!prevVal)
			{
				JSON::Value* val = ParseValue(textFile);
				prevDelim = false;
				if (val)
				{
					ret->value.push_back(val);
					prevVal = true;
					continue;
				}
			}
			else
				LOG("Expected a delimiter before new Key Value pair", Warning);
			parseFail = true;
			continue;
		}
	}
	if (!parseSuccess)
	{
		delete ret;
		LOG("Couldn't successfully parse array", Warning);
		return nullptr;
	}
	return ret;
}

JSON::Number* JSON::Parser::ParseNumber(const std::string & textFile)
{
	uint32 endNumberIdx = m_ReadIdx;
	enum class NumStage
	{
		SIGN,
		NUM,
		FRACTION,
		EXPSIGN,
		EXPONENT
	}stage = NumStage::SIGN;
	bool endFound = false;
	bool isInt = true;
	while (!m_Completed && !endFound)
	{
		if (CheckEOF(textFile)) return nullptr;
		char next = textFile[endNumberIdx];
		switch (stage)
		{
		case NumStage::SIGN:
			if (!(std::isdigit(next) || next == '-'))return nullptr;
			if(next == '-') endNumberIdx++;
			stage = NumStage::NUM;
			break;
		case NumStage::NUM:
			if (!(std::isdigit(next) || next == '.' || next == 'e' || next == 'E'))
			{
				endFound = true;
				continue;
			}
			endNumberIdx++;
			if (next == '.')
			{
				stage = NumStage::FRACTION;
			}
			if (next == 'e' || next == 'E')
			{
				stage = NumStage::EXPSIGN;
			}
			break;
		case NumStage::FRACTION:
			isInt = false;
			if (!(std::isdigit(next) || next == 'e' || next == 'E'))
			{
				endFound = true;
				continue;
			}
			endNumberIdx++;
			if (next == 'e' || next == 'E')
			{
				stage = NumStage::EXPSIGN;
			}
			break;
		case NumStage::EXPSIGN:
			if (!(std::isdigit(next) || next == '-' || next == '+'))return nullptr;
			if(next == '-' || next == '+') endNumberIdx++;
			stage = NumStage::EXPONENT;
			break;
		case NumStage::EXPONENT:
			if (!std::isdigit(next))
			{
				endFound = true;
				continue;
			}
			endNumberIdx++;
			break;
		}
	}
	std::string numString = textFile.substr(m_ReadIdx, endNumberIdx - m_ReadIdx);
	double num = std::atof(numString.c_str());
	int64 numInt = std::stol(numString);
	m_ReadIdx = endNumberIdx;
	JSON::Number* ret = new JSON::Number();
	ret->value = num;
	ret->valueInt = numInt;
	ret->isInt = isInt;
	return ret;
}

bool JSON::Parser::CheckEOF(const std::string &textFile)
{
	if (m_Completed || m_ReadIdx >= (uint32)textFile.size())
	{
		m_Completed = true;
		LOG("Reached end of file unexpected", Warning);
		return true;
	}
	return false;
}

} // namespace core
} // namespace et
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2013 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
#ifndef MAPNIK_TEXT_LINE_HPP
#define MAPNIK_TEXT_LINE_HPP

//mapnik
#include <mapnik/text/glyph_info.hpp>
#include <mapnik/text/text_properties.hpp>
//stl
#include <vector>

namespace mapnik
{

// This class stores all glyphs of a line in left to right order.
// It can be used for rendering but no text processing (like line breaking)
// should be done!

class text_line
{
public:
    using glyph_vector = std::vector<glyph_info>;
    using const_iterator = glyph_vector::const_iterator;

    text_line(unsigned first_char, unsigned last_char);

    // Get glyph vector.
    glyph_vector const& glyphs() const { return glyphs_; }
    // Append glyph.
    void add_glyph(glyph_info && glyph, double scale_factor_);

    // Preallocate memory.
    void reserve(glyph_vector::size_type length);
    // Iterator to first glyph.
    const_iterator begin() const;
    // Iterator beyond last glyph.
    const_iterator end() const;

    // Width of all glyphs including character spacing.
    double width() const { return width_; }
    // Real line height. For first line: max_char_height(), for all others: line_height().
    double height() const;

    // Height of the tallest glyph in this line.
    double max_char_height() const { return max_char_height_; }
    // Called for each font/style to update the maximum height of this line.
    void update_max_char_height(double max_char_height);
    // Line height including line spacing.
    double line_height() const { return line_height_; }

    // Is this object is the first line of a multi-line text?
    // Used to exclude linespacing from first line's height.
    void set_first_line(bool first_line);

    // Index of first UTF-16 char.
    unsigned first_char() const;
    // Index of last UTF-16 char.
    unsigned last_char() const;

    // Number of glyphs.
    unsigned size() const;
private:
    glyph_vector glyphs_;
    double line_height_; //Includes line spacing (returned by freetype)
    double max_char_height_; //Height of 'X' character of the largest font in this run. //TODO: Initialize this!
    double width_;
    unsigned first_char_;
    unsigned last_char_;
    bool first_line_;
};

} //namespace mapnik

#endif // MAPNIK_TEXT_LINE_HPP
<commit_msg>text_line: remove unneeded acces to glyph storage<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2013 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
#ifndef MAPNIK_TEXT_LINE_HPP
#define MAPNIK_TEXT_LINE_HPP

//mapnik
#include <mapnik/text/glyph_info.hpp>
#include <mapnik/text/text_properties.hpp>
//stl
#include <vector>

namespace mapnik
{

// This class stores all glyphs of a line in left to right order.
// It can be used for rendering but no text processing (like line breaking)
// should be done!

class text_line
{
public:
    using glyph_vector = std::vector<glyph_info>;
    using const_iterator = glyph_vector::const_iterator;

    text_line(unsigned first_char, unsigned last_char);

    // Append glyph.
    void add_glyph(glyph_info && glyph, double scale_factor_);

    // Preallocate memory.
    void reserve(glyph_vector::size_type length);
    // Iterator to first glyph.
    const_iterator begin() const;
    // Iterator beyond last glyph.
    const_iterator end() const;

    // Width of all glyphs including character spacing.
    double width() const { return width_; }
    // Real line height. For first line: max_char_height(), for all others: line_height().
    double height() const;

    // Height of the tallest glyph in this line.
    double max_char_height() const { return max_char_height_; }
    // Called for each font/style to update the maximum height of this line.
    void update_max_char_height(double max_char_height);
    // Line height including line spacing.
    double line_height() const { return line_height_; }

    // Is this object is the first line of a multi-line text?
    // Used to exclude linespacing from first line's height.
    void set_first_line(bool first_line);

    // Index of first UTF-16 char.
    unsigned first_char() const;
    // Index of last UTF-16 char.
    unsigned last_char() const;

    // Number of glyphs.
    unsigned size() const;
private:
    glyph_vector glyphs_;
    double line_height_; // Includes line spacing (returned by freetype)
    double max_char_height_; // Height of 'X' character of the largest font in this run. //TODO: Initialize this!
    double width_;
    unsigned first_char_;
    unsigned last_char_;
    bool first_line_;
};

} //namespace mapnik

#endif // MAPNIK_TEXT_LINE_HPP
<|endoftext|>