<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.

*/

#include "libtorrent/pch.hpp"

#include <boost/bind.hpp>
#include <asio/ip/host_name.hpp>

#include "libtorrent/natpmp.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/enum_net.hpp"

using boost::bind;
using namespace libtorrent;

enum { num_mappings = 2 };

namespace libtorrent
{
	// defined in upnp.cpp
	bool is_local(address const& a);
	address guess_local_address(asio::io_service&);
}

natpmp::natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb)
	: m_callback(cb)
	, m_currently_mapping(-1)
	, m_retry_count(0)
	, m_socket(ios)
	, m_send_timer(ios)
	, m_refresh_timer(ios)
	, m_disabled(false)
{
	m_mappings[0].protocol = 2; // tcp
	m_mappings[1].protocol = 1; // udp

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log.open("natpmp.log", std::ios::in | std::ios::out | std::ios::trunc);
#endif
	rebind(listen_interface);
}

void natpmp::rebind(address const& listen_interface) try
{
	address local = address_v4::any();
	if (listen_interface != address_v4::any())
	{
		local = listen_interface;
	}
	else
	{
		local = guess_local_address(m_socket.io_service());

		if (local == address_v4::any())
		{
			throw std::runtime_error("local host is probably not on a NATed "
				"network. disabling NAT-PMP");
		}
	}

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " local ip: " << local.to_string() << std::endl;
#endif

	if (!is_local(local))
	{
		// the local address seems to be an external
		// internet address. Assume it is not behind a NAT
		throw std::runtime_error("local IP is not on a local network");
	}

	m_disabled = false;

	asio::error_code ec;
	udp::endpoint nat_endpoint(router_for_interface(local, ec), 5351);
	if (ec)
		throw std::runtime_error("cannot retrieve router address");

	if (nat_endpoint == m_nat_endpoint) return;
	m_nat_endpoint = nat_endpoint;

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << "assuming router is at: " << m_nat_endpoint.address().to_string() << std::endl;
#endif

	m_socket.open(udp::v4());
	m_socket.bind(udp::endpoint(address_v4::any(), 0));

	for (int i = 0; i < num_mappings; ++i)
	{
		if (m_mappings[i].local_port == 0)
			continue;
		refresh_mapping(i);
	}
}
catch (std::exception& e)
{
	m_disabled = true;
	std::stringstream msg;
	msg << "NAT-PMP disabled: " << e.what();
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << msg.str() << std::endl;
#endif
	m_callback(0, 0, msg.str());
};

void natpmp::set_mappings(int tcp, int udp)
{
	if (m_disabled) return;
	update_mapping(0, tcp);
	update_mapping(1, udp);
}

void natpmp::update_mapping(int i, int port)
{
	natpmp::mapping& m = m_mappings[i];
	if (port <= 0) return;
	if (m.local_port != port)
		m.need_update = true;

	m.local_port = port;
	// prefer the same external port as the local port
	if (m.external_port == 0) m.external_port = port;

	if (m_currently_mapping == -1)
	{
		// the socket is not currently in use
		// send out a mapping request
		m_retry_count = 0;
		send_map_request(i);
		m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16)
			, m_remote, bind(&natpmp::on_reply, self(), _1, _2));
	}
}

void natpmp::send_map_request(int i) try
{
	using namespace libtorrent::detail;

	TORRENT_ASSERT(m_currently_mapping == -1
		|| m_currently_mapping == i);
	m_currently_mapping = i;
	mapping& m = m_mappings[i];
	char buf[12];
	char* out = buf;
	write_uint8(0, out); // NAT-PMP version
	write_uint8(m.protocol, out); // map "protocol"
	write_uint16(0, out); // reserved
	write_uint16(m.local_port, out); // private port
	write_uint16(m.external_port, out); // requested public port
	int ttl = m.external_port == 0 ? 0 : 3600;
	write_uint32(ttl, out); // port mapping lifetime

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " ==> port map request: " << (m.protocol == 1 ? "udp" : "tcp")
		<< " local: " << m.local_port << " external: " << m.external_port
		<< " ttl: " << ttl << std::endl;
#endif

	m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint);
	// linear back-off instead of exponential
	++m_retry_count;
	m_send_timer.expires_from_now(milliseconds(250 * m_retry_count));
	m_send_timer.async_wait(bind(&natpmp::resend_request, self(), i, _1));
}
catch (std::exception& e)
{
	std::string err = e.what();
};

void natpmp::resend_request(int i, asio::error_code const& e)
{
	if (e) return;
	if (m_currently_mapping != i) return;
	if (m_retry_count >= 9)
	{
		m_mappings[i].need_update = false;
		// try again in two hours
		m_mappings[i].expires = time_now() + hours(2);
		return;
	}
	send_map_request(i);
}

void natpmp::on_reply(asio::error_code const& e
	, std::size_t bytes_transferred)
{
	using namespace libtorrent::detail;
	if (e) return;

	try
	{

		if (m_remote != m_nat_endpoint)
		{
			m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16)
				, m_remote, bind(&natpmp::on_reply, self(), _1, _2));
			return;
		}

		m_send_timer.cancel();

		TORRENT_ASSERT(m_currently_mapping >= 0);
		int i = m_currently_mapping;
		mapping& m = m_mappings[i];

		char* in = m_response_buffer;
		int version = read_uint8(in);
		int cmd = read_uint8(in);
		int result = read_uint16(in);
		int time = read_uint32(in);
		int private_port = read_uint16(in);
		int public_port = read_uint16(in);
		int lifetime = read_uint32(in);

		(void)time; // to remove warning

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		m_log << time_now_string()
			<< " <== port map response: " << (cmd - 128 == 1 ? "udp" : "tcp")
			<< " local: " << private_port << " external: " << public_port
			<< " ttl: " << lifetime << std::endl;
#endif

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		if (version != 0)
		{
			m_log << "*** unexpected version: " << version << std::endl;
		}
#endif

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		if (private_port != m.local_port)
		{
			m_log << "*** unexpected local port: " << private_port << std::endl;
		}
#endif

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		if (cmd != 128 + m.protocol)
		{
			m_log << "*** unexpected protocol: " << (cmd - 128) << std::endl;
		}
#endif

		if (public_port == 0 || lifetime == 0)
		{
			// this means the mapping was
			// successfully closed
			m.local_port = 0;
		}
		else
		{
			m.expires = time_now() + seconds(int(lifetime * 0.7f));
			m.external_port = public_port;
		}

		if (result != 0)
		{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
			m_log << "*** ERROR: " << result << std::endl;
#endif
			std::stringstream errmsg;
			errmsg << "NAT router reports error (" << result << ") ";
			switch (result)
			{
				case 1: errmsg << "Unsupported protocol version"; break;
				case 2: errmsg << "Not authorized to create port map (enable NAT-PMP on your router)"; break;
				case 3: errmsg << "Network failure"; break;
				case 4: errmsg << "Out of resources"; break;
				case 5: errmsg << "Unsupported opcode"; break;
			}
			throw std::runtime_error(errmsg.str());
		}

		// don't report when we remove mappings
		if (m.local_port != 0)
		{
			int tcp_port = 0;
			int udp_port = 0;
			if (m.protocol == 1) udp_port = m.external_port;
			else tcp_port = public_port;
			m_callback(tcp_port, udp_port, "");
		}
	}
	catch (std::exception& e)
	{
		// try again in two hours
		m_mappings[m_currently_mapping].expires = time_now() + hours(2);
		m_callback(0, 0, e.what());
	}
	int i = m_currently_mapping;
	m_currently_mapping = -1;
	m_mappings[i].need_update = false;
	m_send_timer.cancel();
	update_expiration_timer();
	try_next_mapping(i);
}

void natpmp::update_expiration_timer()
{
	ptime now = time_now();
	ptime min_expire = now + seconds(3600);
	int min_index = -1;
	for (int i = 0; i < num_mappings; ++i)
		if (m_mappings[i].expires < min_expire
			&& m_mappings[i].local_port != 0)
		{
			min_expire = m_mappings[i].expires;
			min_index = i;
		}

	if (min_index >= 0)
	{
		m_refresh_timer.expires_from_now(min_expire - now);
		m_refresh_timer.async_wait(bind(&natpmp::mapping_expired, self(), _1, min_index));
	}
}

void natpmp::mapping_expired(asio::error_code const& e, int i)
{
	if (e) return;
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << "*** mapping " << i << " expired, updating" << std::endl;
#endif
	refresh_mapping(i);
}

void natpmp::refresh_mapping(int i)
{
	m_mappings[i].need_update = true;
	if (m_currently_mapping == -1)
	{
		// the socket is not currently in use
		// send out a mapping request
		m_retry_count = 0;
		send_map_request(i);
		m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16)
			, m_remote, bind(&natpmp::on_reply, self(), _1, _2));
	}
}

void natpmp::try_next_mapping(int i)
{
	++i;
	if (i >= num_mappings) i = 0;
	if (m_mappings[i].need_update)
		refresh_mapping(i);
}

void natpmp::close()
{
	if (m_disabled) return;
	for (int i = 0; i < num_mappings; ++i)
	{
		if (m_mappings[i].local_port == 0)
			continue;
		m_mappings[i].external_port = 0;
		refresh_mapping(i);
	}
}

<commit_msg>natpmp close fix<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.

*/

#include "libtorrent/pch.hpp"

#include <boost/bind.hpp>
#include <asio/ip/host_name.hpp>

#include "libtorrent/natpmp.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/enum_net.hpp"

using boost::bind;
using namespace libtorrent;

enum { num_mappings = 2 };

namespace libtorrent
{
	// defined in upnp.cpp
	bool is_local(address const& a);
	address guess_local_address(asio::io_service&);
}

natpmp::natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb)
	: m_callback(cb)
	, m_currently_mapping(-1)
	, m_retry_count(0)
	, m_socket(ios)
	, m_send_timer(ios)
	, m_refresh_timer(ios)
	, m_disabled(false)
{
	m_mappings[0].protocol = 2; // tcp
	m_mappings[1].protocol = 1; // udp

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log.open("natpmp.log", std::ios::in | std::ios::out | std::ios::trunc);
#endif
	rebind(listen_interface);
}

void natpmp::rebind(address const& listen_interface) try
{
	address local = address_v4::any();
	if (listen_interface != address_v4::any())
	{
		local = listen_interface;
	}
	else
	{
		local = guess_local_address(m_socket.io_service());

		if (local == address_v4::any())
		{
			throw std::runtime_error("local host is probably not on a NATed "
				"network. disabling NAT-PMP");
		}
	}

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " local ip: " << local.to_string() << std::endl;
#endif

	if (!is_local(local))
	{
		// the local address seems to be an external
		// internet address. Assume it is not behind a NAT
		throw std::runtime_error("local IP is not on a local network");
	}

	m_disabled = false;

	asio::error_code ec;
	udp::endpoint nat_endpoint(router_for_interface(local, ec), 5351);
	if (ec)
		throw std::runtime_error("cannot retrieve router address");

	if (nat_endpoint == m_nat_endpoint) return;
	m_nat_endpoint = nat_endpoint;

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << "assuming router is at: " << m_nat_endpoint.address().to_string() << std::endl;
#endif

	m_socket.open(udp::v4());
	m_socket.bind(udp::endpoint(address_v4::any(), 0));

	for (int i = 0; i < num_mappings; ++i)
	{
		if (m_mappings[i].local_port == 0)
			continue;
		refresh_mapping(i);
	}
}
catch (std::exception& e)
{
	m_disabled = true;
	std::stringstream msg;
	msg << "NAT-PMP disabled: " << e.what();
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << msg.str() << std::endl;
#endif
	m_callback(0, 0, msg.str());
};

void natpmp::set_mappings(int tcp, int udp)
{
	if (m_disabled) return;
	update_mapping(0, tcp);
	update_mapping(1, udp);
}

void natpmp::update_mapping(int i, int port)
{
	natpmp::mapping& m = m_mappings[i];
	if (port <= 0) return;
	if (m.local_port != port)
		m.need_update = true;

	m.local_port = port;
	// prefer the same external port as the local port
	if (m.external_port == 0) m.external_port = port;

	if (m_currently_mapping == -1)
	{
		// the socket is not currently in use
		// send out a mapping request
		m_retry_count = 0;
		send_map_request(i);
		m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16)
			, m_remote, bind(&natpmp::on_reply, self(), _1, _2));
	}
}

void natpmp::send_map_request(int i) try
{
	using namespace libtorrent::detail;

	TORRENT_ASSERT(m_currently_mapping == -1
		|| m_currently_mapping == i);
	m_currently_mapping = i;
	mapping& m = m_mappings[i];
	char buf[12];
	char* out = buf;
	write_uint8(0, out); // NAT-PMP version
	write_uint8(m.protocol, out); // map "protocol"
	write_uint16(0, out); // reserved
	write_uint16(m.local_port, out); // private port
	write_uint16(m.external_port, out); // requested public port
	int ttl = m.external_port == 0 ? 0 : 3600;
	write_uint32(ttl, out); // port mapping lifetime

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " ==> port map request: " << (m.protocol == 1 ? "udp" : "tcp")
		<< " local: " << m.local_port << " external: " << m.external_port
		<< " ttl: " << ttl << std::endl;
#endif

	m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint);
	// linear back-off instead of exponential
	++m_retry_count;
	m_send_timer.expires_from_now(milliseconds(250 * m_retry_count));
	m_send_timer.async_wait(bind(&natpmp::resend_request, self(), i, _1));
}
catch (std::exception& e)
{
	std::string err = e.what();
};

void natpmp::resend_request(int i, asio::error_code const& e)
{
	if (e) return;
	if (m_currently_mapping != i) return;
	if (m_retry_count >= 9)
	{
		m_mappings[i].need_update = false;
		// try again in two hours
		m_mappings[i].expires = time_now() + hours(2);
		return;
	}
	send_map_request(i);
}

void natpmp::on_reply(asio::error_code const& e
	, std::size_t bytes_transferred)
{
	using namespace libtorrent::detail;
	if (e) return;

	try
	{

		if (m_remote != m_nat_endpoint)
		{
			m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16)
				, m_remote, bind(&natpmp::on_reply, self(), _1, _2));
			return;
		}

		m_send_timer.cancel();

		TORRENT_ASSERT(m_currently_mapping >= 0);
		int i = m_currently_mapping;
		mapping& m = m_mappings[i];

		char* in = m_response_buffer;
		int version = read_uint8(in);
		int cmd = read_uint8(in);
		int result = read_uint16(in);
		int time = read_uint32(in);
		int private_port = read_uint16(in);
		int public_port = read_uint16(in);
		int lifetime = read_uint32(in);

		(void)time; // to remove warning

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		m_log << time_now_string()
			<< " <== port map response: " << (cmd - 128 == 1 ? "udp" : "tcp")
			<< " local: " << private_port << " external: " << public_port
			<< " ttl: " << lifetime << std::endl;
#endif

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		if (version != 0)
		{
			m_log << "*** unexpected version: " << version << std::endl;
		}
#endif

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		if (private_port != m.local_port)
		{
			m_log << "*** unexpected local port: " << private_port << std::endl;
		}
#endif

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		if (cmd != 128 + m.protocol)
		{
			m_log << "*** unexpected protocol: " << (cmd - 128) << std::endl;
		}
#endif

		if (public_port == 0 || lifetime == 0)
		{
			// this means the mapping was
			// successfully closed
			m.local_port = 0;
		}
		else
		{
			m.expires = time_now() + seconds(int(lifetime * 0.7f));
			m.external_port = public_port;
		}

		if (result != 0)
		{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
			m_log << "*** ERROR: " << result << std::endl;
#endif
			std::stringstream errmsg;
			errmsg << "NAT router reports error (" << result << ") ";
			switch (result)
			{
				case 1: errmsg << "Unsupported protocol version"; break;
				case 2: errmsg << "Not authorized to create port map (enable NAT-PMP on your router)"; break;
				case 3: errmsg << "Network failure"; break;
				case 4: errmsg << "Out of resources"; break;
				case 5: errmsg << "Unsupported opcode"; break;
			}
			throw std::runtime_error(errmsg.str());
		}

		// don't report when we remove mappings
		if (m.local_port != 0)
		{
			int tcp_port = 0;
			int udp_port = 0;
			if (m.protocol == 1) udp_port = m.external_port;
			else tcp_port = public_port;
			m_callback(tcp_port, udp_port, "");
		}
	}
	catch (std::exception& e)
	{
		// try again in two hours
		m_mappings[m_currently_mapping].expires = time_now() + hours(2);
		m_callback(0, 0, e.what());
	}
	int i = m_currently_mapping;
	m_currently_mapping = -1;
	m_mappings[i].need_update = false;
	m_send_timer.cancel();
	update_expiration_timer();
	try_next_mapping(i);
}

void natpmp::update_expiration_timer()
{
	ptime now = time_now();
	ptime min_expire = now + seconds(3600);
	int min_index = -1;
	for (int i = 0; i < num_mappings; ++i)
		if (m_mappings[i].expires < min_expire
			&& m_mappings[i].local_port != 0)
		{
			min_expire = m_mappings[i].expires;
			min_index = i;
		}

	if (min_index >= 0)
	{
		m_refresh_timer.expires_from_now(min_expire - now);
		m_refresh_timer.async_wait(bind(&natpmp::mapping_expired, self(), _1, min_index));
	}
}

void natpmp::mapping_expired(asio::error_code const& e, int i)
{
	if (e) return;
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << "*** mapping " << i << " expired, updating" << std::endl;
#endif
	refresh_mapping(i);
}

void natpmp::refresh_mapping(int i)
{
	m_mappings[i].need_update = true;
	if (m_currently_mapping == -1)
	{
		// the socket is not currently in use
		// send out a mapping request
		m_retry_count = 0;
		send_map_request(i);
		m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16)
			, m_remote, bind(&natpmp::on_reply, self(), _1, _2));
	}
}

void natpmp::try_next_mapping(int i)
{
	++i;
	if (i >= num_mappings) i = 0;
	if (m_mappings[i].need_update)
		refresh_mapping(i);
}

void natpmp::close()
{
	asio::error_code ec;
	m_socket.close(ec);
	if (m_disabled) return;
	for (int i = 0; i < num_mappings; ++i)
	{
		if (m_mappings[i].local_port == 0)
			continue;
		m_mappings[i].external_port = 0;
		refresh_mapping(i);
	}
	m_refresh_timer.cancel();
	m_send_timer.cancel();
}

<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  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 Willow Garage, Inc. 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.
 *
 * $Id$
 *
 */

#ifdef WIN32
#pragma optimize("g", off)
#endif //WIN32

#include <pcl/impl/instantiate.hpp>
#include <pcl/point_types.h>
#include <pcl/surface/poisson.h>
#include <pcl/surface/impl/poisson.hpp>

// Instantiations of specific point types
PCL_INSTANTIATE(Poisson, (pcl::PointNormal)(pcl::PointXYZRGBNormal)(pcl::PointXYZINormal))

<commit_msg>Enable optimizations, bug 717 is fixed.<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  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 Willow Garage, Inc. 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.
 *
 * $Id$
 *
 */

#include <pcl/impl/instantiate.hpp>
#include <pcl/point_types.h>
#include <pcl/surface/poisson.h>
#include <pcl/surface/impl/poisson.hpp>

// Instantiations of specific point types
PCL_INSTANTIATE(Poisson, (pcl::PointNormal)(pcl::PointXYZRGBNormal)(pcl::PointXYZINormal))
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: reqitem.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2000-12-07 14:00:05 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _REQITEM_HXX
#define _REQITEM_HXX

#ifndef _SOLAR_H
#include <solar.h>
#endif

#ifndef _RTTI_HXX
#include <rtti.hxx>
#endif

#if _SOLAR__PRIVATE
#include "poolitem.hxx"
#else
#include <sfxipool.hxx>
#endif

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

class SfxRequestItem: public SfxSetItem

/** [Description]

    Represents a function call with optional arguments.
*/

{
public:
                                TYPEINFO();
                                SfxRequestItem();
                                SfxRequestItem( USHORT nWhich, SvStream & );
                                SfxRequestItem( const SfxRequestItem& );
                                ~SfxRequestItem();

    virtual int                 operator==( const SfxPoolItem& ) const;
    virtual
    virtual SfxPoolItem*        Clone( SfxItemPool *pPool = 0 ) const;
    virtual SfxPoolItem*        Create(SvStream &, USHORT nItemVersion) const;
    virtual SvStream&           Store(SvStream &, USHORT nItemVersion ) const;
};

#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.1106); FILE MERGED 2005/09/05 14:51:00 rt 1.2.1106.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: reqitem.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 10:10:13 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _REQITEM_HXX
#define _REQITEM_HXX

#ifndef _SOLAR_H
#include <solar.h>
#endif

#ifndef _RTTI_HXX
#include <rtti.hxx>
#endif

#if _SOLAR__PRIVATE
#include "poolitem.hxx"
#else
#include <sfxipool.hxx>
#endif

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

class SfxRequestItem: public SfxSetItem

/** [Description]

    Represents a function call with optional arguments.
*/

{
public:
                                TYPEINFO();
                                SfxRequestItem();
                                SfxRequestItem( USHORT nWhich, SvStream & );
                                SfxRequestItem( const SfxRequestItem& );
                                ~SfxRequestItem();

    virtual int                 operator==( const SfxPoolItem& ) const;
    virtual
    virtual SfxPoolItem*        Clone( SfxItemPool *pPool = 0 ) const;
    virtual SfxPoolItem*        Create(SvStream &, USHORT nItemVersion) const;
    virtual SvStream&           Store(SvStream &, USHORT nItemVersion ) const;
};

#endif

<|endoftext|>


<commit_before>#include "parquet/parquet.h"
#include "encodings.h"

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

#include <thrift/protocol/TDebugProtocol.h>

const int DATA_PAGE_SIZE = 64 * 1024;

using namespace boost;
using namespace parquet;
using namespace std;

namespace parquet_cpp {

InMemoryInputStream::InMemoryInputStream(const uint8_t* buffer, int64_t len) :
  buffer_(buffer), len_(len), offset_(0) {
}

const uint8_t* InMemoryInputStream::Peek(int num_to_peek, int* num_bytes) {
  *num_bytes = ::min(static_cast<int64_t>(num_to_peek), len_ - offset_);
  return buffer_ + offset_;
}

const uint8_t* InMemoryInputStream::Read(int num_to_read, int* num_bytes) {
  const uint8_t* result = Peek(num_to_read, num_bytes);
  offset_ += *num_bytes;
  return result;
}

ColumnReader::ColumnReader(const ColumnMetaData* metadata,
    const SchemaElement* schema, InputStream* stream)
  : metadata_(metadata),
    schema_(schema),
    stream_(stream),
    current_decoder_(NULL),
    num_buffered_values_(0),
    num_decoded_values_(0),
    buffered_values_offset_(0) {
  int value_byte_size;
  switch (metadata->type) {
    case parquet::Type::BOOLEAN:
      value_byte_size = 1;
      break;
    case parquet::Type::INT32:
      value_byte_size = sizeof(int32_t);
      break;
    case parquet::Type::INT64:
      value_byte_size = sizeof(int64_t);
      break;
    case parquet::Type::FLOAT:
      value_byte_size = sizeof(float);
      break;
    case parquet::Type::DOUBLE:
      value_byte_size = sizeof(double);
      break;
    case parquet::Type::BYTE_ARRAY:
      value_byte_size = sizeof(ByteArray);
      break;
    default:
      ParquetException::NYI();
  }

  if (metadata->codec != CompressionCodec::UNCOMPRESSED) ParquetException::NYI();
  config_ = Config::DefaultConfig();
  values_buffer_.resize(config_.batch_size * value_byte_size);
}

void ColumnReader::BatchDecode() {
  buffered_values_offset_ = 0;
  uint8_t* buf= &values_buffer_[0];
  int batch_size = config_.batch_size;
  switch (metadata_->type) {
    case parquet::Type::BOOLEAN:
      num_decoded_values_ =
          current_decoder_->GetBool(reinterpret_cast<bool*>(buf), batch_size);
      break;
    case parquet::Type::INT32:
      num_decoded_values_ =
          current_decoder_->GetInt32(reinterpret_cast<int32_t*>(buf), batch_size);
      break;
    case parquet::Type::INT64:
      num_decoded_values_ =
          current_decoder_->GetInt64(reinterpret_cast<int64_t*>(buf), batch_size);
      break;
    case parquet::Type::FLOAT:
      num_decoded_values_ =
          current_decoder_->GetFloat(reinterpret_cast<float*>(buf), batch_size);
      break;
    case parquet::Type::DOUBLE:
      num_decoded_values_ =
          current_decoder_->GetDouble(reinterpret_cast<double*>(buf), batch_size);
      break;
    case parquet::Type::BYTE_ARRAY:
      num_decoded_values_ =
          current_decoder_->GetByteArray(reinterpret_cast<ByteArray*>(buf), batch_size);
      break;
    default:
      ParquetException::NYI();
  }
}

// PLAIN_DICTIONARY is deprecated but used to be used as a dictionary index
// encoding.
static bool IsDictionaryIndexEncoding(const Encoding::type& e) {
  return e == Encoding::RLE_DICTIONARY || e == Encoding::PLAIN_DICTIONARY;
}

bool ColumnReader::ReadNewPage() {
  // Loop until we find the next data page.
  while (true) {
    int bytes_read = 0;
    const uint8_t* buffer = stream_->Peek(DATA_PAGE_SIZE, &bytes_read);
    if (bytes_read == 0) return false;
    uint32_t header_size = bytes_read;
    DeserializeThriftMsg(buffer, &header_size, &current_page_header_);
    stream_->Read(header_size, &bytes_read);

    // TODO: handle decompression.
    int uncompressed_len = current_page_header_.uncompressed_page_size;
    buffer = stream_->Read(uncompressed_len, &bytes_read);
    if (bytes_read != uncompressed_len) ParquetException::EofException();

    if (current_page_header_.type == PageType::DICTIONARY_PAGE) {
      unordered_map<Encoding::type, shared_ptr<Decoder> >::iterator it =
          decoders_.find(Encoding::RLE_DICTIONARY);
      if (it != decoders_.end()) {
        throw ParquetException("Column cannot have more than one dictionary.");
      }

      PlainDecoder dictionary(schema_);
      dictionary.SetData(current_page_header_.dictionary_page_header.num_values,
          buffer, uncompressed_len);
      shared_ptr<Decoder> decoder(new DictionaryDecoder(schema_, &dictionary));
      decoders_[Encoding::RLE_DICTIONARY] = decoder;
      current_decoder_ = decoders_[Encoding::RLE_DICTIONARY].get();
      continue;
    } else if (current_page_header_.type == PageType::DATA_PAGE) {
      // Read a data page.
      num_buffered_values_ = current_page_header_.data_page_header.num_values;

      // Read definition levels.
      if (schema_->repetition_type != FieldRepetitionType::REQUIRED) {
        int num_definition_bytes = *reinterpret_cast<const uint32_t*>(buffer);
        buffer += sizeof(uint32_t);
        definition_level_decoder_.reset(
            new impala::RleDecoder(buffer, num_definition_bytes, 1));
        buffer += num_definition_bytes;
        uncompressed_len -= sizeof(uint32_t);
        uncompressed_len -= num_definition_bytes;
      }

      // TODO: repetition levels

      // Get a decoder object for this page or create a new decoder if this is the
      // first page with this encoding.
      Encoding::type encoding = current_page_header_.data_page_header.encoding;
      if (IsDictionaryIndexEncoding(encoding)) encoding = Encoding::RLE_DICTIONARY;

      unordered_map<Encoding::type, shared_ptr<Decoder> >::iterator it =
          decoders_.find(encoding);
      if (it != decoders_.end()) {
        current_decoder_ = it->second.get();
      } else {
        switch (encoding) {
          case Encoding::PLAIN: {
            shared_ptr<Decoder> decoder;
            if (schema_->type == Type::BOOLEAN) {
              decoder.reset(new BoolDecoder(schema_));
            } else {
              shared_ptr<Decoder> decoder(new PlainDecoder(schema_));
            }
            decoders_[encoding] = decoder;
            current_decoder_ = decoder.get();
            break;
          }
          case Encoding::RLE_DICTIONARY:
            throw ParquetException("Dictionary page must be before data page.");

          case Encoding::DELTA_BINARY_PACKED:
          case Encoding::DELTA_LENGTH_BYTE_ARRAY:
          case Encoding::DELTA_BYTE_ARRAY:
            ParquetException::NYI();

          default:
            throw ParquetException("Unknown encoding type.");
        }
      }
      current_decoder_->SetData(num_buffered_values_, buffer, uncompressed_len);
    } else {
      // We don't know what this page type is. We're allowed to skip non-data pages.
      continue;
    }
  }
  return true;
}

}

<commit_msg>fix core-dump while reading PLAIN_ENCODING; fix readNewPage to return page instead of the last one<commit_after>#include "parquet/parquet.h"
#include "encodings.h"

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

#include <thrift/protocol/TDebugProtocol.h>

const int DATA_PAGE_SIZE = 64 * 1024;

using namespace boost;
using namespace parquet;
using namespace std;

namespace parquet_cpp {

InMemoryInputStream::InMemoryInputStream(const uint8_t* buffer, int64_t len) :
  buffer_(buffer), len_(len), offset_(0) {
}

const uint8_t* InMemoryInputStream::Peek(int num_to_peek, int* num_bytes) {
  *num_bytes = ::min(static_cast<int64_t>(num_to_peek), len_ - offset_);
  return buffer_ + offset_;
}

const uint8_t* InMemoryInputStream::Read(int num_to_read, int* num_bytes) {
  const uint8_t* result = Peek(num_to_read, num_bytes);
  offset_ += *num_bytes;
  return result;
}

ColumnReader::ColumnReader(const ColumnMetaData* metadata,
    const SchemaElement* schema, InputStream* stream)
  : metadata_(metadata),
    schema_(schema),
    stream_(stream),
    current_decoder_(NULL),
    num_buffered_values_(0),
    num_decoded_values_(0),
    buffered_values_offset_(0) {
  int value_byte_size;
  switch (metadata->type) {
    case parquet::Type::BOOLEAN:
      value_byte_size = 1;
      break;
    case parquet::Type::INT32:
      value_byte_size = sizeof(int32_t);
      break;
    case parquet::Type::INT64:
      value_byte_size = sizeof(int64_t);
      break;
    case parquet::Type::FLOAT:
      value_byte_size = sizeof(float);
      break;
    case parquet::Type::DOUBLE:
      value_byte_size = sizeof(double);
      break;
    case parquet::Type::BYTE_ARRAY:
      value_byte_size = sizeof(ByteArray);
      break;
    default:
      ParquetException::NYI();
  }

  if (metadata->codec != CompressionCodec::UNCOMPRESSED) ParquetException::NYI();
  config_ = Config::DefaultConfig();
  values_buffer_.resize(config_.batch_size * value_byte_size);
}

void ColumnReader::BatchDecode() {
  buffered_values_offset_ = 0;
  uint8_t* buf= &values_buffer_[0];
  int batch_size = config_.batch_size;
  switch (metadata_->type) {
    case parquet::Type::BOOLEAN:
      num_decoded_values_ =
          current_decoder_->GetBool(reinterpret_cast<bool*>(buf), batch_size);
      break;
    case parquet::Type::INT32:
      num_decoded_values_ =
          current_decoder_->GetInt32(reinterpret_cast<int32_t*>(buf), batch_size);
      break;
    case parquet::Type::INT64:
      num_decoded_values_ =
          current_decoder_->GetInt64(reinterpret_cast<int64_t*>(buf), batch_size);
      break;
    case parquet::Type::FLOAT:
      num_decoded_values_ =
          current_decoder_->GetFloat(reinterpret_cast<float*>(buf), batch_size);
      break;
    case parquet::Type::DOUBLE:
      num_decoded_values_ =
          current_decoder_->GetDouble(reinterpret_cast<double*>(buf), batch_size);
      break;
    case parquet::Type::BYTE_ARRAY:
      num_decoded_values_ =
          current_decoder_->GetByteArray(reinterpret_cast<ByteArray*>(buf), batch_size);
      break;
    default:
      ParquetException::NYI();
  }
}

// PLAIN_DICTIONARY is deprecated but used to be used as a dictionary index
// encoding.
static bool IsDictionaryIndexEncoding(const Encoding::type& e) {
  return e == Encoding::RLE_DICTIONARY || e == Encoding::PLAIN_DICTIONARY;
}

bool ColumnReader::ReadNewPage() {
  // Loop until we find the next data page.

  while (true) {
    int bytes_read = 0;
    const uint8_t* buffer = stream_->Peek(DATA_PAGE_SIZE, &bytes_read);
    if (bytes_read == 0) return false;
    uint32_t header_size = bytes_read;
    DeserializeThriftMsg(buffer, &header_size, &current_page_header_);
    stream_->Read(header_size, &bytes_read);

    // TODO: handle decompression.
    int uncompressed_len = current_page_header_.uncompressed_page_size;
    buffer = stream_->Read(uncompressed_len, &bytes_read);
    if (bytes_read != uncompressed_len) ParquetException::EofException();

    if (current_page_header_.type == PageType::DICTIONARY_PAGE) {
      unordered_map<Encoding::type, shared_ptr<Decoder> >::iterator it =
          decoders_.find(Encoding::RLE_DICTIONARY);
      if (it != decoders_.end()) {
        throw ParquetException("Column cannot have more than one dictionary.");
      }

      PlainDecoder dictionary(schema_);
      dictionary.SetData(current_page_header_.dictionary_page_header.num_values,
          buffer, uncompressed_len);
      shared_ptr<Decoder> decoder(new DictionaryDecoder(schema_, &dictionary));
      decoders_[Encoding::RLE_DICTIONARY] = decoder;
      current_decoder_ = decoders_[Encoding::RLE_DICTIONARY].get();
      continue;
    } else if (current_page_header_.type == PageType::DATA_PAGE) {
      // Read a data page.
      num_buffered_values_ = current_page_header_.data_page_header.num_values;

      // Read definition levels.
      if (schema_->repetition_type != FieldRepetitionType::REQUIRED) {
        int num_definition_bytes = *reinterpret_cast<const uint32_t*>(buffer);
        buffer += sizeof(uint32_t);
        definition_level_decoder_.reset(
            new impala::RleDecoder(buffer, num_definition_bytes, 1));
        buffer += num_definition_bytes;
        uncompressed_len -= sizeof(uint32_t);
        uncompressed_len -= num_definition_bytes;
      }

      // TODO: repetition levels

      // Get a decoder object for this page or create a new decoder if this is the
      // first page with this encoding.
      Encoding::type encoding = current_page_header_.data_page_header.encoding;
      if (IsDictionaryIndexEncoding(encoding)) encoding = Encoding::RLE_DICTIONARY;

      unordered_map<Encoding::type, shared_ptr<Decoder> >::iterator it =
          decoders_.find(encoding);
      if (it != decoders_.end()) {
        current_decoder_ = it->second.get();
      } else {
        switch (encoding) {
          case Encoding::PLAIN: {
            shared_ptr<Decoder> decoder;
            if (schema_->type == Type::BOOLEAN) {
              decoder.reset(new BoolDecoder(schema_));
            } else {
              decoder.reset(new PlainDecoder(schema_));
            }
            decoders_[encoding] = decoder;
            current_decoder_ = decoder.get();
            break;
          }
          case Encoding::RLE_DICTIONARY:
            throw ParquetException("Dictionary page must be before data page.");

          case Encoding::DELTA_BINARY_PACKED:
          case Encoding::DELTA_LENGTH_BYTE_ARRAY:
          case Encoding::DELTA_BYTE_ARRAY:
            ParquetException::NYI();

          default:
            throw ParquetException("Unknown encoding type.");
        }
      }
      current_decoder_->SetData(num_buffered_values_, buffer, uncompressed_len);
      return true;
    } else {
      // We don't know what this page type is. We're allowed to skip non-data pages.
      continue;
    }
  }
  return true;
}

}

<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <QUrl>
#include <QFileInfo>
#include "kernel.h"
#include "ilwisdata.h"
#include "resource.h"
#include "identity.h"
#include "OperationExpression.h"
#include "operationmetadata.h"
#include "operation.h"
#include "commandhandler.h"
#include "script.h"
#include "parserlexer/IlwisScriptLexer.h"
#include "parserlexer/IlwisScriptParser.h"
#include "symboltable.h"

using namespace Ilwis;
OperationImplementation *Script::create(quint64 metaid, const Ilwis::OperationExpression &expr)
{
    return new Script(metaid, expr);
}

Script::Script()
{
}

Script::Script(quint64 metaid,const Ilwis::OperationExpression &expr) : OperationImplementation(metaid, expr)
{
}

OperationImplementation::State Script::prepare() {
    QString txt = _expression.parm(0).value();
    QUrl url(txt);
    if ( url.isValid() && url.scheme() == "file") {
        QFileInfo inf( url.toLocalFile());
        bool exists = inf.exists();
        if (exists && inf.suffix() == "isf") {
            std::ifstream in(inf.absoluteFilePath().toLatin1(), std::ios_base::in);
            if(in.is_open() && in.good()) {
                _bufferSize = inf.size();
                _buffer.reset(new char[_bufferSize + 1]);
                in.read(_buffer.get(), _bufferSize) ;
                return sPREPARED;
            }
        } else {
            return sPREPAREFAILED;
        }
    } else {
        return sPREPARED;
    }

    return sNOTPREPARED;
}

bool Script::execute(ExecutionContext *ctx)
{
    if (_prepState == sNOTPREPARED)
        if((_prepState = prepare()) != sPREPARED)
            return false;

    ANTLR3_UINT8 * bufferData = (ANTLR3_UINT8 *) _buffer.get();
    for(int i=0; i < _bufferSize; ++i) {
        if ( bufferData[i] == '\n') { //replace newlines with ; which are the actual seperators
            bufferData[i]=';';
        }
    }
    if ( bufferData[_bufferSize - 1] != ';')
        bufferData[_bufferSize - 1] = ';';

    pANTLR3_INPUT_STREAM input = antlr3StringStreamNew(bufferData,  ANTLR3_ENC_8BIT,  _bufferSize, (pANTLR3_UINT8)"ScriptText");
    if(input == NULL)
        return false;

    pilwisscriptLexer lxr = ilwisscriptLexerNew(input);
    if(lxr == NULL)
        return false;

    //Creates an empty token stream.
    pANTLR3_COMMON_TOKEN_STREAM tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr));
    if(tstream == NULL)
        return false;

    //Creates a parser.
    pilwisscriptParser psr = ilwisscriptParserNew(tstream);
    if(psr == NULL)
        return false;

    //Run the parser rule. This also runs the lexer to create the token stream.
    ASTNode *scr = psr->script(psr);
    SymbolTable symbols;
    bool ok = scr->evaluate(symbols, 1000);
    return ok;

}

quint64 Script::createMetadata()
{
    QString urlTxt = QString("ilwis://operations/script");
    QUrl url(urlTxt);
    Resource res(url, itOPERATIONMETADATA);
    res.addProperty("namespace","ilwis");
    res.addProperty("longname","ilwisscript");
    res.addProperty("inparameters",1);
    res.addProperty("pin_1_type", itFILE | itSTRING);
    res.addProperty("pin_1_name", TR("input script file"));
    res.addProperty("pin_1_domain","none");
    res.addProperty("pin_1_desc",TR("input file containing script commands"));
    res.addProperty("outparameters",1);
    res.addProperty("pout_1_type", itBOOL);
    res.addProperty("pout_1_name", TR("succes"));
    res.addProperty("pout_1_domain","bool");
    res.addProperty("pout_1_desc",TR("returns the succes of the execution of the script"));

    res.prepare();
    urlTxt += "=" + QString::number(res.id());
    res.setUrl(QUrl(urlTxt));
//    IOperationMetaData md;
//    if(!md.prepare(res)) {
//        return i64UNDEF;
//    }
    mastercatalog()->addItems({res});
    return res.id();
}
<commit_msg>modified metadata<commit_after>#include <iostream>
#include <fstream>
#include <QUrl>
#include <QFileInfo>
#include "kernel.h"
#include "ilwisdata.h"
#include "resource.h"
#include "identity.h"
#include "OperationExpression.h"
#include "operationmetadata.h"
#include "operation.h"
#include "commandhandler.h"
#include "script.h"
#include "parserlexer/IlwisScriptLexer.h"
#include "parserlexer/IlwisScriptParser.h"
#include "symboltable.h"

using namespace Ilwis;
OperationImplementation *Script::create(quint64 metaid, const Ilwis::OperationExpression &expr)
{
    return new Script(metaid, expr);
}

Script::Script()
{
}

Script::Script(quint64 metaid,const Ilwis::OperationExpression &expr) : OperationImplementation(metaid, expr)
{
}

OperationImplementation::State Script::prepare() {
    QString txt = _expression.parm(0).value();
    QUrl url(txt);
    if ( url.isValid() && url.scheme() == "file") {
        QFileInfo inf( url.toLocalFile());
        bool exists = inf.exists();
        if (exists && inf.suffix() == "isf") {
            std::ifstream in(inf.absoluteFilePath().toLatin1(), std::ios_base::in);
            if(in.is_open() && in.good()) {
                _bufferSize = inf.size();
                _buffer.reset(new char[_bufferSize + 1]);
                in.read(_buffer.get(), _bufferSize) ;
                return sPREPARED;
            }
        } else {
            return sPREPAREFAILED;
        }
    } else {
        return sPREPARED;
    }

    return sNOTPREPARED;
}

bool Script::execute(ExecutionContext *ctx)
{
    if (_prepState == sNOTPREPARED)
        if((_prepState = prepare()) != sPREPARED)
            return false;

    ANTLR3_UINT8 * bufferData = (ANTLR3_UINT8 *) _buffer.get();
    for(int i=0; i < _bufferSize; ++i) {
        if ( bufferData[i] == '\n') { //replace newlines with ; which are the actual seperators
            bufferData[i]=';';
        }
    }
    if ( bufferData[_bufferSize - 1] != ';')
        bufferData[_bufferSize - 1] = ';';

    pANTLR3_INPUT_STREAM input = antlr3StringStreamNew(bufferData,  ANTLR3_ENC_8BIT,  _bufferSize, (pANTLR3_UINT8)"ScriptText");
    if(input == NULL)
        return false;

    pilwisscriptLexer lxr = ilwisscriptLexerNew(input);
    if(lxr == NULL)
        return false;

    //Creates an empty token stream.
    pANTLR3_COMMON_TOKEN_STREAM tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr));
    if(tstream == NULL)
        return false;

    //Creates a parser.
    pilwisscriptParser psr = ilwisscriptParserNew(tstream);
    if(psr == NULL)
        return false;

    //Run the parser rule. This also runs the lexer to create the token stream.
    ASTNode *scr = psr->script(psr);
    SymbolTable symbols;
    bool ok = scr->evaluate(symbols, 1000);
    return ok;

}

quint64 Script::createMetadata()
{
    QString urlTxt = QString("ilwis://operations/script");
    QUrl url(urlTxt);
    Resource res(url, itOPERATIONMETADATA);
    res.addProperty("namespace","ilwis");
    res.addProperty("longname","ilwisscript");
    res.addProperty("inparameters","1");
    res.addProperty("pin_1_type", itFILE | itSTRING);
    res.addProperty("pin_1_name", TR("input script file"));
    res.addProperty("pin_1_domain","none");
    res.addProperty("pin_1_desc",TR("input file containing script commands"));
    res.addProperty("outparameters",1);
    res.addProperty("pout_1_type", itBOOL);
    res.addProperty("pout_1_name", TR("succes"));
    res.addProperty("pout_1_domain","bool");
    res.addProperty("pout_1_desc",TR("returns the succes of the execution of the script"));

    res.prepare();
    urlTxt += "=" + QString::number(res.id());
    res.setUrl(QUrl(urlTxt));
//    IOperationMetaData md;
//    if(!md.prepare(res)) {
//        return i64UNDEF;
//    }
    mastercatalog()->addItems({res});
    return res.id();
}
<|endoftext|>


<commit_before>//===-- OsLogger.cpp --------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "OsLogger.h"

#if LLDB_USE_OS_LOG

#include <os/log.h>

#include "DNBDefs.h"
#include "DNBLog.h"

#define LLDB_OS_LOG_MAX_BUFFER_LENGTH 256

namespace {
//----------------------------------------------------------------------
// Darwin os_log logging callback that can be registered with
// DNBLogSetLogCallback
//----------------------------------------------------------------------
void DarwinLogCallback(void *baton, uint32_t flags, const char *format,
                       va_list args) {
  if (format == nullptr)
    return;

  static os_log_t g_logger;
  if (!g_logger) {
    g_logger = os_log_create("com.apple.dt.lldb", "debugserver");
    if (!g_logger)
      return;
  }

  os_log_type_t log_type;
  if (flags & DNBLOG_FLAG_FATAL)
    log_type = OS_LOG_TYPE_FAULT;
  else if (flags & DNBLOG_FLAG_ERROR)
    log_type = OS_LOG_TYPE_ERROR;
  else if (flags & DNBLOG_FLAG_WARNING)
    log_type = OS_LOG_TYPE_DEFAULT;
  else if (flags & DNBLOG_FLAG_VERBOSE)
    log_type = OS_LOG_TYPE_DEBUG;
  else
    log_type = OS_LOG_TYPE_DEFAULT;

  // This code is unfortunate.  os_log* only takes static strings, but
  // our current log API isn't set up to make use of that style.
  char buffer[LLDB_OS_LOG_MAX_BUFFER_LENGTH];
  vsnprintf(buffer, sizeof(buffer), format, args);
  os_log_with_type(g_logger, log_type, "%{public}s", buffer);
}
}

DNBCallbackLog OsLogger::GetLogFunction() {
  return _os_log_impl ? DarwinLogCallback : nullptr;
}

#else

DNBCallbackLog OsLogger::GetLogFunction() { return nullptr; }

#endif
<commit_msg>Conditionalized OsLogger.cpp on a modern SDK.<commit_after>//===-- OsLogger.cpp --------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "OsLogger.h"
#include <Availability.h>

#if (LLDB_USE_OS_LOG) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 101200)

#include <os/log.h>

#include "DNBDefs.h"
#include "DNBLog.h"

#define LLDB_OS_LOG_MAX_BUFFER_LENGTH 256

namespace {
//----------------------------------------------------------------------
// Darwin os_log logging callback that can be registered with
// DNBLogSetLogCallback
//----------------------------------------------------------------------
void DarwinLogCallback(void *baton, uint32_t flags, const char *format,
                       va_list args) {
  if (format == nullptr)
    return;

  static os_log_t g_logger;
  if (!g_logger) {
    g_logger = os_log_create("com.apple.dt.lldb", "debugserver");
    if (!g_logger)
      return;
  }

  os_log_type_t log_type;
  if (flags & DNBLOG_FLAG_FATAL)
    log_type = OS_LOG_TYPE_FAULT;
  else if (flags & DNBLOG_FLAG_ERROR)
    log_type = OS_LOG_TYPE_ERROR;
  else if (flags & DNBLOG_FLAG_WARNING)
    log_type = OS_LOG_TYPE_DEFAULT;
  else if (flags & DNBLOG_FLAG_VERBOSE)
    log_type = OS_LOG_TYPE_DEBUG;
  else
    log_type = OS_LOG_TYPE_DEFAULT;

  // This code is unfortunate.  os_log* only takes static strings, but
  // our current log API isn't set up to make use of that style.
  char buffer[LLDB_OS_LOG_MAX_BUFFER_LENGTH];
  vsnprintf(buffer, sizeof(buffer), format, args);
  os_log_with_type(g_logger, log_type, "%{public}s", buffer);
}
}

DNBCallbackLog OsLogger::GetLogFunction() {
  return _os_log_impl ? DarwinLogCallback : nullptr;
}

#else

DNBCallbackLog OsLogger::GetLogFunction() { return nullptr; }

#endif

<|endoftext|>


<commit_before>#include "./parser.hpp"

using namespace json;

int Parser::parseFile (const std::string fileName, JsonTree& tree, bool verbs) {
  errors.resize (0);
  warnings.resize (0);
  verbose = verbs;
  int returnValue = OK;
  parseIndex = 0;
  if (openFile(fileName)) {
    std::stringstream buffer;
    buffer << getFile().rdbuf();
    content = buffer.str();
    std::string empty ("");
    struct timespec start, end;
    clock_gettime(CLOCK_MONOTONIC_RAW, &start);
    ObjectNameFlag result = parseExpectingElement (empty);
    clock_gettime(CLOCK_MONOTONIC_RAW, &end);
    file.close();
    tree.setTop (result.element);
    if (result.flag == EMPTY)
      return EMPTY_FILE;
    if (hasWarnings())
      returnValue += WARNINGS;
    if (hasErrors()) {
      returnValue += ERRORS;
      return returnValue & (INT_MAX - 1); // removes the OK flag
    }
  } else {
    return CANT_OPEN_FILE;
  }
  return returnValue;
}

int Parser::parseString (std::string cnt, JsonTree& tree, bool verbs ) {
  verbose = verbs;
  content = cnt;
  errors.resize (0);
  warnings.resize (0);
  std::string empty ("");
  int returnValue = OK;
  ObjectNameFlag result = parseExpectingElement (empty);
  tree.setTop (result.element);
  if (result.flag == EMPTY)
     return EMPTY_FILE;
  if (hasWarnings())
    returnValue += WARNINGS;
  if (hasErrors()) {
     returnValue += ERRORS;
    return returnValue & (INT_MAX - 1); // removes the OK flag
  }
  return returnValue;
}

Parser::Parser () :
  errors (0),
  warnings (0),
  parseIndex (0)
  {}

bool Parser::openFile (std::string fileName) {
  file.open(fileName, std::ifstream::in);
  if (file.is_open())
    return true;
  else
    return false;
}

bool Parser::hasComma () {
  removeFirstBlanks();
  if(content[parseIndex] == ',') {
    parseIndex++;
    return true;
  } else {
    return false;
  }
}

Parser::ObjectNameFlag Parser::parseVector (std::string path) {
  ObjectVector* obj = new ObjectVector ();
  ObjectNameFlag aux;
  int flag = REGULAR_ELEMENT;
  int i = 0;
  do {
    aux = parseExpectingElement (path + "." + std::to_string(i));
    if (aux.flag == EMPTY) {
      evaluateFlag(EMPTY, path, aux.key);
      break;
    }
    if (!obj->insert (aux.key, aux.element)) {
      evaluateFlag(INVALID_KEY, path, aux.key);
      break;
    }
    i++;
    removeFirstBlanks();
  } while (content[parseIndex] != ']' && aux.flag == REGULAR_ELEMENT);
  if (aux.flag == REGULAR_ELEMENT) {
    flag = EXPECTED_MORE;
    evaluateFlag(flag, path, aux.key);
  } else if (content[parseIndex] == ']') { 													// has matched
    parseIndex++;
    flag = hasComma();
  } else {
    flag = NO_CLOSED;
    evaluateFlag(flag, path, aux.key);
  }
  return {obj, "", flag};
}

Parser::ObjectNameFlag Parser::parseMap (std::string path) {
  ObjectMap* obj = new ObjectMap ();
  int flag = REGULAR_ELEMENT;
  ObjectNameFlag aux;

  do {
    aux = parseExpectingKeyDef (path);

    if (aux.flag == EMPTY) {
      evaluateFlag(EMPTY, path, aux.key);
      break;
    }
    if (!obj->insert (aux.key, aux.element)) {
      evaluateFlag(INVALID_KEY, path, aux.key);
      break;
    }
    removeFirstBlanks();
  } while (content[parseIndex] != '}' && aux.flag == REGULAR_ELEMENT);
  if (aux.flag == REGULAR_ELEMENT) {
    flag = EXPECTED_MORE;
    evaluateFlag(flag, path, aux.key);
  } else if (content[parseIndex] == '}') {
    parseIndex++;
    flag = hasComma();
  } else {
    flag = NO_CLOSED;
    evaluateFlag(flag, path, aux.key);
  }
  return {obj, "", flag};
}

void Parser::evaluateFlag (int flag, std::string path, std::string finalElement) {
  path.append("." + finalElement);
  if (flag < CONTROL_WARNING) {
    errors.push_back ({path, flag});
    if (verbose)
      std::cerr << "Error";
  } else {
    warnings.push_back ({path, flag});
    if (verbose)
      std::cerr << "Warning";
  }
  if (verbose)
    std::cerr << " parsing JSON: " << reverseflag[flag] << " in path: " << path << std::endl;
}

Parser::ObjectNameFlag Parser::parseExpectingKeyDef (std::string path) {
  removeFirstBlanks();
  if (content[parseIndex] == '\"') {
    parseIndex++;
    int from = parseIndex;
    while (content[parseIndex] != '\"') {
      parseIndex++;
    }
    std::string key (content.substr(from, parseIndex - from));
    while (content[parseIndex] != ':') {
      parseIndex++;
    }
    parseIndex++;
    ObjectNameFlag aux = parseExpectingElement (path + "." + key);
    return { aux.element, key, aux.flag };
  } else {
    return { nullptr, "", EMPTY};
  }
}

Parser::ObjectNameFlag Parser::parseQuote() {
  parseIndex++;
  std::string buff;
  char element = content[parseIndex];
  while (element != '\"') {
    buff.push_back(element);
    element = content[++parseIndex];
  }
  parseIndex++;
  return {new ObjectFinalString (buff), "", hasComma()};
}

Parser::ObjectNameFlag Parser::parseBool() {
  if (content.substr(parseIndex, 4) == "true") {
    parseIndex += 4;
    return {new ObjectFinalBool (true), "", hasComma()};
  } else if (content.substr(parseIndex, 5) == "false") {
    parseIndex += 5;
    return {new ObjectFinalBool (false), "", hasComma()};
  } else {
    return {nullptr, "", EXPECTED_KEY};
  }
}

Parser::ObjectNameFlag Parser::parseNumber() {
  std::string buff;
  bool end = false;
  while (!end && parseIndex < content.size()) {
    switch (content[parseIndex]) {
      case ' ':
        end = true;
        break;
      case '}':
        end = true;
        break;
      case ']':
        end = true;
        break;
      case ',':
        end = true;
        break;
      default:
        buff.push_back(content[parseIndex]);
        parseIndex++;
        break;
    }
  }
  if (!buff.empty()) {
    double number;
    try {
      number = stod (buff);
    }
    catch (std::invalid_argument e) {
      return {nullptr, "", INVALID_KEY};
    }
    return {new ObjectFinalNumberFloat (number), "", hasComma()};
  } else {
    return {nullptr, "", EMPTY};
  }
}

// Unpdate parseIndex position ignoring all blanks
void Parser::removeFirstBlanks() {
  int max = content.size();
  char element = content[parseIndex];
  while((element == ' ' || element == '\t'|| element == '\n' ) && parseIndex < max) {
    element = content[++parseIndex];
  }
}

Parser::ObjectNameFlag Parser::parseExpectingElement (std::string path) {
  removeFirstBlanks();
  switch (content[parseIndex]) {
    case '{':
      parseIndex++;
      removeFirstBlanks();
      return parseMap (path);
    case '[':
      parseIndex++;
      removeFirstBlanks();
      return parseVector (path);
    case '\"':
      return parseQuote();
    case 't':
      return parseBool();
    case 'f':
      return parseBool();
  }
  return parseNumber();
}

int Parser::saveFile (std::string fileName, JsonTree& tree, bool uglify) {
  std::ofstream file;
  file.open (fileName);
  if (!file.is_open())
    return CANT_OPEN_FILE;
  file << tree.toText(uglify);
  file.close ();
  return OK;
}
<commit_msg>Delete chrono<commit_after>#include "./parser.hpp"

using namespace json;

int Parser::parseFile (const std::string fileName, JsonTree& tree, bool verbs) {
  errors.resize (0);
  warnings.resize (0);
  verbose = verbs;
  int returnValue = OK;
  parseIndex = 0;
  if (openFile(fileName)) {
    std::stringstream buffer;
    buffer << getFile().rdbuf();
    content = buffer.str();
    ObjectNameFlag result = parseExpectingElement ("");
    file.close();
    tree.setTop (result.element);
    if (result.flag == EMPTY)
      return EMPTY_FILE;
    if (hasWarnings())
      returnValue += WARNINGS;
    if (hasErrors()) {
      returnValue += ERRORS;
      return returnValue & (INT_MAX - 1); // removes the OK flag
    }
  } else {
    return CANT_OPEN_FILE;
  }
  return returnValue;
}

int Parser::parseString (std::string cnt, JsonTree& tree, bool verbs ) {
  verbose = verbs;
  content = cnt;
  errors.resize (0);
  warnings.resize (0);
  parseIndex = 0;
  int returnValue = OK;
  ObjectNameFlag result = parseExpectingElement ("");
  tree.setTop (result.element);
  if (result.flag == EMPTY)
     return EMPTY_FILE;
  if (hasWarnings())
    returnValue += WARNINGS;
  if (hasErrors()) {
     returnValue += ERRORS;
    return returnValue & (INT_MAX - 1); // removes the OK flag
  }
  return returnValue;
}

Parser::Parser () :
  errors (0),
  warnings (0),
  parseIndex (0)
  {}

bool Parser::openFile (std::string fileName) {
  file.open(fileName, std::ifstream::in);
  if (file.is_open())
    return true;
  else
    return false;
}

bool Parser::hasComma () {
  removeFirstBlanks();
  if(content[parseIndex] == ',') {
    parseIndex++;
    return true;
  } else {
    return false;
  }
}

Parser::ObjectNameFlag Parser::parseVector (std::string path) {
  parseIndex++;
  ObjectVector* obj = new ObjectVector ();
  ObjectNameFlag aux;
  int flag = REGULAR_ELEMENT;
  unsigned i = 0;
  do {
    aux = parseExpectingElement (path + "." + std::to_string(i));
    if (aux.flag == EMPTY) {
      evaluateFlag(EMPTY, path, aux.key);
      break;
    }
    if (!obj->insert (aux.key, aux.element)) {
      evaluateFlag(INVALID_KEY, path, aux.key);
      break;
    }
    i++;
    removeFirstBlanks();
  } while (content[parseIndex] != ']' && aux.flag == REGULAR_ELEMENT);
  if (aux.flag == REGULAR_ELEMENT) {
    flag = EXPECTED_MORE;
    evaluateFlag(flag, path, aux.key);
  } else if (content[parseIndex] == ']') { 													// has matched
    parseIndex++;
    flag = hasComma();
  } else {
    flag = NO_CLOSED;
    evaluateFlag(flag, path, aux.key);
  }
  return {obj, "", flag};
}

Parser::ObjectNameFlag Parser::parseMap (std::string path) {
  parseIndex++;
  ObjectMap* obj = new ObjectMap ();
  int flag = REGULAR_ELEMENT;
  ObjectNameFlag aux;

  do {
    aux = parseExpectingKeyDef (path);

    if (aux.flag == EMPTY) {
      evaluateFlag(EMPTY, path, aux.key);
      break;
    }
    if (!obj->insert (aux.key, aux.element)) {
      evaluateFlag(INVALID_KEY, path, aux.key);
      break;
    }
    removeFirstBlanks();
  } while (content[parseIndex] != '}' && aux.flag == REGULAR_ELEMENT);
  if (aux.flag == REGULAR_ELEMENT) {
    flag = EXPECTED_MORE;
    evaluateFlag(flag, path, aux.key);
  } else if (content[parseIndex] == '}') {
    parseIndex++;
    flag = hasComma();
  } else {
    flag = NO_CLOSED;
    evaluateFlag(flag, path, aux.key);
  }
  return {obj, "", flag};
}

void Parser::evaluateFlag (int flag, std::string path, std::string finalElement) {
  path.append("." + finalElement);
  if (flag < CONTROL_WARNING) {
    errors.push_back ({path, flag});
    if (verbose)
      std::cerr << "Error";
  } else {
    warnings.push_back ({path, flag});
    if (verbose)
      std::cerr << "Warning";
  }
  if (verbose)
    std::cerr << " parsing JSON: " << reverseflag[flag] << " in path: " << path << std::endl;
}

Parser::ObjectNameFlag Parser::parseExpectingKeyDef (std::string path) {
  removeFirstBlanks();
  if (content[parseIndex] == '\"') {
    parseIndex++;
    int from = parseIndex;
    while (content[parseIndex] != '\"') {
      parseIndex++;
    }
    std::string key (content.substr(from, parseIndex - from));
    while (content[parseIndex] != ':') {
      parseIndex++;
    }
    parseIndex++;
    ObjectNameFlag aux = parseExpectingElement (path + "." + key);
    return { aux.element, key, aux.flag };
  } else {
    return { nullptr, "", EMPTY};
  }
}

Parser::ObjectNameFlag Parser::parseQuote() {
  parseIndex++;
  std::string buff;
  char element = content[parseIndex];
  while (element != '\"') {
    buff.push_back(element);
    element = content[++parseIndex];
  }
  parseIndex++;
  return {new ObjectFinalString (buff), "", hasComma()};
}

Parser::ObjectNameFlag Parser::parseBool() {
  if (content.substr(parseIndex, 4) == "true") {
    parseIndex += 4;
    return {new ObjectFinalBool (true), "", hasComma()};
  } else if (content.substr(parseIndex, 5) == "false") {
    parseIndex += 5;
    return {new ObjectFinalBool (false), "", hasComma()};
  } else {
    return {nullptr, "", EXPECTED_KEY};
  }
}

Parser::ObjectNameFlag Parser::parseNumber() {
  std::string buff;
  bool end = false;
  while (!end && parseIndex < content.size()) {
    switch (content[parseIndex]) {
      case ' ':
        end = true;
        break;
      case '}':
        end = true;
        break;
      case ']':
        end = true;
        break;
      case ',':
        end = true;
        break;
      default:
        buff.push_back(content[parseIndex]);
        parseIndex++;
        break;
    }
  }
  if (!buff.empty()) {
    double number;
    try {
      number = stod (buff);
    }
    catch (std::invalid_argument e) {
      return {nullptr, "", INVALID_KEY};
    }
    return {new ObjectFinalNumberFloat (number), "", hasComma()};
  } else {
    return {nullptr, "", EMPTY};
  }
}

// Updates parseIndex position ignoring all blanks
void Parser::removeFirstBlanks() {
  unsigned max = content.size();
  char element = content[parseIndex];
  while((element == ' ' || element == '\t'|| element == '\n' ) && parseIndex < max) {
    element = content[++parseIndex];
  }
}

Parser::ObjectNameFlag Parser::parseExpectingElement (std::string path) {
  removeFirstBlanks();
  switch (content[parseIndex]) {
    case '{':
      return parseMap (path);
    case '[':
      return parseVector (path);
    case '\"':
      return parseQuote();
    case 't':
      return parseBool();
    case 'f':
      return parseBool();
  }
  return parseNumber();
}

int Parser::saveFile (std::string fileName, JsonTree& tree, bool uglify) {
  std::ofstream file;
  file.open (fileName);
  if (!file.is_open())
    return CANT_OPEN_FILE;
  file << tree.toText(uglify);
  file.close ();
  return OK;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <QUrl>
#include <QFileInfo>
#include "kernel.h"
#include "ilwisdata.h"
#include "resource.h"
#include "identity.h"
#include "symboltable.h"
#include "operationExpression.h"
#include "operationmetadata.h"
#include "commandhandler.h"
#include "operation.h"
#include "script.h"
#include "parserlexer/IlwisScriptLexer.h"
#include "parserlexer/ilwisscriptParser.h"

using namespace Ilwis;
OperationImplementation *Script::create(quint64 metaid, const Ilwis::OperationExpression &expr)
{
    return new Script(metaid, expr);
}

Script::Script()
{
}

Script::Script(quint64 metaid,const Ilwis::OperationExpression &expr) : OperationImplementation(metaid, expr)
{
}

bool Script::detectKey(const std::string& line, const std::string& key) {
    int index = line.find(key);
    if ( index == std::string::npos)
        return false;
    if ( index == 0)
        return true;

    int index1 = line.find('"');
    int index2 = line.find_last_of('"');
    bool ok = index < index1 || index > index2;
    if (!ok)
        return false;

    if ( index != 0 && line[index -1] == ' ')
        return true;
    return false;
}

OperationImplementation::State Script::prepare(ExecutionContext *, const SymbolTable&) {
    QString txt = _expression.parm(0).value();
    if ( txt == "") {
        ERROR2(ERR_NOT_FOUND2, TR("valid expression"), _expression.toString());
        return sPREPAREFAILED;
    }
    QUrl url(txt);
    if ( url.isValid() && url.scheme() == "file") {
        QFileInfo inf( url.toLocalFile());
        bool exists = inf.exists();
        if (exists && inf.suffix() == "isf") {
            std::string text;
            std::ifstream in(inf.absoluteFilePath().toLatin1(), std::ios_base::in);
            int ignorenCount=0;
            if(in.is_open() && in.good()) {
                while(!in.eof()) {
                    std::string line;
                    std::getline(in, line);
                    if ( line == "") // skip empty lines
                        continue;
                    if (detectKey(line, "if") || detectKey(line, "while") ){
                        ignorenCount++;
                    }
                    if (detectKey(line, "endif") || detectKey(line, "endwhile")) {
                        ignorenCount--;
                    }
                    text += line + (ignorenCount != 0 ? " " : ";");
                }
                char *buf = new char[text.size()];
                memcpy(buf,text.c_str(), text.size());
                _buffer.reset( buf );
                _bufferSize = text.size();
                return sPREPARED;
            }
        } else {
            return sPREPAREFAILED;
        }
    } else {
        QString text = txt.trimmed();
        if ( text[text.size() - 1] != ';')
            text += ';';
        char *buf = new char[text.size()];
        memcpy(buf,text.toLatin1(), text.size());
        _buffer.reset( buf );
        _bufferSize = text.size();
        return sPREPARED;
    }

    return sNOTPREPARED;
}

bool Script::execute(ExecutionContext *ctx, SymbolTable& symbols )
{
    try{
    if (_prepState == sNOTPREPARED)
        if((_prepState = prepare(ctx, symbols)) != sPREPARED)
            return false;

    ANTLR3_UINT8 * bufferData = (ANTLR3_UINT8 *) _buffer.get();

    pANTLR3_INPUT_STREAM input = antlr3StringStreamNew(bufferData,  ANTLR3_ENC_8BIT,  _bufferSize, (pANTLR3_UINT8)"ScriptText");
    if(input == NULL)
        return false;

    pilwisscriptLexer lxr = ilwisscriptLexerNew(input);
    if(lxr == NULL)
        return false;

    //Creates an empty token stream.
    pANTLR3_COMMON_TOKEN_STREAM tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr));
    if(tstream == NULL)
        return false;

    //Creates a parser.
    pilwisscriptParser psr = ilwisscriptParserNew(tstream);
    if(psr == NULL)
        return false;

    //Run the parser rule. This also runs the lexer to create the token stream.
    ASTNode *scr = psr->script(psr);

    bool ok = scr->evaluate(symbols, 1000, ctx);
    return ok;
    }
    catch(Ilwis::ScriptError& err) {
        kernel()->issues()->log(err.message());
    }
    return false;

}

quint64 Script::createMetadata()
{
    QString urlTxt = QString("ilwis://operations/script");
    QUrl url(urlTxt);
    Resource resource(url, itOPERATIONMETADATA);
    resource.addProperty("namespace","ilwis");
    resource.addProperty("longname","ilwisscript");
    resource.addProperty("syntax","script file|script scriptline(,scriptline)*");
    resource.addProperty("inparameters","1");
    resource.addProperty("pin_1_type", itFILE | itSTRING);
    resource.addProperty("pin_1_name", TR("input script file"));
    resource.addProperty("pin_1_domain","none");
    resource.addProperty("pin_1_desc",TR("input file containing script commands"));
    resource.addProperty("outparameters",1);
    resource.addProperty("pout_1_type", itBOOL);
    resource.addProperty("pout_1_name", TR("succes"));
    resource.addProperty("pout_1_domain","bool");
    resource.addProperty("pout_1_desc",TR("returns the succes of the execution of the script"));

    resource.prepare();
    urlTxt += "=" + QString::number(resource.id());
    resource.setUrl(QUrl(urlTxt));
//    IOperationMetaData md;
//    if(!md.prepare(resource)) {
//        return i64UNDEF;
//    }
    mastercatalog()->addItems({resource});
    return resource.id();
}
<commit_msg>any script command that has a existing file as parameter will use this file to search for script commands. else it will assume the rest is a valid script command and will pass it the script processor<commit_after>#include <iostream>
#include <fstream>
#include <QUrl>
#include <QFileInfo>
#include "kernel.h"
#include "ilwisdata.h"
#include "resource.h"
#include "identity.h"
#include "symboltable.h"
#include "operationExpression.h"
#include "operationmetadata.h"
#include "commandhandler.h"
#include "operation.h"
#include "script.h"
#include "parserlexer/IlwisScriptLexer.h"
#include "parserlexer/ilwisscriptParser.h"

using namespace Ilwis;
OperationImplementation *Script::create(quint64 metaid, const Ilwis::OperationExpression &expr)
{
    return new Script(metaid, expr);
}

Script::Script()
{
}

Script::Script(quint64 metaid,const Ilwis::OperationExpression &expr) : OperationImplementation(metaid, expr)
{
}

bool Script::detectKey(const std::string& line, const std::string& key) {
    int index = line.find(key);
    if ( index == std::string::npos)
        return false;
    if ( index == 0)
        return true;

    int index1 = line.find('"');
    int index2 = line.find_last_of('"');
    bool ok = index < index1 || index > index2;
    if (!ok)
        return false;

    if ( index != 0 && line[index -1] == ' ')
        return true;
    return false;
}

OperationImplementation::State Script::prepare(ExecutionContext *, const SymbolTable&) {
    QString txt = _expression.parm(0).value();
    if ( txt == "") {
        ERROR2(ERR_NOT_FOUND2, TR("valid expression"), _expression.toString());
        return sPREPAREFAILED;
    }
    QUrl url(txt);
    QFileInfo inf( url.toLocalFile());
    bool exists = inf.exists();
    if (  exists) {

        std::string text;
        std::ifstream in(inf.absoluteFilePath().toLatin1(), std::ios_base::in);
        int ignorenCount=0;
        if(in.is_open() && in.good()) {
            while(!in.eof()) {
                std::string line;
                std::getline(in, line);
                if ( line == "") // skip empty lines
                    continue;
                if (detectKey(line, "if") || detectKey(line, "while") ){
                    ignorenCount++;
                }
                if (detectKey(line, "endif") || detectKey(line, "endwhile")) {
                    ignorenCount--;
                }
                text += line + (ignorenCount != 0 ? " " : ";");
            }
            char *buf = new char[text.size()];
            memcpy(buf,text.c_str(), text.size());
            _buffer.reset( buf );
            _bufferSize = text.size();
            return sPREPARED;
        }

    } else {
        QString text = txt.trimmed();
        if ( text[text.size() - 1] != ';')
            text += ';';
        char *buf = new char[text.size()];
        memcpy(buf,text.toLatin1(), text.size());
        _buffer.reset( buf );
        _bufferSize = text.size();
        return sPREPARED;
    }

    return sNOTPREPARED;
}

bool Script::execute(ExecutionContext *ctx, SymbolTable& symbols )
{
    try{
    if (_prepState == sNOTPREPARED)
        if((_prepState = prepare(ctx, symbols)) != sPREPARED)
            return false;

    ANTLR3_UINT8 * bufferData = (ANTLR3_UINT8 *) _buffer.get();

    pANTLR3_INPUT_STREAM input = antlr3StringStreamNew(bufferData,  ANTLR3_ENC_8BIT,  _bufferSize, (pANTLR3_UINT8)"ScriptText");
    if(input == NULL)
        return false;

    pilwisscriptLexer lxr = ilwisscriptLexerNew(input);
    if(lxr == NULL)
        return false;

    //Creates an empty token stream.
    pANTLR3_COMMON_TOKEN_STREAM tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr));
    if(tstream == NULL)
        return false;

    //Creates a parser.
    pilwisscriptParser psr = ilwisscriptParserNew(tstream);
    if(psr == NULL)
        return false;

    //Run the parser rule. This also runs the lexer to create the token stream.
    ASTNode *scr = psr->script(psr);

    bool ok = scr->evaluate(symbols, 1000, ctx);
    return ok;
    }
    catch(Ilwis::ScriptError& err) {
        kernel()->issues()->log(err.message());
    }
    return false;

}

quint64 Script::createMetadata()
{
    QString urlTxt = QString("ilwis://operations/script");
    QUrl url(urlTxt);
    Resource resource(url, itOPERATIONMETADATA);
    resource.addProperty("namespace","ilwis");
    resource.addProperty("longname","ilwisscript");
    resource.addProperty("syntax","script file|script scriptline(,scriptline)*");
    resource.addProperty("inparameters","1");
    resource.addProperty("pin_1_type", itFILE | itSTRING);
    resource.addProperty("pin_1_name", TR("input script file"));
    resource.addProperty("pin_1_domain","none");
    resource.addProperty("pin_1_desc",TR("input file containing script commands"));
    resource.addProperty("outparameters",1);
    resource.addProperty("pout_1_type", itBOOL);
    resource.addProperty("pout_1_name", TR("succes"));
    resource.addProperty("pout_1_domain","bool");
    resource.addProperty("pout_1_desc",TR("returns the succes of the execution of the script"));

    resource.prepare();
    urlTxt += "=" + QString::number(resource.id());
    resource.setUrl(QUrl(urlTxt));
//    IOperationMetaData md;
//    if(!md.prepare(resource)) {
//        return i64UNDEF;
//    }
    mastercatalog()->addItems({resource});
    return resource.id();
}
<|endoftext|>


<commit_before>#include <regex>
#include <string>
#include "parser.h"

static ast_type_t identifier_type(const std::string &s)
{
    static const std::regex float_re("^-?(\\d+\\.\\d*|\\d*\\.\\d+)$");
    static const std::regex int_re("^-?\\d+$");
    if(std::regex_match(s, int_re))
        return ast_type_t::INT;
    if(std::regex_match(s, float_re))
        return ast_type_t::FLOAT;
    return ast_type_t::NAME;
}

std::shared_ptr<ASTNode> readObject(std::istream &is)
{
    auto o = std::make_shared<ASTNode>();
    int c;
    c = is.get();
    while(isspace(c) && c != EOF)
        c = is.get();
    if(c == EOF)
        throw end_of_input("");
    if(c == ')')
        throw parse_error("Invalid syntax");
    if(c == '"')
    {
        o->type = ast_type_t::STRING;
        c = is.get();
        while(c != EOF && c != '"')
        {
            o->value.push_back(c);
            c = is.get();
        }
        if(c == EOF)
            throw parse_error("Unclosed string literal");
        return o;
    }
    if(c == '(')
    {
        o->type = ast_type_t::LIST;
        c = is.peek();
        while(c != EOF && c != ')')
        {
            o->list.push_back(readObject(is));
            c = is.peek();
            while(c != EOF && isspace(c))
            {
                is.get();
                c = is.peek();
            }
        }
        if(c == EOF)
            throw parse_error("Unclosed list literal");
        is.get();
        return o;
    }
    if(c == '\'')
    {
        auto quote = std::make_shared<ASTNode>();
        quote->type = ast_type_t::NAME;
        quote->value = "quote";
        o->type = ast_type_t::LIST;
        o->list.push_back(quote);
        o->list.push_back(readObject(is));
        return o;
    }
    o->value.push_back(c);
    c = is.peek();
    while(c != EOF && c != '(' && c != ')' && !isspace(c))
    {
        o->value.push_back(c);
        is.get();
        c = is.peek();
    }
    o->type = identifier_type(o->value);
    return o;
}<commit_msg>Комментарии<commit_after>#include <regex>
#include <string>
#include "parser.h"

static ast_type_t identifier_type(const std::string &s)
{
    static const std::regex float_re("^-?(\\d+\\.\\d*|\\d*\\.\\d+)$");
    static const std::regex int_re("^-?\\d+$");
    if(std::regex_match(s, int_re))
        return ast_type_t::INT;
    if(std::regex_match(s, float_re))
        return ast_type_t::FLOAT;
    return ast_type_t::NAME;
}

static int skip_whitespace(std::istream &is)
{
    int c;
    while(true)
    {
        c = is.peek();
        while(c != EOF && isspace(c))
        {
            is.get();
            c = is.peek();
        }
        if(c == ';')
        {
            while(c != EOF && c != '\n')
            {
                c = is.get();
            }
        }
        else
            return c;
    }
}

std::shared_ptr<ASTNode> readObject(std::istream &is)
{
    auto o = std::make_shared<ASTNode>();
    skip_whitespace(is);
    int c = is.get();
    if(c == EOF)
        throw end_of_input("");
    if(c == ')')
        throw parse_error("Invalid syntax");
    if(c == '"')
    {
        o->type = ast_type_t::STRING;
        c = is.get();
        while(c != EOF && c != '"')
        {
            o->value.push_back(c);
            c = is.get();
        }
        if(c == EOF)
            throw parse_error("Unclosed string literal");
        return o;
    }
    if(c == '(')
    {
        o->type = ast_type_t::LIST;
        skip_whitespace(is);
        c = is.peek();
        while(c != EOF && c != ')')
        {
            o->list.push_back(readObject(is));
            c = skip_whitespace(is);
        }
        if(c == EOF)
            throw parse_error("Unclosed list literal");
        is.get();
        return o;
    }
    if(c == '\'')
    {
        auto quote = std::make_shared<ASTNode>();
        quote->type = ast_type_t::NAME;
        quote->value = "quote";
        o->type = ast_type_t::LIST;
        o->list.push_back(quote);
        o->list.push_back(readObject(is));
        return o;
    }
    o->value.push_back(c);
    c = is.peek();
    while(c != EOF && c != '(' && c != ')' && !isspace(c))
    {
        o->value.push_back(c);
        is.get();
        c = is.peek();
    }
    o->type = identifier_type(o->value);
    return o;
}<|endoftext|>


<commit_before>#include "common.hpp"
#include <time.h>

static long sys_nanosleep(const struct timespec */*req*/, struct timespec */*rem*/)
{
  return -ENOSYS;
}

extern "C"
long syscall_SYS_nanosleep(const struct timespec *req, struct timespec *rem)
{
  return strace(sys_nanosleep, "nanosleep", req, rem);
}
<commit_msg>musl: Implement nanosleep<commit_after>#include "common.hpp"
#include <time.h>
#include <timers>
using namespace std::chrono;

static void nanosleep(nanoseconds nanos)
{
  bool ticked = false;

  Timers::oneshot(nanos,
  [&ticked] (int) {
    ticked = true;
  });

  while (ticked == false) {
    os::block();
  }
}

static long sys_nanosleep(const struct timespec* req, struct timespec */*rem*/)
{
  if (req == nullptr) return -EINVAL;
  auto nanos = nanoseconds(req->tv_sec * 1'000'000'000ull + req->tv_nsec);
  nanosleep(nanos);
  return 0;
}

extern "C"
long syscall_SYS_nanosleep(const struct timespec *req, struct timespec *rem)
{
  return strace(sys_nanosleep, "nanosleep", req, rem);
}
<|endoftext|>