<commit_before>#include "file.hpp"
#include "internal.hpp"
#include "macros.hpp"
#include "message.hpp"

extern "C" {
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
};

namespace CaDiCaL {

/*------------------------------------------------------------------------*/

File::File (Internal *i, bool w, int c, FILE * f, const char * n) :
  internal (i), writing (w),
  close_file (c), file (f),
  _name (n), _lineno (1), _bytes (0)
{
  assert (f), assert (n);
}

/*------------------------------------------------------------------------*/

bool File::exists (const char * path) {
  struct stat buf;
  return !stat (path, &buf);
}

size_t File::size (const char * path) {
  struct stat buf;
  if (stat (path, &buf)) return 0;
  return (size_t) buf.st_size;
}

char * File::find (const char * prg) {
  size_t prglen = strlen (prg);
  const char * c = getenv ("PATH");
  if (!c) return 0;;
  size_t len = strlen (c);
  char * e = new char[len + 1];
  strcpy (e, c);
  char * res = 0;
  for (char * p = e, * q; !res && p < e + len; p = q) {
    for (q = p; *q && *q != ':'; q++)
      ;
    *q++ = 0;
    size_t pathlen = (q - p) + prglen;
    char * path = new char [pathlen + 1];
    sprintf (path, "%s/%s", p, prg);
    assert (strlen (path) == pathlen);
    if (exists (path)) res = path;
    else delete [] path;
  }
  delete [] e;
  return res;
}

/*------------------------------------------------------------------------*/

FILE * File::open_file (Internal * internal,
                        const char * path,
                        const char * mode) {
  return fopen (path, mode);
}

FILE * File::read_file (Internal * internal, const char * path) {
  MSG ("opening file to read '%s'", path);
  return open_file (internal, path, "r");
}

FILE * File::write_file (Internal * internal, const char * path) {
  MSG ("opening file to write '%s'", path);
  return open_file (internal, path, "w");
}

/*------------------------------------------------------------------------*/

FILE * File::open_pipe (Internal * internal,
                        const char * fmt, const char * path,
                        const char * mode) {
  size_t prglen = 0;
  while (fmt[prglen] && fmt[prglen] != ' ') prglen++;
  char * prg = new char [prglen + 1];
  strncpy (prg, fmt, prglen);
  prg[prglen] = 0;
  char * found = find (prg);
  delete [] prg;
  if (!found) return 0;
  MSG ("using '%s'", found);
  delete [] found;
  char * cmd = new char [strlen (fmt) + strlen (path)];
  sprintf (cmd, fmt, path);
  FILE * res = popen (cmd, mode);
  delete [] cmd;
  return res;
}

FILE * File::read_pipe (Internal * internal,
                        const char * fmt, const char * path) {
  if (!File::exists (path)) return 0;
  MSG ("opening pipe to read '%s'", path);
  return open_pipe (internal, fmt, path, "r");
}

FILE * File::write_pipe (Internal * internal,
                         const char * fmt, const char * path) {
  MSG ("opening pipe to write '%s'", path);
  return open_pipe (internal, fmt, path, "w");
}

/*------------------------------------------------------------------------*/

File * File::read (Internal * internal, FILE * f, const char * n) {
  return new File (internal, false, 0, f, n);
}

File * File::write (Internal * internal, FILE * f, const char * n) {
  return new File (internal, true, 0, f, n);
}

File * File::read (Internal * internal, const char * path) {
  FILE * file;
  int close_input = 2;
  if (has_suffix (path, ".xz"))
    file = read_pipe (internal, "xz -c -d %s", path);
  else if (has_suffix (path, ".bz2"))
    file = read_pipe (internal, "bzip2 -c -d %s", path);
  else if (has_suffix (path, ".gz"))
    file = read_pipe (internal, "gzip -c -d %s", path);
  else if (has_suffix (path, ".7z"))
    file = read_pipe (internal, "7z x -so %s 2>/dev/null", path);
  else
    file = read_file (internal, path), close_input = 1;
  return file ? new File (internal, false, close_input, file, path) : 0;
}

File * File::write (Internal * internal, const char * path) {
  FILE * file;
  int close_input = 2;
  if (has_suffix (path, ".xz"))
    file = write_pipe (internal, "xz -c -e > %s", path);
  else if (has_suffix (path, ".bz2"))
    file = write_pipe (internal, "bzip2 -c > %s", path);
  else if (has_suffix (path, ".gz"))
    file = write_pipe (internal, "gzip -c > %s", path);
  else if (has_suffix (path, ".7z"))
    file = write_pipe (internal,
                       "7z a -an -txz -si -so > %s 2>/dev/null", path);
  else
    file = write_file (internal, path), close_input = 1;
  return file ? new File (internal, true, close_input, file, path) : 0;
}

File::~File () {
  if (close_file == 1) {
    MSG ("closing file '%s'", name ());
    fclose (file);
  }
  if (close_file == 2) {
    MSG ("closing pipe command on '%s'", name ());
    pclose (file);
  }
  double mb = bytes () / (double) (1 << 20);
  if (writing) MSG ("after writing %ld bytes %.1f MB", bytes (), mb);
  else MSG ("after reading %ld bytes %.1f MB", bytes (), mb);
  if (close_file == 2) {
    long s = size (name ());
    double mb = s / (double) (1<<20);
    if (writing)
      MSG ("deflated to %ld bytes %.1f MB by factor %.2f or %.2f%%",
        s, mb, relative (bytes (), s), percent (bytes () - s, bytes ()));
    else
      MSG ("inflated from %ld bytes %.1f MB by factor %.2f or %.2f%%",
        s, mb, relative (bytes (), s), percent (bytes () - s, bytes ()));
  }
}

};
<commit_msg>compression message<commit_after>#include "file.hpp"
#include "internal.hpp"
#include "macros.hpp"
#include "message.hpp"

extern "C" {
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
};

namespace CaDiCaL {

/*------------------------------------------------------------------------*/

File::File (Internal *i, bool w, int c, FILE * f, const char * n) :
  internal (i), writing (w),
  close_file (c), file (f),
  _name (n), _lineno (1), _bytes (0)
{
  assert (f), assert (n);
}

/*------------------------------------------------------------------------*/

bool File::exists (const char * path) {
  struct stat buf;
  return !stat (path, &buf);
}

size_t File::size (const char * path) {
  struct stat buf;
  if (stat (path, &buf)) return 0;
  return (size_t) buf.st_size;
}

char * File::find (const char * prg) {
  size_t prglen = strlen (prg);
  const char * c = getenv ("PATH");
  if (!c) return 0;;
  size_t len = strlen (c);
  char * e = new char[len + 1];
  strcpy (e, c);
  char * res = 0;
  for (char * p = e, * q; !res && p < e + len; p = q) {
    for (q = p; *q && *q != ':'; q++)
      ;
    *q++ = 0;
    size_t pathlen = (q - p) + prglen;
    char * path = new char [pathlen + 1];
    sprintf (path, "%s/%s", p, prg);
    assert (strlen (path) == pathlen);
    if (exists (path)) res = path;
    else delete [] path;
  }
  delete [] e;
  return res;
}

/*------------------------------------------------------------------------*/

FILE * File::open_file (Internal * internal,
                        const char * path,
                        const char * mode) {
  return fopen (path, mode);
}

FILE * File::read_file (Internal * internal, const char * path) {
  MSG ("opening file to read '%s'", path);
  return open_file (internal, path, "r");
}

FILE * File::write_file (Internal * internal, const char * path) {
  MSG ("opening file to write '%s'", path);
  return open_file (internal, path, "w");
}

/*------------------------------------------------------------------------*/

FILE * File::open_pipe (Internal * internal,
                        const char * fmt, const char * path,
                        const char * mode) {
  size_t prglen = 0;
  while (fmt[prglen] && fmt[prglen] != ' ') prglen++;
  char * prg = new char [prglen + 1];
  strncpy (prg, fmt, prglen);
  prg[prglen] = 0;
  char * found = find (prg);
  if (found) MSG ("found '%s' in path for '%s'", found, prg);
  delete [] prg;
  if (!found) return 0;
  delete [] found;
  char * cmd = new char [strlen (fmt) + strlen (path)];
  sprintf (cmd, fmt, path);
  FILE * res = popen (cmd, mode);
  delete [] cmd;
  return res;
}

FILE * File::read_pipe (Internal * internal,
                        const char * fmt, const char * path) {
  if (!File::exists (path)) return 0;
  MSG ("opening pipe to read '%s'", path);
  return open_pipe (internal, fmt, path, "r");
}

FILE * File::write_pipe (Internal * internal,
                         const char * fmt, const char * path) {
  MSG ("opening pipe to write '%s'", path);
  return open_pipe (internal, fmt, path, "w");
}

/*------------------------------------------------------------------------*/

File * File::read (Internal * internal, FILE * f, const char * n) {
  return new File (internal, false, 0, f, n);
}

File * File::write (Internal * internal, FILE * f, const char * n) {
  return new File (internal, true, 0, f, n);
}

File * File::read (Internal * internal, const char * path) {
  FILE * file;
  int close_input = 2;
  if (has_suffix (path, ".xz"))
    file = read_pipe (internal, "xz -c -d %s", path);
  else if (has_suffix (path, ".bz2"))
    file = read_pipe (internal, "bzip2 -c -d %s", path);
  else if (has_suffix (path, ".gz"))
    file = read_pipe (internal, "gzip -c -d %s", path);
  else if (has_suffix (path, ".7z"))
    file = read_pipe (internal, "7z x -so %s 2>/dev/null", path);
  else
    file = read_file (internal, path), close_input = 1;
  return file ? new File (internal, false, close_input, file, path) : 0;
}

File * File::write (Internal * internal, const char * path) {
  FILE * file;
  int close_input = 2;
  if (has_suffix (path, ".xz"))
    file = write_pipe (internal, "xz -c -e > %s", path);
  else if (has_suffix (path, ".bz2"))
    file = write_pipe (internal, "bzip2 -c > %s", path);
  else if (has_suffix (path, ".gz"))
    file = write_pipe (internal, "gzip -c > %s", path);
  else if (has_suffix (path, ".7z"))
    file = write_pipe (internal,
                       "7z a -an -txz -si -so > %s 2>/dev/null", path);
  else
    file = write_file (internal, path), close_input = 1;
  return file ? new File (internal, true, close_input, file, path) : 0;
}

File::~File () {
  if (close_file == 1) {
    MSG ("closing file '%s'", name ());
    fclose (file);
  }
  if (close_file == 2) {
    MSG ("closing pipe command on '%s'", name ());
    pclose (file);
  }
  double mb = bytes () / (double) (1 << 20);
  if (writing) MSG ("after writing %ld bytes %.1f MB", bytes (), mb);
  else MSG ("after reading %ld bytes %.1f MB", bytes (), mb);
  if (close_file == 2) {
    long s = size (name ());
    double mb = s / (double) (1<<20);
    if (writing)
      MSG ("deflated to %ld bytes %.1f MB by factor %.2f or %.2f%%",
        s, mb, relative (bytes (), s), percent (bytes () - s, bytes ()));
    else
      MSG ("inflated from %ld bytes %.1f MB by factor %.2f or %.2f%%",
        s, mb, relative (bytes (), s), percent (bytes () - s, bytes ()));
  }
}

};
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, 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/scoped_ptr.hpp>
#ifdef _WIN32
// windows part
#include "libtorrent/utf8.hpp"

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef _MODE_T_
typedef int mode_t;
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#else
// unix part
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include <boost/static_assert.hpp>
// make sure the _FILE_OFFSET_BITS define worked
// on this platform
BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8);

#endif

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>
#include <cstring>
#include <vector>

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#include "libtorrent/assert.hpp"

namespace
{
	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
		if (m == (mode_in | mode_out)) return O_RDWR | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		TORRENT_ASSERT(false);
		return 0;
	}

#ifdef WIN32
	std::string utf8_native(std::string const& s)
	{
		try
		{
			std::wstring ws;
			libtorrent::utf8_wchar(s, ws);
			std::size_t size = wcstombs(0, ws.c_str(), 0);
			if (size == std::size_t(-1)) return s;
			std::string ret;
			ret.resize(size);
			size = wcstombs(&ret[0], ws.c_str(), size + 1);
			if (size == wchar_t(-1)) return s;
			ret.resize(size);
			return ret;
		}
		catch(std::exception)
		{
			return s;
		}
	}
#else
	std::string utf8_native(std::string const& s)
	{
		return s;
	}
#endif

}

namespace libtorrent
{
	namespace fs = boost::filesystem;

	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);

	const file::seek_mode file::begin(1);
	const file::seek_mode file::end(2);

	struct file::impl
	{
		impl()
			: m_fd(-1)
			, m_open_mode(0)
		{}

		impl(fs::path const& path, int mode)
			: m_fd(-1)
			, m_open_mode(0)
		{
			open(path, mode);
		}

		~impl()
		{
			close();
		}

		bool open(fs::path const& path, int mode)
		{
			close();
#if defined(_WIN32) && defined(UNICODE)
			std::wstring wpath(safe_convert(path.native_file_string()));
			m_fd = ::_wopen(
				wpath.c_str()
				, map_open_mode(mode)
				, S_IREAD | S_IWRITE);
#else
#ifdef _WIN32
			m_fd = ::_open(
#else
			m_fd = ::open(
#endif
				utf8_native(path.native_file_string()).c_str()
				, map_open_mode(mode)
#ifdef _WIN32
				, S_IREAD | S_IWRITE);
#else
				, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
#endif
#endif
			if (m_fd == -1)
			{
				std::stringstream msg;
				msg << "open failed: '" << path.native_file_string() << "'. "
					<< std::strerror(errno);
				if (!m_error) m_error.reset(new std::string);
				*m_error = msg.str();
				return false;
			}
			m_open_mode = mode;
			return true;
		}

		void close()
		{
			if (m_fd == -1) return;

#ifdef _WIN32
			::_close(m_fd);
#else
			::close(m_fd);
#endif
			m_fd = -1;
			m_open_mode = 0;
		}

		size_type read(char* buf, size_type num_bytes)
		{
			TORRENT_ASSERT(m_open_mode & mode_in);
			TORRENT_ASSERT(m_fd != -1);

#ifdef _WIN32
			size_type ret = ::_read(m_fd, buf, num_bytes);
#else
			size_type ret = ::read(m_fd, buf, num_bytes);
#endif
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "read failed: " << std::strerror(errno);
				if (!m_error) m_error.reset(new std::string);
				*m_error = msg.str();
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			TORRENT_ASSERT(m_open_mode & mode_out);
			TORRENT_ASSERT(m_fd != -1);

			// TODO: Test this a bit more, what happens with random failures in
			// the files?
//			if ((rand() % 100) > 80)
//				throw file_error("debug");

#ifdef _WIN32
			size_type ret = ::_write(m_fd, buf, num_bytes);
#else
			size_type ret = ::write(m_fd, buf, num_bytes);
#endif
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "write failed: " << std::strerror(errno);
				if (!m_error) m_error.reset(new std::string);
				*m_error = msg.str();
			}
			return ret;
		}

		bool set_size(size_type s)
		{
#ifdef _WIN32
#error file.cpp is for posix systems only. use file_win.cpp on windows
#else
			if (ftruncate(m_fd, s) < 0)
			{
				std::stringstream msg;
				msg << "ftruncate failed: '" << std::strerror(errno);
				if (!m_error) m_error.reset(new std::string);
				*m_error = msg.str();
				return false;
			}
			return true;
#endif
		}

		size_type seek(size_type offset, int m = 1)
		{
			TORRENT_ASSERT(m_open_mode);
			TORRENT_ASSERT(m_fd != -1);

			int seekdir = (m == 1)?SEEK_SET:SEEK_END;
#ifdef _WIN32
			size_type ret = _lseeki64(m_fd, offset, seekdir);
#else
			size_type ret = lseek(m_fd, offset, seekdir);
#endif

			// For some strange reason this fails
			// on win32. Use windows specific file
			// wrapper instead.
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "seek failed: '" << std::strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				if (!m_error) m_error.reset(new std::string);
				*m_error = msg.str();
				return -1;
			}
			return ret;
		}

		size_type tell()
		{
			TORRENT_ASSERT(m_open_mode);
			TORRENT_ASSERT(m_fd != -1);

#ifdef _WIN32
			return _telli64(m_fd);
#else
			return lseek(m_fd, 0, SEEK_CUR);
#endif
		}

		std::string const& error() const
		{
			if (!m_error) m_error.reset(new std::string);
			return *m_error;
		}

		int m_fd;
		int m_open_mode;
		mutable boost::scoped_ptr<std::string> m_error;
	};

	// pimpl forwardings

	file::file() : m_impl(new impl()) {}

	file::file(fs::path const& p, file::open_mode m)
		: m_impl(new impl(p, m.m_mask))
	{}

	file::~file() {}

	bool file::open(fs::path const& p, file::open_mode m)
	{
		return m_impl->open(p, m.m_mask);
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buf, size_type num_bytes)
	{
		return m_impl->write(buf, num_bytes);
	}

	size_type file::read(char* buf, size_type num_bytes)
	{
		return m_impl->read(buf, num_bytes);
	}

	bool file::set_size(size_type s)
	{
		return m_impl->set_size(s);
	}

	size_type file::seek(size_type pos, file::seek_mode m)
	{
		return m_impl->seek(pos, m.m_val);
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}

	std::string const& file::error() const
	{
		return m_impl->error();
	}

}
<commit_msg>removed hard coded file permission bits<commit_after>/*

Copyright (c) 2003, 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/scoped_ptr.hpp>
#ifdef _WIN32
// windows part
#include "libtorrent/utf8.hpp"

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef _MODE_T_
typedef int mode_t;
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#else
// unix part
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include <boost/static_assert.hpp>
// make sure the _FILE_OFFSET_BITS define worked
// on this platform
BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8);

#endif

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>
#include <cstring>
#include <vector>

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#include "libtorrent/assert.hpp"

namespace
{
	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
		if (m == (mode_in | mode_out)) return O_RDWR | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		TORRENT_ASSERT(false);
		return 0;
	}

#ifdef WIN32
	std::string utf8_native(std::string const& s)
	{
		try
		{
			std::wstring ws;
			libtorrent::utf8_wchar(s, ws);
			std::size_t size = wcstombs(0, ws.c_str(), 0);
			if (size == std::size_t(-1)) return s;
			std::string ret;
			ret.resize(size);
			size = wcstombs(&ret[0], ws.c_str(), size + 1);
			if (size == wchar_t(-1)) return s;
			ret.resize(size);
			return ret;
		}
		catch(std::exception)
		{
			return s;
		}
	}
#else
	std::string utf8_native(std::string const& s)
	{
		return s;
	}
#endif

}

namespace libtorrent
{
	namespace fs = boost::filesystem;

	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);

	const file::seek_mode file::begin(1);
	const file::seek_mode file::end(2);

	struct file::impl
	{
		impl()
			: m_fd(-1)
			, m_open_mode(0)
		{}

		impl(fs::path const& path, int mode)
			: m_fd(-1)
			, m_open_mode(0)
		{
			open(path, mode);
		}

		~impl()
		{
			close();
		}

		bool open(fs::path const& path, int mode)
		{
			close();
#if defined _WIN32 && defined UNICODE
			std::wstring wpath(safe_convert(path.native_file_string()));
			m_fd = ::_wopen(
				wpath.c_str()
				, map_open_mode(mode));
#elif defined _WIN32
			m_fd = ::_open(
				utf8_native(path.native_file_string()).c_str()
				, map_open_mode(mode));
#else
			m_fd = ::open(
				utf8_native(path.native_file_string()).c_str()
				, map_open_mode(mode));
#endif
			if (m_fd == -1)
			{
				std::stringstream msg;
				msg << "open failed: '" << path.native_file_string() << "'. "
					<< std::strerror(errno);
				if (!m_error) m_error.reset(new std::string);
				*m_error = msg.str();
				return false;
			}
			m_open_mode = mode;
			return true;
		}

		void close()
		{
			if (m_fd == -1) return;

#ifdef _WIN32
			::_close(m_fd);
#else
			::close(m_fd);
#endif
			m_fd = -1;
			m_open_mode = 0;
		}

		size_type read(char* buf, size_type num_bytes)
		{
			TORRENT_ASSERT(m_open_mode & mode_in);
			TORRENT_ASSERT(m_fd != -1);

#ifdef _WIN32
			size_type ret = ::_read(m_fd, buf, num_bytes);
#else
			size_type ret = ::read(m_fd, buf, num_bytes);
#endif
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "read failed: " << std::strerror(errno);
				if (!m_error) m_error.reset(new std::string);
				*m_error = msg.str();
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			TORRENT_ASSERT(m_open_mode & mode_out);
			TORRENT_ASSERT(m_fd != -1);

			// TODO: Test this a bit more, what happens with random failures in
			// the files?
//			if ((rand() % 100) > 80)
//				throw file_error("debug");

#ifdef _WIN32
			size_type ret = ::_write(m_fd, buf, num_bytes);
#else
			size_type ret = ::write(m_fd, buf, num_bytes);
#endif
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "write failed: " << std::strerror(errno);
				if (!m_error) m_error.reset(new std::string);
				*m_error = msg.str();
			}
			return ret;
		}

		bool set_size(size_type s)
		{
#ifdef _WIN32
#error file.cpp is for posix systems only. use file_win.cpp on windows
#else
			if (ftruncate(m_fd, s) < 0)
			{
				std::stringstream msg;
				msg << "ftruncate failed: '" << std::strerror(errno);
				if (!m_error) m_error.reset(new std::string);
				*m_error = msg.str();
				return false;
			}
			return true;
#endif
		}

		size_type seek(size_type offset, int m = 1)
		{
			TORRENT_ASSERT(m_open_mode);
			TORRENT_ASSERT(m_fd != -1);

			int seekdir = (m == 1)?SEEK_SET:SEEK_END;
#ifdef _WIN32
			size_type ret = _lseeki64(m_fd, offset, seekdir);
#else
			size_type ret = lseek(m_fd, offset, seekdir);
#endif

			// For some strange reason this fails
			// on win32. Use windows specific file
			// wrapper instead.
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "seek failed: '" << std::strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				if (!m_error) m_error.reset(new std::string);
				*m_error = msg.str();
				return -1;
			}
			return ret;
		}

		size_type tell()
		{
			TORRENT_ASSERT(m_open_mode);
			TORRENT_ASSERT(m_fd != -1);

#ifdef _WIN32
			return _telli64(m_fd);
#else
			return lseek(m_fd, 0, SEEK_CUR);
#endif
		}

		std::string const& error() const
		{
			if (!m_error) m_error.reset(new std::string);
			return *m_error;
		}

		int m_fd;
		int m_open_mode;
		mutable boost::scoped_ptr<std::string> m_error;
	};

	// pimpl forwardings

	file::file() : m_impl(new impl()) {}

	file::file(fs::path const& p, file::open_mode m)
		: m_impl(new impl(p, m.m_mask))
	{}

	file::~file() {}

	bool file::open(fs::path const& p, file::open_mode m)
	{
		return m_impl->open(p, m.m_mask);
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buf, size_type num_bytes)
	{
		return m_impl->write(buf, num_bytes);
	}

	size_type file::read(char* buf, size_type num_bytes)
	{
		return m_impl->read(buf, num_bytes);
	}

	bool file::set_size(size_type s)
	{
		return m_impl->set_size(s);
	}

	size_type file::seek(size_type pos, file::seek_mode m)
	{
		return m_impl->seek(pos, m.m_val);
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}

	std::string const& file::error() const
	{
		return m_impl->error();
	}

}
<|endoftext|>


<commit_before>#ifndef flags_hh_INCLUDED
#define flags_hh_INCLUDED

#include <type_traits>

namespace Kakoune
{

template<typename Flags>
struct WithBitOps : std::false_type {};

template<typename Flags>
using EnumStorageType = typename std::underlying_type<Flags>::type;

template<typename Flags>
using EnableIfWithBitOps = typename std::enable_if<WithBitOps<Flags>::value>::type;

template<typename Flags, typename = EnableIfWithBitOps<Flags>>
constexpr Flags operator|(Flags lhs, Flags rhs)
{
    return (Flags)((EnumStorageType<Flags>) lhs | (EnumStorageType<Flags>) rhs);
}

template<typename Flags, typename = EnableIfWithBitOps<Flags>>
Flags& operator|=(Flags& lhs, Flags rhs)
{
    (EnumStorageType<Flags>&) lhs |= (EnumStorageType<Flags>) rhs;
    return lhs;
}

template<typename Flags, typename = EnableIfWithBitOps<Flags>>
constexpr bool operator&(Flags lhs, Flags rhs)
{
    return ((EnumStorageType<Flags>) lhs & (EnumStorageType<Flags>) rhs) != 0;
}

template<typename Flags, typename = EnableIfWithBitOps<Flags>>
Flags& operator&=(Flags& lhs, Flags rhs)
{
    (EnumStorageType<Flags>&) lhs &= (EnumStorageType<Flags>) rhs;
    return lhs;
}

template<typename Flags, typename = EnableIfWithBitOps<Flags>>
constexpr Flags operator~(Flags lhs)
{
    return (Flags)(~(EnumStorageType<Flags>)lhs);
}

}

#endif // flags_hh_INCLUDED
<commit_msg>Tweak flags implementation<commit_after>#ifndef flags_hh_INCLUDED
#define flags_hh_INCLUDED

#include <type_traits>

namespace Kakoune
{

template<typename Flags>
struct WithBitOps : std::false_type {};

template<typename Flags>
using UnderlyingType = typename std::underlying_type<Flags>::type;

template<typename Flags>
using EnableIfWithBitOps = typename std::enable_if<WithBitOps<Flags>::value>::type;

template<typename Flags, typename = EnableIfWithBitOps<Flags>>
constexpr Flags operator|(Flags lhs, Flags rhs)
{
    return (Flags)((UnderlyingType<Flags>) lhs | (UnderlyingType<Flags>) rhs);
}

template<typename Flags, typename = EnableIfWithBitOps<Flags>>
Flags& operator|=(Flags& lhs, Flags rhs)
{
    (UnderlyingType<Flags>&) lhs |= (UnderlyingType<Flags>) rhs;
    return lhs;
}

template<typename Flags, typename = EnableIfWithBitOps<Flags>>
constexpr bool operator&(Flags lhs, Flags rhs)
{
    return ((UnderlyingType<Flags>) lhs & (UnderlyingType<Flags>) rhs) == (UnderlyingType<Flags>)rhs;
}

template<typename Flags, typename = EnableIfWithBitOps<Flags>>
Flags& operator&=(Flags& lhs, Flags rhs)
{
    (UnderlyingType<Flags>&) lhs &= (UnderlyingType<Flags>) rhs;
    return lhs;
}

template<typename Flags, typename = EnableIfWithBitOps<Flags>>
constexpr Flags operator~(Flags lhs)
{
    return (Flags)(~(UnderlyingType<Flags>)lhs);
}

}

#endif // flags_hh_INCLUDED
<|endoftext|>


<commit_before>#include <reactive/buffer.hpp>
#include <reactive/generate.hpp>
#include <reactive/consume.hpp>
#include <reactive/tuple.hpp>
#include <reactive/ptr_observable.hpp>
#include <reactive/transform.hpp>
#include <reactive/bridge.hpp>
#include <reactive/take.hpp>
#include <reactive/enumerate.hpp>
#include <reactive/cache.hpp>
#include <reactive/connector.hpp>
#include <reactive/receiver.hpp>
#include <reactive/deref_optional.hpp>
#include <boost/test/unit_test.hpp>

namespace Si
{
	BOOST_AUTO_TEST_CASE(reactive_take)
	{
		auto zeros = rx::generate([]{ return 0; });
		auto ones  = rx::generate([]{ return 1; });
		auto both = rx::make_tuple(zeros, ones);
		std::vector<std::tuple<int, int>> const expected(4, std::make_tuple(0, 1));
		std::vector<std::tuple<int, int>> const generated = rx::take(both, expected.size());
		BOOST_CHECK(expected == generated);
	}

	BOOST_AUTO_TEST_CASE(reactive_transform)
	{
		auto twos = rx::generate([]{ return 2; });
		auto ones  = rx::generate([]{ return 1; });
		auto both = rx::make_tuple(twos, ones);
		auto added = rx::transform(both, [](std::tuple<int, int> const &element)
		{
			return std::get<0>(element) + std::get<1>(element);
		});
		std::vector<int> const expected(4, 3);
		std::vector<int> const generated = rx::take(added, expected.size());
		BOOST_CHECK(expected == generated);
	}

	BOOST_AUTO_TEST_CASE(reactive_bridge)
	{
		auto bridge = std::make_shared<rx::bridge<int>>();
		rx::ptr_observable<int, std::shared_ptr<rx::observable<int>>> first(bridge);
		auto ones  = rx::generate([]{ return 1; });
		auto both = rx::make_tuple(first, ones);
		auto added = rx::transform(both, [](std::tuple<int, int> const &element)
		{
			return std::get<0>(element) + std::get<1>(element);
		});
		std::vector<int> generated;
		auto consumer = rx::consume<int>([&generated](int element)
		{
			generated.emplace_back(element);
		});
		BOOST_CHECK(generated.empty());

		added.async_get_one(consumer);
		BOOST_CHECK(generated.empty());

		bridge->got_element(2);
		std::vector<int> const expected(1, 3);
		BOOST_CHECK(expected == generated);
	}

	BOOST_AUTO_TEST_CASE(reactive_make_buffer)
	{
		auto bridge = std::make_shared<rx::bridge<int>>();
		rx::ptr_observable<int, std::shared_ptr<rx::observable<int>>> first{bridge};
		auto buf = rx::make_buffer(first, 2);

		std::vector<int> generated;
		auto consumer = rx::consume<int>([&generated](int element)
		{
			generated.emplace_back(element);
		});
		BOOST_CHECK(generated.empty());

		for (size_t i = 0; i < 2; ++i)
		{
			BOOST_REQUIRE(bridge->is_waiting());
			bridge->got_element(7);
		}
		BOOST_CHECK(!bridge->is_waiting());
		BOOST_CHECK(generated.empty());

		buf.async_get_one(consumer);
		std::vector<int> expected(1, 7);
		BOOST_CHECK(expected == generated);

		buf.async_get_one(consumer);
		expected.emplace_back(7);
		BOOST_CHECK(expected == generated);

		buf.async_get_one(consumer);
		BOOST_CHECK(expected == generated);
	}
}
<commit_msg>begin a coroutine observable<commit_after>#include <reactive/buffer.hpp>
#include <reactive/generate.hpp>
#include <reactive/consume.hpp>
#include <reactive/tuple.hpp>
#include <reactive/ptr_observable.hpp>
#include <reactive/transform.hpp>
#include <reactive/bridge.hpp>
#include <reactive/take.hpp>
#include <reactive/enumerate.hpp>
#include <reactive/cache.hpp>
#include <reactive/connector.hpp>
#include <reactive/receiver.hpp>
#include <reactive/deref_optional.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/coroutine/all.hpp>

namespace Si
{
	BOOST_AUTO_TEST_CASE(reactive_take)
	{
		auto zeros = rx::generate([]{ return 0; });
		auto ones  = rx::generate([]{ return 1; });
		auto both = rx::make_tuple(zeros, ones);
		std::vector<std::tuple<int, int>> const expected(4, std::make_tuple(0, 1));
		std::vector<std::tuple<int, int>> const generated = rx::take(both, expected.size());
		BOOST_CHECK(expected == generated);
	}

	BOOST_AUTO_TEST_CASE(reactive_transform)
	{
		auto twos = rx::generate([]{ return 2; });
		auto ones  = rx::generate([]{ return 1; });
		auto both = rx::make_tuple(twos, ones);
		auto added = rx::transform(both, [](std::tuple<int, int> const &element)
		{
			return std::get<0>(element) + std::get<1>(element);
		});
		std::vector<int> const expected(4, 3);
		std::vector<int> const generated = rx::take(added, expected.size());
		BOOST_CHECK(expected == generated);
	}

	BOOST_AUTO_TEST_CASE(reactive_bridge)
	{
		auto bridge = std::make_shared<rx::bridge<int>>();
		rx::ptr_observable<int, std::shared_ptr<rx::observable<int>>> first(bridge);
		auto ones  = rx::generate([]{ return 1; });
		auto both = rx::make_tuple(first, ones);
		auto added = rx::transform(both, [](std::tuple<int, int> const &element)
		{
			return std::get<0>(element) + std::get<1>(element);
		});
		std::vector<int> generated;
		auto consumer = rx::consume<int>([&generated](int element)
		{
			generated.emplace_back(element);
		});
		BOOST_CHECK(generated.empty());

		added.async_get_one(consumer);
		BOOST_CHECK(generated.empty());

		bridge->got_element(2);
		std::vector<int> const expected(1, 3);
		BOOST_CHECK(expected == generated);
	}

	BOOST_AUTO_TEST_CASE(reactive_make_buffer)
	{
		auto bridge = std::make_shared<rx::bridge<int>>();
		rx::ptr_observable<int, std::shared_ptr<rx::observable<int>>> first{bridge};
		auto buf = rx::make_buffer(first, 2);

		std::vector<int> generated;
		auto consumer = rx::consume<int>([&generated](int element)
		{
			generated.emplace_back(element);
		});
		BOOST_CHECK(generated.empty());

		for (size_t i = 0; i < 2; ++i)
		{
			BOOST_REQUIRE(bridge->is_waiting());
			bridge->got_element(7);
		}
		BOOST_CHECK(!bridge->is_waiting());
		BOOST_CHECK(generated.empty());

		buf.async_get_one(consumer);
		std::vector<int> expected(1, 7);
		BOOST_CHECK(expected == generated);

		buf.async_get_one(consumer);
		expected.emplace_back(7);
		BOOST_CHECK(expected == generated);

		buf.async_get_one(consumer);
		BOOST_CHECK(expected == generated);
	}

	namespace detail
	{
		template <class Element>
		struct result
		{
			Element value;
		};

		struct nothing
		{
		};

		struct yield
		{
			rx::observable<nothing> *target;
		};

		template <class Element>
		struct make_command
		{
			typedef boost::variant<result<Element>, yield> type;
		};
	}

	template <class Element>
	struct coroutine_observable
			: public rx::observable<Element>
			, private rx::observer<detail::nothing>
			, public boost::static_visitor<> //TODO make private
	{
		typedef Element element_type;

		template <class Action>
		explicit coroutine_observable(Action &&action)
			: coro(std::forward<Action>(action))
		{
		}

		virtual void async_get_one(rx::observer<element_type> &receiver) SILICIUM_OVERRIDE
		{
			receiver_ = &receiver;
			next();
		}

		virtual void cancel() SILICIUM_OVERRIDE
		{
			throw std::logic_error("not implemented");
		}

		//TODO make private
		void operator()(detail::result<element_type> command)
		{
			return rx::exchange(receiver_, nullptr)->got_element(std::move(command.value));
		}

		//TODO make private
		void operator()(detail::yield command)
		{
			command.target->async_get_one(*this);
		}

	private:

		typedef typename detail::make_command<element_type>::type command_type;

		typename boost::coroutines::coroutine<command_type>::pull_type coro;
		rx::observer<Element> *receiver_ = nullptr;
		bool first = true;

		virtual void got_element(detail::nothing) SILICIUM_OVERRIDE
		{
			next();
		}

		virtual void ended() SILICIUM_OVERRIDE
		{
			exchange(receiver_, nullptr)->ended();
		}

		void next()
		{
			if (!rx::exchange(first, false))
			{
				coro();
			}
			if (coro)
			{
				command_type command = coro.get();
				return boost::apply_visitor(*this, command);
			}
			else
			{
				rx::exchange(receiver_, nullptr)->ended();
			}
		}
	};

	template <class Element, class Action>
	auto make_coroutine(Action &&action)
	{
		return coroutine_observable<Element>(std::forward<Action>(action));
	}

	BOOST_AUTO_TEST_CASE(reactive_coroutine)
	{
		auto co = make_coroutine<int>([](boost::coroutines::coroutine<detail::make_command<int>::type>::push_type &yield) -> void
		{
			yield(detail::result<int>{1});
			yield(detail::result<int>{2});
		});
		std::vector<int> generated;
		auto collector = rx::consume<int>([&generated](int element)
		{
			generated.emplace_back(element);
		});
		for (;;)
		{
			auto old_size = generated.size();
			co.async_get_one(collector);
			if (generated.size() == old_size)
			{
				break;
			}
			BOOST_REQUIRE(generated.size() == old_size + 1);
		}
		std::vector<int> const expected{1, 2};
		BOOST_CHECK(expected == generated);
	}
}
<|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.

*/

#include "libtorrent/assert.hpp"

#include "zlib.h"

#include <vector>
#include <string>

namespace
{
	enum
	{
		FTEXT = 0x01,
		FHCRC = 0x02,
		FEXTRA = 0x04,
		FNAME = 0x08,
		FCOMMENT = 0x10,
		FRESERVED = 0xe0,

		GZIP_MAGIC0 = 0x1f,
		GZIP_MAGIC1 = 0x8b
	};

}

namespace libtorrent
{
	// returns -1 if gzip header is invalid or the header size in bytes
	int gzip_header(const char* buf, int size)
	{
		TORRENT_ASSERT(buf != 0);
		TORRENT_ASSERT(size > 0);

		const unsigned char* buffer = reinterpret_cast<const unsigned char*>(buf);
		const int total_size = size;

		// The zip header cannot be shorter than 10 bytes
		if (size < 10) return -1;

		// check the magic header of gzip
		if ((buffer[0] != GZIP_MAGIC0) || (buffer[1] != GZIP_MAGIC1)) return -1;

		int method = buffer[2];
		int flags = buffer[3];

		// check for reserved flag and make sure it's compressed with the correct metod
		if (method != Z_DEFLATED || (flags & FRESERVED) != 0) return -1;

		// skip time, xflags, OS code
		size -= 10;
		buffer += 10;

		if (flags & FEXTRA)
		{
			int extra_len;

			if (size < 2) return -1;

			extra_len = (buffer[1] << 8) | buffer[0];

			if (size < (extra_len+2)) return -1;
			size -= (extra_len + 2);
			buffer += (extra_len + 2);
		}

		if (flags & FNAME)
		{
			while (size && *buffer)
			{
				--size;
				++buffer;
			}
			if (!size || *buffer) return -1;

			--size;
			++buffer;
		}

		if (flags & FCOMMENT)
		{
			while (size && *buffer)
			{
				--size;
				++buffer;
			}
			if (!size || *buffer) return -1;

			--size;
			++buffer;
		}

		if (flags & FHCRC)
		{
			if (size < 2) return -1;

			size -= 2;
			buffer += 2;
		}

		return total_size - size;
	}

	bool inflate_gzip(
		char const* in
		, int size
		, std::vector<char>& buffer
		, int maximum_size
		, std::string& error)
	{
		TORRENT_ASSERT(maximum_size > 0);

		int header_len = gzip_header(in, size);
		if (header_len < 0)
		{
			error = "invalid gzip header in tracker response";
			return true;
		}

		// start off with one kilobyte and grow
		// if needed
		buffer.resize(1024);

		// initialize the zlib-stream
		z_stream str;

		// subtract 8 from the end of the buffer since that's CRC32 and input size
		// and those belong to the gzip file
		str.avail_in = (int)size - header_len - 8;
		str.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(in + header_len));
		str.next_out = reinterpret_cast<Bytef*>(&buffer[0]);
		str.avail_out = (int)buffer.size();
		str.zalloc = Z_NULL;
		str.zfree = Z_NULL;
		str.opaque = 0;
		// -15 is really important. It will make inflate() not look for a zlib header
		// and just deflate the buffer
		if (inflateInit2(&str, -15) != Z_OK)
		{
			error = "gzip out of memory";
			return true;
		}

		// inflate and grow inflate_buffer as needed
		int ret = inflate(&str, Z_SYNC_FLUSH);
		while (ret == Z_OK)
		{
			if (str.avail_out == 0)
			{
				if (buffer.size() >= (unsigned)maximum_size)
				{
					inflateEnd(&str);
					error = "response too large";
					return true;
				}
				int new_size = (int)buffer.size() * 2;
				if (new_size > maximum_size)
					new_size = maximum_size;
				int old_size = (int)buffer.size();

				buffer.resize(new_size);
				str.next_out = reinterpret_cast<Bytef*>(&buffer[old_size]);
				str.avail_out = new_size - old_size;
			}

			ret = inflate(&str, Z_SYNC_FLUSH);
		}

		buffer.resize(buffer.size() - str.avail_out);
		inflateEnd(&str);

		if (ret != Z_STREAM_END)
		{
			error = "gzip error";
			return true;
		}

		// commit the resulting buffer
		return false;
	}

}

<commit_msg>removed invalid assert<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/assert.hpp"

#include "zlib.h"

#include <vector>
#include <string>

namespace
{
	enum
	{
		FTEXT = 0x01,
		FHCRC = 0x02,
		FEXTRA = 0x04,
		FNAME = 0x08,
		FCOMMENT = 0x10,
		FRESERVED = 0xe0,

		GZIP_MAGIC0 = 0x1f,
		GZIP_MAGIC1 = 0x8b
	};

}

namespace libtorrent
{
	// returns -1 if gzip header is invalid or the header size in bytes
	int gzip_header(const char* buf, int size)
	{
		TORRENT_ASSERT(buf != 0);

		const unsigned char* buffer = reinterpret_cast<const unsigned char*>(buf);
		const int total_size = size;

		// The zip header cannot be shorter than 10 bytes
		if (size < 10) return -1;

		// check the magic header of gzip
		if ((buffer[0] != GZIP_MAGIC0) || (buffer[1] != GZIP_MAGIC1)) return -1;

		int method = buffer[2];
		int flags = buffer[3];

		// check for reserved flag and make sure it's compressed with the correct metod
		if (method != Z_DEFLATED || (flags & FRESERVED) != 0) return -1;

		// skip time, xflags, OS code
		size -= 10;
		buffer += 10;

		if (flags & FEXTRA)
		{
			int extra_len;

			if (size < 2) return -1;

			extra_len = (buffer[1] << 8) | buffer[0];

			if (size < (extra_len+2)) return -1;
			size -= (extra_len + 2);
			buffer += (extra_len + 2);
		}

		if (flags & FNAME)
		{
			while (size && *buffer)
			{
				--size;
				++buffer;
			}
			if (!size || *buffer) return -1;

			--size;
			++buffer;
		}

		if (flags & FCOMMENT)
		{
			while (size && *buffer)
			{
				--size;
				++buffer;
			}
			if (!size || *buffer) return -1;

			--size;
			++buffer;
		}

		if (flags & FHCRC)
		{
			if (size < 2) return -1;

			size -= 2;
			buffer += 2;
		}

		return total_size - size;
	}

	bool inflate_gzip(
		char const* in
		, int size
		, std::vector<char>& buffer
		, int maximum_size
		, std::string& error)
	{
		TORRENT_ASSERT(maximum_size > 0);

		int header_len = gzip_header(in, size);
		if (header_len < 0)
		{
			error = "invalid gzip header in tracker response";
			return true;
		}

		// start off with one kilobyte and grow
		// if needed
		buffer.resize(1024);

		// initialize the zlib-stream
		z_stream str;

		// subtract 8 from the end of the buffer since that's CRC32 and input size
		// and those belong to the gzip file
		str.avail_in = (int)size - header_len - 8;
		str.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(in + header_len));
		str.next_out = reinterpret_cast<Bytef*>(&buffer[0]);
		str.avail_out = (int)buffer.size();
		str.zalloc = Z_NULL;
		str.zfree = Z_NULL;
		str.opaque = 0;
		// -15 is really important. It will make inflate() not look for a zlib header
		// and just deflate the buffer
		if (inflateInit2(&str, -15) != Z_OK)
		{
			error = "gzip out of memory";
			return true;
		}

		// inflate and grow inflate_buffer as needed
		int ret = inflate(&str, Z_SYNC_FLUSH);
		while (ret == Z_OK)
		{
			if (str.avail_out == 0)
			{
				if (buffer.size() >= (unsigned)maximum_size)
				{
					inflateEnd(&str);
					error = "response too large";
					return true;
				}
				int new_size = (int)buffer.size() * 2;
				if (new_size > maximum_size)
					new_size = maximum_size;
				int old_size = (int)buffer.size();

				buffer.resize(new_size);
				str.next_out = reinterpret_cast<Bytef*>(&buffer[old_size]);
				str.avail_out = new_size - old_size;
			}

			ret = inflate(&str, Z_SYNC_FLUSH);
		}

		buffer.resize(buffer.size() - str.avail_out);
		inflateEnd(&str);

		if (ret != Z_STREAM_END)
		{
			error = "gzip error";
			return true;
		}

		// commit the resulting buffer
		return false;
	}

}

<|endoftext|>


<commit_before>#include "TextureEditor.h"

namespace ofx {
namespace piMapper {
TextureEditor::TextureEditor() {
  clear();
  enable();
}

TextureEditor::~TextureEditor() {
  clear();
  disable();
}

void TextureEditor::registerAppEvents() {
  ofAddListener(ofEvents().update, this, &TextureEditor::update);
}

void TextureEditor::unregisterAppEvents() {
  ofRemoveListener(ofEvents().update, this, &TextureEditor::update);
}

void TextureEditor::registerKeyEvents() {
  ofAddListener(ofEvents().keyPressed, this, &TextureEditor::keyPressed);
  ofAddListener(ofEvents().keyReleased, this, &TextureEditor::keyReleased);
}

void TextureEditor::unregisterKeyEvents() {
  ofRemoveListener(ofEvents().keyPressed, this, &TextureEditor::keyPressed);
  ofRemoveListener(ofEvents().keyReleased, this, &TextureEditor::keyReleased);
}

void TextureEditor::enable() {
  registerAppEvents();
  registerKeyEvents();
  bShiftKeyDown = false;
}

void TextureEditor::disable() {
  unregisterAppEvents();
  unregisterKeyEvents();
}

void TextureEditor::update(ofEventArgs& args) {
  if (surface == NULL) return;

  // update surface if one of the joints is being dragged
  ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(),
                                surface->getSource()->getTexture()->getHeight());

  // Get selected joint index
  int selectedJointIndex = 0;
  bool bJointSelected = false;
  for (int i = 0; i < joints.size(); i++) {
    if (joints[i]->isDragged() || joints[i]->isSelected()) {
      selectedJointIndex = i;
      bJointSelected = true;
      break;
    }
  } // for

  // Constrain quad texture selection
  if (joints.size() == 4) {
    if (bJointSelected) {
      constrainJointsToQuad(selectedJointIndex);

      for (int i = 0; i < joints.size(); i++) {
        surface->setTexCoord(i, joints[i]->position / textureSize);
      }
    } // if
  } else {
    if (bJointSelected) {
      surface->setTexCoord(selectedJointIndex, joints[selectedJointIndex]->position / textureSize);
    }
  } // else
}

void TextureEditor::keyPressed(ofKeyEventArgs& args) {
  int key = args.key;
  float moveStep;

  if (bShiftKeyDown)
    moveStep = 10.0f;
  else
    moveStep = 0.5f;

  switch (key) {
    case OF_KEY_LEFT:
      moveSelection(ofVec2f(-moveStep, 0.0f));
      break;
    case OF_KEY_RIGHT:
      moveSelection(ofVec2f(moveStep, 0.0f));
      break;
    case OF_KEY_UP:
      moveSelection(ofVec2f(0.0f, -moveStep));
      break;
    case OF_KEY_DOWN:
      moveSelection(ofVec2f(0.0f, moveStep));
      break;
    case OF_KEY_SHIFT:
      bShiftKeyDown = true;
      break;
  }
}

void TextureEditor::keyReleased(ofKeyEventArgs& args) {
  int key = args.key;
  switch (key) {
    case OF_KEY_SHIFT:
      bShiftKeyDown = false;
      break;
  }
}

void TextureEditor::draw() {
  if (surface == NULL) return;

  drawJoints();
}

void TextureEditor::drawJoints() {
  for (int i = 0; i < joints.size(); i++) {
    joints[i]->draw();
  }
}

void TextureEditor::setSurface(BaseSurface* newSurface) {
  surface = newSurface;
  createJoints();
}

void TextureEditor::clear() {
  surface = NULL;
  clearJoints();
}

void TextureEditor::createJoints() {
  if (surface == NULL) return;
  clearJoints();
  vector<ofVec2f>& texCoords = surface->getTexCoords();
  ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(),
                                surface->getSource()->getTexture()->getHeight());

  for (int i = 0; i < texCoords.size(); i++) {
    joints.push_back(new CircleJoint());
    joints.back()->position = texCoords[i] * textureSize;
  }
}

void TextureEditor::clearJoints() {
  while (joints.size()) {
    delete joints.back();
    joints.pop_back();
  }
}

void TextureEditor::unselectAllJoints() {
  for (int i = 0; i < joints.size(); i++) {
    joints[i]->unselect();
  }
}

void TextureEditor::moveTexCoords(ofVec2f by) {
  if (surface == NULL) return;
  vector<ofVec2f>& texCoords = surface->getTexCoords();
  ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(),
                                surface->getSource()->getTexture()->getHeight());
  for (int i = 0; i < texCoords.size(); i++) {
    joints[i]->position += by;
    texCoords[i] = joints[i]->position / textureSize;
  }
}

void TextureEditor::stopDragJoints() {
  for (int i = 0; i < joints.size(); i++) {
    joints[i]->stopDrag();
  }
}

void TextureEditor::moveSelection(ofVec2f by) {
  // check if joints selected
  bool bJointSelected = false;
  BaseJoint* selectedJoint;
  for (int i = 0; i < joints.size(); i++) {
    if (joints[i]->isSelected()) {
      bJointSelected = true;
      selectedJoint = joints[i];
      break;
    }
  }

  if (bJointSelected) {
    selectedJoint->position += by;
  } else {
    moveTexCoords(by);
  }
}

void TextureEditor::constrainJointsToQuad(int selectedJointIndex)
{
  switch (selectedJointIndex) {
    case 0:
      joints[1]->position = ofVec2f(joints[1]->position.x, joints[0]->position.y);
      joints[2]->position = ofVec2f(joints[1]->position.x, joints[3]->position.y);
      joints[3]->position = ofVec2f(joints[0]->position.x, joints[3]->position.y);
      break;
    case 1:
      joints[0]->position = ofVec2f(joints[0]->position.x, joints[1]->position.y);
      joints[2]->position = ofVec2f(joints[1]->position.x, joints[2]->position.y);
      joints[3]->position = ofVec2f(joints[0]->position.x, joints[2]->position.y);
      break;
    case 2:
      joints[1]->position = ofVec2f(joints[2]->position.x, joints[1]->position.y);
      joints[3]->position = ofVec2f(joints[3]->position.x, joints[2]->position.y);
      joints[0]->position = ofVec2f(joints[3]->position.x, joints[1]->position.y);
      break;
    case 3:
      joints[0]->position = ofVec2f(joints[3]->position.x, joints[0]->position.y);
      joints[2]->position = ofVec2f(joints[2]->position.x, joints[3]->position.y);
      joints[1]->position = ofVec2f(joints[2]->position.x, joints[0]->position.y);
      break;
  } // switch
}

CircleJoint* TextureEditor::hitTestJoints(ofVec2f pos) {
  for (int i = 0; i < joints.size(); i++) {
    if (joints[i]->hitTest(pos)) {
      return joints[i];
    }
  }
  return NULL;
}
}
}<commit_msg>Fix texture coord update for quad surface [issue 15]<commit_after>#include "TextureEditor.h"

namespace ofx {
namespace piMapper {
TextureEditor::TextureEditor() {
  clear();
  enable();
}

TextureEditor::~TextureEditor() {
  clear();
  disable();
}

void TextureEditor::registerAppEvents() {
  ofAddListener(ofEvents().update, this, &TextureEditor::update);
}

void TextureEditor::unregisterAppEvents() {
  ofRemoveListener(ofEvents().update, this, &TextureEditor::update);
}

void TextureEditor::registerKeyEvents() {
  ofAddListener(ofEvents().keyPressed, this, &TextureEditor::keyPressed);
  ofAddListener(ofEvents().keyReleased, this, &TextureEditor::keyReleased);
}

void TextureEditor::unregisterKeyEvents() {
  ofRemoveListener(ofEvents().keyPressed, this, &TextureEditor::keyPressed);
  ofRemoveListener(ofEvents().keyReleased, this, &TextureEditor::keyReleased);
}

void TextureEditor::enable() {
  registerAppEvents();
  registerKeyEvents();
  bShiftKeyDown = false;
}

void TextureEditor::disable() {
  unregisterAppEvents();
  unregisterKeyEvents();
}

void TextureEditor::update(ofEventArgs& args) {
  if (surface == NULL) return;

  // update surface if one of the joints is being dragged
  ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(),
                                surface->getSource()->getTexture()->getHeight());

  // Get selected joint index
  int selectedJointIndex = 0;
  bool bJointSelected = false;
  for (int i = 0; i < joints.size(); i++) {
    if (joints[i]->isDragged() || joints[i]->isSelected()) {
      selectedJointIndex = i;
      bJointSelected = true;
      break;
    }
  } // for

  // Constrain quad texture selection
  if (joints.size() == 4) {
    if (bJointSelected) {
      constrainJointsToQuad(selectedJointIndex);

      for (int i = 0; i < joints.size(); i++) {
        surface->setTexCoord(i, joints[i]->position / textureSize);
      }
    } // if
  } else {
    if (bJointSelected) {
      surface->setTexCoord(selectedJointIndex, joints[selectedJointIndex]->position / textureSize);
    }
  } // else
}

void TextureEditor::keyPressed(ofKeyEventArgs& args) {
  int key = args.key;
  float moveStep;

  if (bShiftKeyDown)
    moveStep = 10.0f;
  else
    moveStep = 0.5f;

  switch (key) {
    case OF_KEY_LEFT:
      moveSelection(ofVec2f(-moveStep, 0.0f));
      break;
    case OF_KEY_RIGHT:
      moveSelection(ofVec2f(moveStep, 0.0f));
      break;
    case OF_KEY_UP:
      moveSelection(ofVec2f(0.0f, -moveStep));
      break;
    case OF_KEY_DOWN:
      moveSelection(ofVec2f(0.0f, moveStep));
      break;
    case OF_KEY_SHIFT:
      bShiftKeyDown = true;
      break;
  }
}

void TextureEditor::keyReleased(ofKeyEventArgs& args) {
  int key = args.key;
  switch (key) {
    case OF_KEY_SHIFT:
      bShiftKeyDown = false;
      break;
  }
}

void TextureEditor::draw() {
  if (surface == NULL) return;

  drawJoints();
}

void TextureEditor::drawJoints() {
  for (int i = 0; i < joints.size(); i++) {
    joints[i]->draw();
  }
}

void TextureEditor::setSurface(BaseSurface* newSurface) {
  surface = newSurface;
  createJoints();
}

void TextureEditor::clear() {
  surface = NULL;
  clearJoints();
}

void TextureEditor::createJoints() {
  if (surface == NULL) return;
  clearJoints();
  vector<ofVec2f>& texCoords = surface->getTexCoords();
  ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(),
                                surface->getSource()->getTexture()->getHeight());

  for (int i = 0; i < texCoords.size(); i++) {
    joints.push_back(new CircleJoint());
    joints.back()->position = texCoords[i] * textureSize;
  }
}

void TextureEditor::clearJoints() {
  while (joints.size()) {
    delete joints.back();
    joints.pop_back();
  }
}

void TextureEditor::unselectAllJoints() {
  for (int i = 0; i < joints.size(); i++) {
    joints[i]->unselect();
  }
}

void TextureEditor::moveTexCoords(ofVec2f by) {
  if (surface == NULL) return;
  vector<ofVec2f>& texCoords = surface->getTexCoords();
  ofVec2f textureSize = ofVec2f(surface->getSource()->getTexture()->getWidth(),
                                surface->getSource()->getTexture()->getHeight());
  for (int i = 0; i < texCoords.size(); i++) {
    joints[i]->position += by;
    surface->setTexCoord(i, joints[i]->position / textureSize);
  }
}

void TextureEditor::stopDragJoints() {
  for (int i = 0; i < joints.size(); i++) {
    joints[i]->stopDrag();
  }
}

void TextureEditor::moveSelection(ofVec2f by) {
  // check if joints selected
  bool bJointSelected = false;
  BaseJoint* selectedJoint;
  for (int i = 0; i < joints.size(); i++) {
    if (joints[i]->isSelected()) {
      bJointSelected = true;
      selectedJoint = joints[i];
      break;
    }
  }

  if (bJointSelected) {
    selectedJoint->position += by;
  } else {
    moveTexCoords(by);
  }
}

void TextureEditor::constrainJointsToQuad(int selectedJointIndex)
{
  switch (selectedJointIndex) {
    case 0:
      joints[1]->position = ofVec2f(joints[1]->position.x, joints[0]->position.y);
      joints[2]->position = ofVec2f(joints[1]->position.x, joints[3]->position.y);
      joints[3]->position = ofVec2f(joints[0]->position.x, joints[3]->position.y);
      break;
    case 1:
      joints[0]->position = ofVec2f(joints[0]->position.x, joints[1]->position.y);
      joints[2]->position = ofVec2f(joints[1]->position.x, joints[2]->position.y);
      joints[3]->position = ofVec2f(joints[0]->position.x, joints[2]->position.y);
      break;
    case 2:
      joints[1]->position = ofVec2f(joints[2]->position.x, joints[1]->position.y);
      joints[3]->position = ofVec2f(joints[3]->position.x, joints[2]->position.y);
      joints[0]->position = ofVec2f(joints[3]->position.x, joints[1]->position.y);
      break;
    case 3:
      joints[0]->position = ofVec2f(joints[3]->position.x, joints[0]->position.y);
      joints[2]->position = ofVec2f(joints[2]->position.x, joints[3]->position.y);
      joints[1]->position = ofVec2f(joints[2]->position.x, joints[0]->position.y);
      break;
  } // switch
}

CircleJoint* TextureEditor::hitTestJoints(ofVec2f pos) {
  for (int i = 0; i < joints.size(); i++) {
    if (joints[i]->hitTest(pos)) {
      return joints[i];
    }
  }
  return NULL;
}
}
}<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file IfImpl.hxx
 *
 * Implementation details for the asynchronous NMRAnet interfaces. This file
 * should only be needed in hardware interface implementations.
 *
 * @author Balazs Racz
 * @date 4 Dec 2013
 */

#ifndef _NMRANET_IFIMPL_HXX_
#define _NMRANET_IFIMPL_HXX_

#include "nmranet/If.hxx"

namespace nmranet
{

/** Implementation of the hardware-independent parts of the write flows. */
class WriteFlowBase : public StateFlow<Buffer<NMRAnetMessage>, QList<4>>
{
public:
    WriteFlowBase(If *async_if)
        : StateFlow<Buffer<NMRAnetMessage>, QList<4>>(async_if)
    {
    }

protected:
    /** This function will be called (on the main executor) to initiate sending
     * this message to the hardware. The flow will then execute the returned
     * action.
     *
     * NOTE: it is possible that this functon will never be called for a given
     * flow. */
    virtual Action send_to_hardware() = 0;

    /** Virtual method called after the send is completed, i.e., all the frames
     * are generated and sent to the hardware. Various flows might need to take
     * additional steps afterwards. */
    virtual Action send_finished()
    {
        return release_and_exit();
    }

    /// @returns the interface that this flow is assigned to.
    If *async_if()
    {
        return static_cast<If *>(service());
    }

    /** Implementations shall call this function when they are done with
     * sending the packet.
     */
    // void cleanup();

    /// Returns the NMRAnet message we are trying to send.
    NMRAnetMessage *nmsg()
    {
        return message()->data();
    }

protected:
    /*    /// Entry point for external callers.
        virtual void WriteAddressedMessage(Defs::MTI mti, NodeID src, NodeHandle
       dst,
                                           Buffer* data, Notifiable* done)
        {
            HASSERT(IsNotStarted());
            Restart(done);
            mti_ = mti;
            src_ = src;
            dst_ = dst;
            dstNode_ = nullptr;
            data_ = data;
            StartFlowAt(STATE(maybe_send_to_local_node));
        }

        /// Entry point for external callers.
        virtual void WriteGlobalMessage(Defs::MTI mti, NodeID src, Buffer* data,
                                        Notifiable* done)
        {
            HASSERT(IsNotStarted());
            Restart(done);
            mti_ = mti;
            src_ = src;
            dst_.id = 0;
            dst_.alias = 0;
            dstNode_ = nullptr;
            data_ = data;
            StartFlowAt(STATE(send_to_local_nodes));
        }
    */

    /** Addressed write flows should call this state BEFORE sending to the
     * hardware. They may get back control at the send_to_hardware state if
     * needed.
     * NOTE: datagram write flow cannot use this because it won't get back. */
    Action addressed_entry();
    /** Global write flows should return to this state AFTER sending the
     * message to the hardware. They should ensure the message is still
     * intact. They will not get back control. */
    Action global_entry();
};

/** This handler handles VerifyNodeId messages (both addressed and global) on
 * the interface level. Each interface implementation will want to create one
 * of these. */
class VerifyNodeIdHandler : public IncomingMessageStateFlow
{
public:
    VerifyNodeIdHandler(If *service) : IncomingMessageStateFlow(service)
    {
        interface()->dispatcher()->register_handler(
            this,
            Defs::MTI_VERIFY_NODE_ID_GLOBAL & Defs::MTI_VERIFY_NODE_ID_ADDRESSED,
            0xffff & ~(Defs::MTI_VERIFY_NODE_ID_GLOBAL ^
                       Defs::MTI_VERIFY_NODE_ID_ADDRESSED));
    }

    ~VerifyNodeIdHandler()
    {
        interface()->dispatcher()->unregister_handler(
            this,
            Defs::MTI_VERIFY_NODE_ID_GLOBAL & Defs::MTI_VERIFY_NODE_ID_ADDRESSED,
            0xffff & ~(Defs::MTI_VERIFY_NODE_ID_GLOBAL ^
                       Defs::MTI_VERIFY_NODE_ID_ADDRESSED));
    }

    /// Handler callback for incoming messages.
    virtual Action entry()
    {
        NMRAnetMessage *m = message()->data();
        if (m->dst.id)
        {
            // Addressed message.
            srcNode_ = m->dstNode;
        }
        else if (!m->payload.empty() && m->payload.size() == 6)
        {
            // Global message with a node id included
            NodeID id = buffer_to_node_id(m->payload);
            srcNode_ = interface()->lookup_local_node(id);
        }
        else
        {
// Global message. Everyone should respond.
#ifdef SIMPLE_NODE_ONLY
            // We assume there can be only one local node.
            If::VNodeMap::Iterator it = interface()->localNodes_.begin();
            if (it == interface()->localNodes_.end())
            {
                // No local nodes.
                return release_and_exit();
            }
            srcNode_ = it->second;
            ++it;
            HASSERT(it == interface()->localNodes_.end());
#else
            // We need to do an iteration over all local nodes.
            it_ = interface()->localNodes_.begin();
            if (it_ == interface()->localNodes_.end())
            {
                // No local nodes.
                return release_and_exit();
            }
            srcNode_ = it_->second;
            ++it_;
#endif // not simple node.
        }
        if (srcNode_)
        {
            release();
            return allocate_and_call(interface()->global_message_write_flow(),
                                     STATE(send_response));
        }
        LOG(WARNING, "node pointer not found.");
        return release_and_exit();
    }

#ifdef SIMPLE_NODE_ONLY
    Action send_response()
    {
        auto *b =
            get_allocation_result(interface()->global_message_write_flow());
        NMRAnetMessage *m = b->data();
        NodeID id = srcNode_->node_id();
        m->reset(Defs::MTI_VERIFIED_NODE_ID_NUMBER, id, node_id_to_buffer(id));
        interface()->global_message_write_flow()->send(b);
        return exit();
    }
#else
    Action send_response()
    {
        auto *b =
            get_allocation_result(interface()->global_message_write_flow());
        NMRAnetMessage *m = b->data();
        // This is called on the main executor of the interface, this we are
        // allowed to access the local nodes cache.
        NodeID id = srcNode_->node_id();
        LOG(VERBOSE, "Sending verified reply from node %012llx", id);
        m->reset(Defs::MTI_VERIFIED_NODE_ID_NUMBER, id, node_id_to_buffer(id));
        interface()->global_message_write_flow()->send(b);

        /** Continues the iteration over the nodes.
         *
         * @TODO(balazs.racz): we should probably wait for the outgoing message
         * to be sent. */
        if (it_ != interface()->localNodes_.end())
        {
            srcNode_ = it_->second;
            ++it_;
            return allocate_and_call(interface()->global_message_write_flow(),
                                     STATE(send_response));
        }
        else
        {
            return exit();
        }
    }
#endif // not simple node

private:
    Node *srcNode_;

#ifndef SIMPLE_NODE_ONLY
    If::VNodeMap::Iterator it_;
#endif
};
} // namespace nmranet

#endif // _NMRANET_IFIMPL_HXX_
<commit_msg>Makes verify nodeid handler not complain when it receives a global unaddressed verify node id with a payload that is not for the current interface. This is regular traffic between nodes unrelated to us.<commit_after>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file IfImpl.hxx
 *
 * Implementation details for the asynchronous NMRAnet interfaces. This file
 * should only be needed in hardware interface implementations.
 *
 * @author Balazs Racz
 * @date 4 Dec 2013
 */

#ifndef _NMRANET_IFIMPL_HXX_
#define _NMRANET_IFIMPL_HXX_

#include "nmranet/If.hxx"

namespace nmranet
{

/** Implementation of the hardware-independent parts of the write flows. */
class WriteFlowBase : public StateFlow<Buffer<NMRAnetMessage>, QList<4>>
{
public:
    WriteFlowBase(If *async_if)
        : StateFlow<Buffer<NMRAnetMessage>, QList<4>>(async_if)
    {
    }

protected:
    /** This function will be called (on the main executor) to initiate sending
     * this message to the hardware. The flow will then execute the returned
     * action.
     *
     * NOTE: it is possible that this functon will never be called for a given
     * flow. */
    virtual Action send_to_hardware() = 0;

    /** Virtual method called after the send is completed, i.e., all the frames
     * are generated and sent to the hardware. Various flows might need to take
     * additional steps afterwards. */
    virtual Action send_finished()
    {
        return release_and_exit();
    }

    /// @returns the interface that this flow is assigned to.
    If *async_if()
    {
        return static_cast<If *>(service());
    }

    /** Implementations shall call this function when they are done with
     * sending the packet.
     */
    // void cleanup();

    /// Returns the NMRAnet message we are trying to send.
    NMRAnetMessage *nmsg()
    {
        return message()->data();
    }

protected:
    /*    /// Entry point for external callers.
        virtual void WriteAddressedMessage(Defs::MTI mti, NodeID src, NodeHandle
       dst,
                                           Buffer* data, Notifiable* done)
        {
            HASSERT(IsNotStarted());
            Restart(done);
            mti_ = mti;
            src_ = src;
            dst_ = dst;
            dstNode_ = nullptr;
            data_ = data;
            StartFlowAt(STATE(maybe_send_to_local_node));
        }

        /// Entry point for external callers.
        virtual void WriteGlobalMessage(Defs::MTI mti, NodeID src, Buffer* data,
                                        Notifiable* done)
        {
            HASSERT(IsNotStarted());
            Restart(done);
            mti_ = mti;
            src_ = src;
            dst_.id = 0;
            dst_.alias = 0;
            dstNode_ = nullptr;
            data_ = data;
            StartFlowAt(STATE(send_to_local_nodes));
        }
    */

    /** Addressed write flows should call this state BEFORE sending to the
     * hardware. They may get back control at the send_to_hardware state if
     * needed.
     * NOTE: datagram write flow cannot use this because it won't get back. */
    Action addressed_entry();
    /** Global write flows should return to this state AFTER sending the
     * message to the hardware. They should ensure the message is still
     * intact. They will not get back control. */
    Action global_entry();
};

/** This handler handles VerifyNodeId messages (both addressed and global) on
 * the interface level. Each interface implementation will want to create one
 * of these. */
class VerifyNodeIdHandler : public IncomingMessageStateFlow
{
public:
    VerifyNodeIdHandler(If *service) : IncomingMessageStateFlow(service)
    {
        interface()->dispatcher()->register_handler(
            this, Defs::MTI_VERIFY_NODE_ID_GLOBAL &
                      Defs::MTI_VERIFY_NODE_ID_ADDRESSED,
            0xffff & ~(Defs::MTI_VERIFY_NODE_ID_GLOBAL ^
                       Defs::MTI_VERIFY_NODE_ID_ADDRESSED));
    }

    ~VerifyNodeIdHandler()
    {
        interface()->dispatcher()->unregister_handler(
            this, Defs::MTI_VERIFY_NODE_ID_GLOBAL &
                      Defs::MTI_VERIFY_NODE_ID_ADDRESSED,
            0xffff & ~(Defs::MTI_VERIFY_NODE_ID_GLOBAL ^
                       Defs::MTI_VERIFY_NODE_ID_ADDRESSED));
    }

    /// Handler callback for incoming messages.
    virtual Action entry()
    {
        NMRAnetMessage *m = message()->data();
        if (m->dst.id)
        {
            // Addressed message.
            srcNode_ = m->dstNode;
        }
        else if (!m->payload.empty() && m->payload.size() == 6)
        {
            // Global message with a node id included
            NodeID id = buffer_to_node_id(m->payload);
            srcNode_ = interface()->lookup_local_node(id);
            if (!srcNode_)
            {
                // Someone looking for a node that's not on this interface.
                return release_and_exit();
            }
        }
        else
        {
// Global message. Everyone should respond.
#ifdef SIMPLE_NODE_ONLY
            // We assume there can be only one local node.
            If::VNodeMap::Iterator it = interface()->localNodes_.begin();
            if (it == interface()->localNodes_.end())
            {
                // No local nodes.
                return release_and_exit();
            }
            srcNode_ = it->second;
            ++it;
            HASSERT(it == interface()->localNodes_.end());
#else
            // We need to do an iteration over all local nodes.
            it_ = interface()->localNodes_.begin();
            if (it_ == interface()->localNodes_.end())
            {
                // No local nodes.
                return release_and_exit();
            }
            srcNode_ = it_->second;
            ++it_;
#endif // not simple node.
        }
        if (srcNode_)
        {
            release();
            return allocate_and_call(interface()->global_message_write_flow(),
                                     STATE(send_response));
        }
        LOG(WARNING, "node pointer not found.");
        return release_and_exit();
    }

#ifdef SIMPLE_NODE_ONLY
    Action send_response()
    {
        auto *b =
            get_allocation_result(interface()->global_message_write_flow());
        NMRAnetMessage *m = b->data();
        NodeID id = srcNode_->node_id();
        m->reset(Defs::MTI_VERIFIED_NODE_ID_NUMBER, id, node_id_to_buffer(id));
        interface()->global_message_write_flow()->send(b);
        return exit();
    }
#else
    Action send_response()
    {
        auto *b =
            get_allocation_result(interface()->global_message_write_flow());
        NMRAnetMessage *m = b->data();
        // This is called on the main executor of the interface, this we are
        // allowed to access the local nodes cache.
        NodeID id = srcNode_->node_id();
        LOG(VERBOSE, "Sending verified reply from node %012llx", id);
        m->reset(Defs::MTI_VERIFIED_NODE_ID_NUMBER, id, node_id_to_buffer(id));
        interface()->global_message_write_flow()->send(b);

        /** Continues the iteration over the nodes.
         *
         * @TODO(balazs.racz): we should probably wait for the outgoing message
         * to be sent. */
        if (it_ != interface()->localNodes_.end())
        {
            srcNode_ = it_->second;
            ++it_;
            return allocate_and_call(interface()->global_message_write_flow(),
                                     STATE(send_response));
        }
        else
        {
            return exit();
        }
    }
#endif // not simple node

private:
    Node *srcNode_;

#ifndef SIMPLE_NODE_ONLY
    If::VNodeMap::Iterator it_;
#endif
};
} // namespace nmranet

#endif // _NMRANET_IFIMPL_HXX_
<|endoftext|>


<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (c) Olivier Devillers <Olivier.Devillers@sophia.inria.fr>
 * Copyright (C) 2006 Refractions Research Inc.
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Last port: algorithm/RobustDeterminant.java 1.15 (JTS-1.10)
 *
 **********************************************************************/

#include <geos/algorithm/RobustDeterminant.h>
#include <geos/util/IllegalArgumentException.h>

#include <cmath>

#include <geos/platform.h> // for ISNAN, FINITE

#ifdef _MSC_VER
#pragma warning(disable : 4127)
#endif

using namespace std; // for isfinite..

namespace geos {
namespace algorithm { // geos.algorithm

int RobustDeterminant::signOfDet2x2(double x1,double y1,double x2,double y2) {
	// returns -1 if the determinant is negative,
	// returns  1 if the determinant is positive,
	// retunrs  0 if the determinant is null.
	int sign=1;
	double swap;
	double k;
	long count=0;

  // Protect against non-finite numbers
  if ( ISNAN(x1)   || ISNAN(y1)   || ISNAN(x2)   || ISNAN(y2) ||
       !FINITE(x1) || !FINITE(y1) || !FINITE(x2) || !FINITE(y2) )
  {
    throw util::IllegalArgumentException("RobustDeterminant encountered non-finite numbers ");
  }

	/*
	*  testing null entries
	*/
	if ((x1==0.0) || (y2==0.0)) {
		if ((y1==0.0) || (x2==0.0)) {
			return 0;
		} else if (y1>0) {
			if (x2>0) {
				return -sign;
			} else {
				return sign;
			}
		} else {
			if (x2>0) {
				return sign;
			} else {
				return -sign;
			}
		}
	}
	if ((y1==0.0) || (x2==0.0)) {
		if (y2>0) {
			if (x1>0) {
				return sign;
			} else {
				return -sign;
			}
		} else {
			if (x1>0) {
				return -sign;
			} else {
				return sign;
			}
		}
	}

	/*
	*  making y coordinates positive and permuting the entries
	*  so that y2 is the biggest one
	*/
	if (0.0<y1) {
		if (0.0<y2) {
			if (y1<=y2) {
				;
			} else {
				sign=-sign;
				swap=x1;
				x1=x2;
				x2=swap;
				swap=y1;
				y1=y2;
				y2=swap;
			}
		} else {
			if (y1<=-y2) {
				sign=-sign;
				x2=-x2;
				y2=-y2;
			} else {
				swap=x1;
				x1=-x2;
				x2=swap;
				swap=y1;
				y1=-y2;
				y2=swap;
			}
		}
	} else {
		if (0.0<y2) {
			if (-y1<=y2) {
				sign=-sign;
				x1=-x1;
				y1=-y1;
			} else {
				swap=-x1;
				x1=x2;
				x2=swap;
				swap=-y1;
				y1=y2;
				y2=swap;
			}
		} else {
			if (y1>=y2) {
				x1=-x1;
				y1=-y1;
				x2=-x2;
				y2=-y2;
			} else {
				sign=-sign;
				swap=-x1;
				x1=-x2;
				x2=swap;
				swap=-y1;
				y1=-y2;
				y2=swap;
			}
		}
	}

	/*
	*  making x coordinates positive
	*/
	/*
	*  if |x2|<|x1| one can conclude
	*/
	if (0.0<x1) {
		if (0.0<x2) {
			if (x1 <= x2) {
				;
			} else {
				return sign;
			}
		} else {
			return sign;
		}
	} else {
		if (0.0<x2) {
			return -sign;
		} else {
			if (x1 >= x2) {
				sign=-sign;
				x1=-x1;
				x2=-x2;
			} else {
				return -sign;
			}
		}
	}

	/*
	*  all entries strictly positive   x1 <= x2 and y1 <= y2
	*/
	while (true) {
		count=count+1;
		k=std::floor(x2/x1);
		x2=x2-k*x1;
		y2=y2-k*y1;

		/*
		*  testing if R (new U2) is in U1 rectangle
		*/
		if (y2<0.0) {
			return -sign;
		}
		if (y2>y1) {
			return sign;
		}

		/*
		*  finding R'
		*/
		if (x1>x2+x2) {
			if (y1<y2+y2) {
				return sign;
			}
		} else {
			if (y1>y2+y2) {
				return -sign;
			} else {
				x2=x1-x2;
				y2=y1-y2;
				sign=-sign;
			}
		}
		if (y2==0.0) {
			if (x2==0.0) {
				return 0;
			} else {
				return -sign;
			}
		}
		if (x2==0.0) {
			return sign;
		}

		/*
		*  exchange 1 and 2 role.
		*/
		k=std::floor(x1/x2);
		x1=x1-k*x2;
		y1=y1-k*y2;

		/*
		*  testing if R (new U1) is in U2 rectangle
		*/
		if (y1<0.0) {
			return sign;
		}
		if (y1>y2) {
			return -sign;
		}

		/*
		*  finding R'
		*/
		if (x2>x1+x1) {
			if (y2<y1+y1) {
				return -sign;
			}
		} else {
			if (y2>y1+y1) {
				return sign;
			} else {
				x1=x2-x1;
				y1=y2-y1;
				sign=-sign;
			}
		}
		if (y1==0.0) {
			if (x1==0.0) {
				return 0;
			} else {
				return sign;
			}
		}
		if (x1==0.0) {
			return -sign;
		}
	}
}
} // namespace geos.algorithm
} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.10  2006/03/21 11:12:23  strk
 * Cleanups: headers inclusion and Log section
 *
 * Revision 1.9  2006/03/21 10:46:03  strk
 * streamlined header inclusion, put original copyright on top
 *
 * Revision 1.8  2006/02/19 19:46:49  strk
 * Packages <-> namespaces mapping for most GEOS internal code (uncomplete, but working). Dir-level libs for index/ subdirs.
 *
 **********************************************************************/

<commit_msg>Drop unused variable<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (c) Olivier Devillers <Olivier.Devillers@sophia.inria.fr>
 * Copyright (C) 2006 Refractions Research Inc.
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Last port: algorithm/RobustDeterminant.java 1.15 (JTS-1.10)
 *
 **********************************************************************/

#include <geos/algorithm/RobustDeterminant.h>
#include <geos/util/IllegalArgumentException.h>

#include <cmath>

#include <geos/platform.h> // for ISNAN, FINITE

#ifdef _MSC_VER
#pragma warning(disable : 4127)
#endif

using namespace std; // for isfinite..

namespace geos {
namespace algorithm { // geos.algorithm

int RobustDeterminant::signOfDet2x2(double x1,double y1,double x2,double y2) {
	// returns -1 if the determinant is negative,
	// returns  1 if the determinant is positive,
	// retunrs  0 if the determinant is null.
	int sign=1;
	double swap;
	double k;

  // Protect against non-finite numbers
  if ( ISNAN(x1)   || ISNAN(y1)   || ISNAN(x2)   || ISNAN(y2) ||
       !FINITE(x1) || !FINITE(y1) || !FINITE(x2) || !FINITE(y2) )
  {
    throw util::IllegalArgumentException("RobustDeterminant encountered non-finite numbers ");
  }

	/*
	*  testing null entries
	*/
	if ((x1==0.0) || (y2==0.0)) {
		if ((y1==0.0) || (x2==0.0)) {
			return 0;
		} else if (y1>0) {
			if (x2>0) {
				return -sign;
			} else {
				return sign;
			}
		} else {
			if (x2>0) {
				return sign;
			} else {
				return -sign;
			}
		}
	}
	if ((y1==0.0) || (x2==0.0)) {
		if (y2>0) {
			if (x1>0) {
				return sign;
			} else {
				return -sign;
			}
		} else {
			if (x1>0) {
				return -sign;
			} else {
				return sign;
			}
		}
	}

	/*
	*  making y coordinates positive and permuting the entries
	*  so that y2 is the biggest one
	*/
	if (0.0<y1) {
		if (0.0<y2) {
			if (y1<=y2) {
				;
			} else {
				sign=-sign;
				swap=x1;
				x1=x2;
				x2=swap;
				swap=y1;
				y1=y2;
				y2=swap;
			}
		} else {
			if (y1<=-y2) {
				sign=-sign;
				x2=-x2;
				y2=-y2;
			} else {
				swap=x1;
				x1=-x2;
				x2=swap;
				swap=y1;
				y1=-y2;
				y2=swap;
			}
		}
	} else {
		if (0.0<y2) {
			if (-y1<=y2) {
				sign=-sign;
				x1=-x1;
				y1=-y1;
			} else {
				swap=-x1;
				x1=x2;
				x2=swap;
				swap=-y1;
				y1=y2;
				y2=swap;
			}
		} else {
			if (y1>=y2) {
				x1=-x1;
				y1=-y1;
				x2=-x2;
				y2=-y2;
			} else {
				sign=-sign;
				swap=-x1;
				x1=-x2;
				x2=swap;
				swap=-y1;
				y1=-y2;
				y2=swap;
			}
		}
	}

	/*
	*  making x coordinates positive
	*/
	/*
	*  if |x2|<|x1| one can conclude
	*/
	if (0.0<x1) {
		if (0.0<x2) {
			if (x1 <= x2) {
				;
			} else {
				return sign;
			}
		} else {
			return sign;
		}
	} else {
		if (0.0<x2) {
			return -sign;
		} else {
			if (x1 >= x2) {
				sign=-sign;
				x1=-x1;
				x2=-x2;
			} else {
				return -sign;
			}
		}
	}

	/*
	*  all entries strictly positive   x1 <= x2 and y1 <= y2
	*/
	while (true) {
		k=std::floor(x2/x1);
		x2=x2-k*x1;
		y2=y2-k*y1;

		/*
		*  testing if R (new U2) is in U1 rectangle
		*/
		if (y2<0.0) {
			return -sign;
		}
		if (y2>y1) {
			return sign;
		}

		/*
		*  finding R'
		*/
		if (x1>x2+x2) {
			if (y1<y2+y2) {
				return sign;
			}
		} else {
			if (y1>y2+y2) {
				return -sign;
			} else {
				x2=x1-x2;
				y2=y1-y2;
				sign=-sign;
			}
		}
		if (y2==0.0) {
			if (x2==0.0) {
				return 0;
			} else {
				return -sign;
			}
		}
		if (x2==0.0) {
			return sign;
		}

		/*
		*  exchange 1 and 2 role.
		*/
		k=std::floor(x1/x2);
		x1=x1-k*x2;
		y1=y1-k*y2;

		/*
		*  testing if R (new U1) is in U2 rectangle
		*/
		if (y1<0.0) {
			return sign;
		}
		if (y1>y2) {
			return -sign;
		}

		/*
		*  finding R'
		*/
		if (x2>x1+x1) {
			if (y2<y1+y1) {
				return -sign;
			}
		} else {
			if (y2>y1+y1) {
				return sign;
			} else {
				x1=x2-x1;
				y1=y2-y1;
				sign=-sign;
			}
		}
		if (y1==0.0) {
			if (x1==0.0) {
				return 0;
			} else {
				return sign;
			}
		}
		if (x1==0.0) {
			return -sign;
		}
	}
}
} // namespace geos.algorithm
} // namespace geos

<|endoftext|>


<commit_before>/*
* Basic Allocators
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/internal/defalloc.h>
#include <botan/internal/mlock.h>
#include <botan/libstate.h>
#include <cstdlib>
#include <cstring>

namespace Botan {

namespace {

/*
* Perform Memory Allocation
*/
void* do_malloc(u32bit n, bool do_lock)
   {
   void* ptr = std::malloc(n);

   if(!ptr)
      return 0;

   if(do_lock)
      lock_mem(ptr, n);

   std::memset(ptr, 0, n);
   return ptr;
   }

/*
* Perform Memory Deallocation
*/
void do_free(void* ptr, u32bit n, bool do_lock)
   {
   if(!ptr)
      return;

   std::memset(ptr, 0, n);
   if(do_lock)
      unlock_mem(ptr, n);

   std::free(ptr);
   }

}

/*
* Malloc_Allocator's Allocation
*/
void* Malloc_Allocator::allocate(u32bit n)
   {
   return do_malloc(n, false);
   }

/*
* Malloc_Allocator's Deallocation
*/
void Malloc_Allocator::deallocate(void* ptr, u32bit n)
   {
   do_free(ptr, n, false);
   }

/*
* Locking_Allocator's Allocation
*/
void* Locking_Allocator::alloc_block(u32bit n)
   {
   return do_malloc(n, true);
   }

/*
* Locking_Allocator's Deallocation
*/
void Locking_Allocator::dealloc_block(void* ptr, u32bit n)
   {
   do_free(ptr, n, true);
   }

/*
* Get an allocator
*/
Allocator* Allocator::get(bool locking)
   {
   std::string type = "";
   if(!locking)
      type = "malloc";

   Allocator* alloc = global_state().get_allocator(type);
   if(alloc)
      return alloc;

   throw Internal_Error("Couldn't find an allocator to use in get_allocator");
   }

}
<commit_msg>Malloc_Allocator isn't a pool, so it needs to fail directly if malloc fails, not just return 0 since callers expect that the allocator will either succeed or throw.<commit_after>/*
* Basic Allocators
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/internal/defalloc.h>
#include <botan/internal/mlock.h>
#include <botan/libstate.h>
#include <cstdlib>
#include <cstring>

namespace Botan {

namespace {

/*
* Perform Memory Allocation
*/
void* do_malloc(u32bit n, bool do_lock)
   {
   void* ptr = std::malloc(n);

   if(!ptr)
      return 0;

   if(do_lock)
      lock_mem(ptr, n);

   std::memset(ptr, 0, n);
   return ptr;
   }

/*
* Perform Memory Deallocation
*/
void do_free(void* ptr, u32bit n, bool do_lock)
   {
   if(!ptr)
      return;

   std::memset(ptr, 0, n);
   if(do_lock)
      unlock_mem(ptr, n);

   std::free(ptr);
   }

}

/*
* Malloc_Allocator's Allocation
*/
void* Malloc_Allocator::allocate(u32bit n)
   {
   void* ptr = do_malloc(n, false);
   if(!ptr)
      throw Memory_Exhaustion();
   }

/*
* Malloc_Allocator's Deallocation
*/
void Malloc_Allocator::deallocate(void* ptr, u32bit n)
   {
   do_free(ptr, n, false);
   }

/*
* Locking_Allocator's Allocation
*/
void* Locking_Allocator::alloc_block(u32bit n)
   {
   return do_malloc(n, true);
   }

/*
* Locking_Allocator's Deallocation
*/
void Locking_Allocator::dealloc_block(void* ptr, u32bit n)
   {
   do_free(ptr, n, true);
   }

/*
* Get an allocator
*/
Allocator* Allocator::get(bool locking)
   {
   std::string type = "";
   if(!locking)
      type = "malloc";

   Allocator* alloc = global_state().get_allocator(type);
   if(alloc)
      return alloc;

   throw Internal_Error("Couldn't find an allocator to use in get_allocator");
   }

}
<|endoftext|>


<commit_before>// Copyright (c) 2014, Baidu.com, Inc. All Rights Reserved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Author: yanshiguang02@baidu.com

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <bfs.h>

int main() {
    bfs::FS *fs = NULL;
    if (!bfs::FS::OpenFileSystem("127.0.0.1:8028", &fs)) {
        printf("Open fs fail\n");
        return 1;
    }

    bfs::File *file = NULL;
    bool ret = fs->OpenFile("/synctest", O_WRONLY, &file);
    assert(ret);
    const char* hw = "Hello world~\n";
    file->Write(hw, strlen(hw));
    file->Sync();

    ret = fs->OpenFile("/synctest", O_RDONLY, &file);
    assert(ret);
    char buff[64] = {};
    int64_t len = file->Read(buff, 1024);
    printf("Read return %ld, buff: %s\n", len, buff);
    return 0;
}

/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
<commit_msg>Delete blanks lines<commit_after>// Copyright (c) 2014, Baidu.com, Inc. All Rights Reserved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Author: yanshiguang02@baidu.com

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <bfs.h>

int main() {
    bfs::FS *fs = NULL;
    if (!bfs::FS::OpenFileSystem("127.0.0.1:8028", &fs)) {
        printf("Open fs fail\n");
        return 1;
    }

    bfs::File *file = NULL;
    bool ret = fs->OpenFile("/synctest", O_WRONLY, &file);
    assert(ret);
    const char* hw = "Hello world~\n";
    file->Write(hw, strlen(hw));
    file->Sync();

    ret = fs->OpenFile("/synctest", O_RDONLY, &file);
    assert(ret);
    char buff[64] = {};
    int64_t len = file->Read(buff, 1024);
    printf("Read return %ld, buff: %s\n", len, buff);
    return 0;
}

/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
<|endoftext|>