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

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

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

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

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;
		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();
		}

		void open(fs::path const& path, int mode)
		{
			assert(path.is_complete());
			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() << "'. "
					<< strerror(errno);
				throw file_error(msg.str());
			}
			m_open_mode = mode;
		}

		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)
		{
			assert(m_open_mode & mode_in);
			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: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			assert(m_open_mode & mode_out);
			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: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		void set_size(size_type s)
		{
			size_type pos = tell();
			seek(s - 1);
			char dummy = 0;
			read(&dummy, 1);
			seek(s - 1);
			write(&dummy, 1);
			seek(pos);
		}

		size_type seek(size_type offset, int m = 1)
		{
			assert(m_open_mode);
			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: '" << strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				throw file_error(msg.str());
			}
			return ret;
		}

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

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

		int m_fd;
		int m_open_mode;
	};

	// 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() {}

	void file::open(fs::path const& p, file::open_mode m)
	{
		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);
	}

	void file::set_size(size_type s)
	{
		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();
	}

}
<commit_msg>fixed issue where file::set_size would update the file modification date even when the size was not changed (fixes #105)<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"

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

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

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

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;
		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();
		}

		void open(fs::path const& path, int mode)
		{
			assert(path.is_complete());
			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() << "'. "
					<< strerror(errno);
				throw file_error(msg.str());
			}
			m_open_mode = mode;
		}

		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)
		{
			assert(m_open_mode & mode_in);
			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: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			assert(m_open_mode & mode_out);
			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: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		void set_size(size_type s)
		{
			size_type pos = tell();
			// Only set size if current file size not equals s.
			// 2 as "m" argument is to be sure seek() sets SEEK_END on
			// all compilers.
			if(s != seek(0, 2))
			{
				seek(s - 1);
				char dummy = 0;
				read(&dummy, 1);
				seek(s - 1);
				write(&dummy, 1);
			}
			seek(pos);
		}

		size_type seek(size_type offset, int m = 1)
		{
			assert(m_open_mode);
			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: '" << strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				throw file_error(msg.str());
			}
			return ret;
		}

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

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

		int m_fd;
		int m_open_mode;
	};

	// 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() {}

	void file::open(fs::path const& p, file::open_mode m)
	{
		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);
	}

	void file::set_size(size_type s)
	{
		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();
	}

}
<|endoftext|>


<commit_before>#ifndef MANIFOLDS_ZERO_FUNCTION_HH
#define MANIFOLDS_ZERO_FUNCTION_HH

#include "full_function_defs.hh"
#include <ostream>

namespace manifolds {
  struct ZeroImpl : MultiFunction
{
  static const bool stateless = true;

  template <class ... Args>
  auto operator()(Args...) const
  {
    return 0;
  }
};

  DEF_FULL_FUNCTION(Zero)

  static const Zero zero;

  inline std::ostream & operator<<(std::ostream & s, Zero z)
  {
    return s << "Zero";
  }
}

#include "simplify.hh"
#include "addition.hh"
#include "multiplication.hh"

namespace manifolds {
  template <class T>
  struct Simplification<Addition<T,Zero>>
  {
    typedef T type;

    static type Combine(Addition<T,Zero> t)
    {
      return std::get<0>(t.GetFunctions());
    }
  };

  template <class T>
  struct Simplification<
    Addition<Zero,T>,
    typename std::enable_if<
      !std::is_same<Zero,T>::value>::type>
  {
    typedef T type;

    static type Combine(Addition<Zero,T> t)
    {
      return std::get<1>(t.GetFunctions());
    }
  };

  template <class T>
  struct Simplification<Multiplication<T,Zero>>
  {
    typedef Zero type;
    static type Combine(Multiplication<T,Zero>)
    {
      return zero;
    }
  };

  template <class T>
  struct Simplification<Multiplication<Zero,T>,
		  typename std::enable_if<
		    !std::is_same<T,Zero>::value>::type>
  {
    typedef Zero type;

    static type Combine(Multiplication<Zero,T> )
    {
      return zero;
    }
  };
}

#endif
<commit_msg>fixing error that gcc didn't report<commit_after>#ifndef MANIFOLDS_ZERO_FUNCTION_HH
#define MANIFOLDS_ZERO_FUNCTION_HH

#include "full_function_defs.hh"
#include <ostream>

namespace manifolds {
  struct ZeroImpl : MultiFunction
{
  static const bool stateless = true;

  template <class ... Args>
  auto operator()(Args...) const
  {
    return 0;
  }
};

  DEF_FULL_FUNCTION(Zero)

  static const Zero zero = Zero();

  inline std::ostream & operator<<(std::ostream & s, Zero z)
  {
    return s << "Zero";
  }
}

#include "simplify.hh"
#include "addition.hh"
#include "multiplication.hh"

namespace manifolds {
  template <class T>
  struct Simplification<Addition<T,Zero>>
  {
    typedef T type;

    static type Combine(Addition<T,Zero> t)
    {
      return std::get<0>(t.GetFunctions());
    }
  };

  template <class T>
  struct Simplification<
    Addition<Zero,T>,
    typename std::enable_if<
      !std::is_same<Zero,T>::value>::type>
  {
    typedef T type;

    static type Combine(Addition<Zero,T> t)
    {
      return std::get<1>(t.GetFunctions());
    }
  };

  template <class T>
  struct Simplification<Multiplication<T,Zero>>
  {
    typedef Zero type;
    static type Combine(Multiplication<T,Zero>)
    {
      return zero;
    }
  };

  template <class T>
  struct Simplification<Multiplication<Zero,T>,
		  typename std::enable_if<
		    !std::is_same<T,Zero>::value>::type>
  {
    typedef Zero type;

    static type Combine(Multiplication<Zero,T> )
    {
      return zero;
    }
  };
}

#endif
<|endoftext|>


<commit_before>/*
    Copyright (c) 2009-2011 250bpm s.r.o.
    Copyright (c) 2011 Botond Ballo
    Copyright (c) 2007-2009 iMatix Corporation

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

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

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

#ifndef __ZMQ_HPP_INCLUDED__
#define __ZMQ_HPP_INCLUDED__

#include <zmq.h>

#include <algorithm>
#include <cassert>
#include <cstring>
#include <exception>

//  Detect whether the compiler supports C++11 rvalue references.
#if (defined(__GNUC__) && (__GNUC__ > 4 || \
      (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \
      defined(__GXX_EXPERIMENTAL_CXX0X__))
    #define ZMQ_HAS_RVALUE_REFS
    #define ZMQ_DELETED_FUNCTION = delete
#elif defined(__clang__)
    #if __has_feature(cxx_rvalue_references)
        #define ZMQ_HAS_RVALUE_REFS
    #endif

    #if __has_feature(cxx_deleted_functions)
        #define ZMQ_DELETED_FUNCTION = delete
    #else
        #define ZMQ_DELETED_FUNCTION
    #endif
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
    #define ZMQ_HAS_RVALUE_REFS
    #define ZMQ_DELETED_FUNCTION
#else
    #define ZMQ_DELETED_FUNCTION
#endif

// In order to prevent unused variable warnings when building in non-debug
// mode use this macro to make assertions.
#ifndef NDEBUG
#   define ZMQ_ASSERT(expression) assert(expression)
#else
#   define ZMQ_ASSERT(expression) (void)(expression)
#endif

namespace zmq
{

    typedef zmq_free_fn free_fn;
    typedef zmq_pollitem_t pollitem_t;

    class error_t : public std::exception
    {
    public:

        error_t () : errnum (zmq_errno ()) {}

        virtual const char *what () const throw ()
        {
            return zmq_strerror (errnum);
        }

        int num () const
        {
            return errnum;
        }

    private:

        int errnum;
    };

    inline int poll (zmq_pollitem_t *items_, int nitems_, long timeout_ = -1)
    {
        int rc = zmq_poll (items_, nitems_, timeout_);
        if (rc < 0)
            throw error_t ();
        return rc;
    }

    inline void proxy (void *frontend, void *backend, void *capture)
    {
        int rc = zmq_proxy (frontend, backend, capture);
        if (rc != 0)
            throw error_t ();
    }

    inline void version (int *major_, int *minor_, int *patch_)
    {
        zmq_version (major_, minor_, patch_);
    }

    class message_t
    {
        friend class socket_t;

    public:

        inline message_t ()
        {
            int rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline explicit message_t (size_t size_)
        {
            int rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline message_t (message_t &&rhs) : msg (rhs.msg)
        {
            int rc = zmq_msg_init (&rhs.msg);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t &operator = (message_t &&rhs)
        {
            std::swap (msg, rhs.msg);
            return *this;
        }
#endif

        inline ~message_t ()
        {
            int rc = zmq_msg_close (&msg);
            ZMQ_ASSERT (rc == 0);
        }

        inline void rebuild ()
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (size_t size_)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

        inline void move (message_t *msg_)
        {
            int rc = zmq_msg_move (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void copy (message_t *msg_)
        {
            int rc = zmq_msg_copy (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void *data ()
        {
            return zmq_msg_data (&msg);
        }

        inline const void* data () const
        {
            return zmq_msg_data (const_cast<zmq_msg_t*>(&msg));
        }

        inline size_t size () const
        {
            return zmq_msg_size (const_cast<zmq_msg_t*>(&msg));
        }

    private:

        //  The underlying message
        zmq_msg_t msg;

        //  Disable implicit message copying, so that users won't use shared
        //  messages (less efficient) without being aware of the fact.
        message_t (const message_t&);
        void operator = (const message_t&);
    };

    class context_t
    {
        friend class socket_t;

    public:

        inline explicit context_t (int io_threads_)
        {
            ptr = zmq_init (io_threads_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline context_t (context_t &&rhs) : ptr (rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline context_t &operator = (context_t &&rhs)
        {
            std::swap (ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~context_t ()
        {
            close();
        }

        inline void close()
        {
            if (ptr == NULL)
                return;
            int rc = zmq_term (ptr);
            ZMQ_ASSERT (rc == 0);
            ptr = NULL;
        }

        //  Be careful with this, it's probably only useful for
        //  using the C api together with an existing C++ api.
        //  Normally you should never need to use this.
        inline operator void* ()
        {
            return ptr;
        }

    private:

        void *ptr;

        context_t (const context_t&);
        void operator = (const context_t&);
    };

    class socket_t
    {
		friend class monitor_t;
    public:

        inline socket_t (context_t &context_, int type_)
        {
            ctxptr = context_.ptr;
            ptr = zmq_socket (context_.ptr, type_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline socket_t(socket_t&& rhs) : ptr(rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline socket_t& operator=(socket_t&& rhs)
        {
            std::swap(ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~socket_t ()
        {
            close();
        }

        inline operator void* ()
        {
            return ptr;
        }

        inline void close()
        {
            if(ptr == NULL)
                // already closed
                return ;
            int rc = zmq_close (ptr);
            ZMQ_ASSERT (rc == 0);
            ptr = 0 ;
        }

        inline void setsockopt (int option_, const void *optval_,
            size_t optvallen_)
        {
            int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void getsockopt (int option_, void *optval_,
            size_t *optvallen_)
        {
            int rc = zmq_getsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void bind (const char *addr_)
        {
            int rc = zmq_bind (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline void unbind (const char *addr_)
        {
            int rc = zmq_unbind (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline void connect (const char *addr_)
        {
            int rc = zmq_connect (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline void disconnect (const char *addr_)
        {
            int rc = zmq_disconnect (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline bool connected()
        {
            return(ptr != NULL);
        }

        inline size_t send (const void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_send (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool send (message_t &msg_, int flags_ = 0)
        {
            int nbytes = zmq_msg_send (&(msg_.msg), ptr, flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

        inline size_t recv (void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_recv (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool recv (message_t *msg_, int flags_ = 0)
        {
            int nbytes = zmq_msg_recv (&(msg_->msg), ptr, flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

    private:
        void *ptr;
        void *ctxptr;

        socket_t (const socket_t&) ZMQ_DELETED_FUNCTION;
        void operator = (const socket_t&) ZMQ_DELETED_FUNCTION;
    };

	class monitor_t
	{
	public:
		virtual ~monitor_t() {}

		void monitor(socket_t& socket, const char *addr_, int events = ZMQ_EVENT_ALL)
		{
			int rc = zmq_socket_monitor(socket.ptr, addr_, events);
			if (rc != 0)
				throw error_t ();

			void *s = zmq_socket (socket.ctxptr, ZMQ_PAIR);
			assert (s);

			rc = zmq_connect (s, addr_);
			assert (rc == 0);
			while (true) {
				zmq_msg_t msg;
				zmq_msg_init (&msg);
				rc = zmq_recvmsg (s, &msg, 0);
				if (rc == -1 && zmq_errno() == ETERM)
					break;
				assert (rc != -1);

				zmq_event_t* event = static_cast<zmq_event_t*>(zmq_msg_data (&msg));

				switch (event->event) {
				case ZMQ_EVENT_CONNECTED:
					on_event_connected(event->data.connected.addr);
					break;
				case ZMQ_EVENT_CONNECT_DELAYED:
					on_event_connect_delayed(event->data.connect_delayed.addr);
					break;
				case ZMQ_EVENT_CONNECT_RETRIED:
					on_event_connect_retried(event->data.connect_retried.addr);
					break;
				case ZMQ_EVENT_LISTENING:
					on_event_listening(event->data.listening.addr);
					break;
				case ZMQ_EVENT_BIND_FAILED:
					on_event_bind_failed(event->data.bind_failed.addr);
					break;
				case ZMQ_EVENT_ACCEPTED:
					on_event_accepted(event->data.accepted.addr);
					break;
				case ZMQ_EVENT_ACCEPT_FAILED:
					on_event_accept_failed(event->data.accept_failed.addr);
					break;
				case ZMQ_EVENT_CLOSED:
					on_event_closed(event->data.closed.addr);
					break;
				case ZMQ_EVENT_CLOSE_FAILED:
					on_event_close_failed(event->data.close_failed.addr);
					break;
				case ZMQ_EVENT_DISCONNECTED:
					on_event_disconnected(event->data.disconnected.addr);
					break;
				default:
					on_event_unknown(event->event);
					break;
				}
				zmq_msg_close (&msg);
			}
			zmq_close (s);
		}

		virtual void on_event_connected(const char *addr_) {}
		virtual void on_event_connect_delayed(const char *addr_) {}
		virtual void on_event_connect_retried(const char *addr_) {}
		virtual void on_event_listening(const char *addr_) {}
		virtual void on_event_bind_failed(const char *addr_) {}
		virtual void on_event_accepted(const char *addr_) {}
		virtual void on_event_accept_failed(const char *addr_) {}
		virtual void on_event_closed(const char *addr_) {}
		virtual void on_event_close_failed(const char *addr_) {}
		virtual void on_event_disconnected(const char *addr_) {}
		virtual void on_event_unknown(int event) {}
	};
}

#endif
<commit_msg>Parse event structure as data for event handlers.<commit_after>/*
    Copyright (c) 2009-2011 250bpm s.r.o.
    Copyright (c) 2011 Botond Ballo
    Copyright (c) 2007-2009 iMatix Corporation

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

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

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

#ifndef __ZMQ_HPP_INCLUDED__
#define __ZMQ_HPP_INCLUDED__

#include <zmq.h>

#include <algorithm>
#include <cassert>
#include <cstring>
#include <exception>

//  Detect whether the compiler supports C++11 rvalue references.
#if (defined(__GNUC__) && (__GNUC__ > 4 || \
      (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \
      defined(__GXX_EXPERIMENTAL_CXX0X__))
    #define ZMQ_HAS_RVALUE_REFS
    #define ZMQ_DELETED_FUNCTION = delete
#elif defined(__clang__)
    #if __has_feature(cxx_rvalue_references)
        #define ZMQ_HAS_RVALUE_REFS
    #endif

    #if __has_feature(cxx_deleted_functions)
        #define ZMQ_DELETED_FUNCTION = delete
    #else
        #define ZMQ_DELETED_FUNCTION
    #endif
#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
    #define ZMQ_HAS_RVALUE_REFS
    #define ZMQ_DELETED_FUNCTION
#else
    #define ZMQ_DELETED_FUNCTION
#endif

// In order to prevent unused variable warnings when building in non-debug
// mode use this macro to make assertions.
#ifndef NDEBUG
#   define ZMQ_ASSERT(expression) assert(expression)
#else
#   define ZMQ_ASSERT(expression) (void)(expression)
#endif

namespace zmq
{

    typedef zmq_free_fn free_fn;
    typedef zmq_pollitem_t pollitem_t;

    class error_t : public std::exception
    {
    public:

        error_t () : errnum (zmq_errno ()) {}

        virtual const char *what () const throw ()
        {
            return zmq_strerror (errnum);
        }

        int num () const
        {
            return errnum;
        }

    private:

        int errnum;
    };

    inline int poll (zmq_pollitem_t *items_, int nitems_, long timeout_ = -1)
    {
        int rc = zmq_poll (items_, nitems_, timeout_);
        if (rc < 0)
            throw error_t ();
        return rc;
    }

    inline void proxy (void *frontend, void *backend, void *capture)
    {
        int rc = zmq_proxy (frontend, backend, capture);
        if (rc != 0)
            throw error_t ();
    }

    inline void version (int *major_, int *minor_, int *patch_)
    {
        zmq_version (major_, minor_, patch_);
    }

    class message_t
    {
        friend class socket_t;

    public:

        inline message_t ()
        {
            int rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline explicit message_t (size_t size_)
        {
            int rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline message_t (message_t &&rhs) : msg (rhs.msg)
        {
            int rc = zmq_msg_init (&rhs.msg);
            if (rc != 0)
                throw error_t ();
        }

        inline message_t &operator = (message_t &&rhs)
        {
            std::swap (msg, rhs.msg);
            return *this;
        }
#endif

        inline ~message_t ()
        {
            int rc = zmq_msg_close (&msg);
            ZMQ_ASSERT (rc == 0);
        }

        inline void rebuild ()
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init (&msg);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (size_t size_)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_size (&msg, size_);
            if (rc != 0)
                throw error_t ();
        }

        inline void rebuild (void *data_, size_t size_, free_fn *ffn_,
            void *hint_ = NULL)
        {
            int rc = zmq_msg_close (&msg);
            if (rc != 0)
                throw error_t ();
            rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_);
            if (rc != 0)
                throw error_t ();
        }

        inline void move (message_t *msg_)
        {
            int rc = zmq_msg_move (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void copy (message_t *msg_)
        {
            int rc = zmq_msg_copy (&msg, &(msg_->msg));
            if (rc != 0)
                throw error_t ();
        }

        inline void *data ()
        {
            return zmq_msg_data (&msg);
        }

        inline const void* data () const
        {
            return zmq_msg_data (const_cast<zmq_msg_t*>(&msg));
        }

        inline size_t size () const
        {
            return zmq_msg_size (const_cast<zmq_msg_t*>(&msg));
        }

    private:

        //  The underlying message
        zmq_msg_t msg;

        //  Disable implicit message copying, so that users won't use shared
        //  messages (less efficient) without being aware of the fact.
        message_t (const message_t&);
        void operator = (const message_t&);
    };

    class context_t
    {
        friend class socket_t;

    public:

        inline explicit context_t (int io_threads_)
        {
            ptr = zmq_init (io_threads_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline context_t (context_t &&rhs) : ptr (rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline context_t &operator = (context_t &&rhs)
        {
            std::swap (ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~context_t ()
        {
            close();
        }

        inline void close()
        {
            if (ptr == NULL)
                return;
            int rc = zmq_term (ptr);
            ZMQ_ASSERT (rc == 0);
            ptr = NULL;
        }

        //  Be careful with this, it's probably only useful for
        //  using the C api together with an existing C++ api.
        //  Normally you should never need to use this.
        inline operator void* ()
        {
            return ptr;
        }

    private:

        void *ptr;

        context_t (const context_t&);
        void operator = (const context_t&);
    };

    class socket_t
    {
		friend class monitor_t;
    public:

        inline socket_t (context_t &context_, int type_)
        {
            ctxptr = context_.ptr;
            ptr = zmq_socket (context_.ptr, type_);
            if (ptr == NULL)
                throw error_t ();
        }

#ifdef ZMQ_HAS_RVALUE_REFS
        inline socket_t(socket_t&& rhs) : ptr(rhs.ptr)
        {
            rhs.ptr = NULL;
        }
        inline socket_t& operator=(socket_t&& rhs)
        {
            std::swap(ptr, rhs.ptr);
            return *this;
        }
#endif

        inline ~socket_t ()
        {
            close();
        }

        inline operator void* ()
        {
            return ptr;
        }

        inline void close()
        {
            if(ptr == NULL)
                // already closed
                return ;
            int rc = zmq_close (ptr);
            ZMQ_ASSERT (rc == 0);
            ptr = 0 ;
        }

        inline void setsockopt (int option_, const void *optval_,
            size_t optvallen_)
        {
            int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void getsockopt (int option_, void *optval_,
            size_t *optvallen_)
        {
            int rc = zmq_getsockopt (ptr, option_, optval_, optvallen_);
            if (rc != 0)
                throw error_t ();
        }

        inline void bind (const char *addr_)
        {
            int rc = zmq_bind (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline void unbind (const char *addr_)
        {
            int rc = zmq_unbind (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline void connect (const char *addr_)
        {
            int rc = zmq_connect (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline void disconnect (const char *addr_)
        {
            int rc = zmq_disconnect (ptr, addr_);
            if (rc != 0)
                throw error_t ();
        }

        inline bool connected()
        {
            return(ptr != NULL);
        }

        inline size_t send (const void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_send (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool send (message_t &msg_, int flags_ = 0)
        {
            int nbytes = zmq_msg_send (&(msg_.msg), ptr, flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

        inline size_t recv (void *buf_, size_t len_, int flags_ = 0)
        {
            int nbytes = zmq_recv (ptr, buf_, len_, flags_);
            if (nbytes >= 0)
                return (size_t) nbytes;
            if (zmq_errno () == EAGAIN)
                return 0;
            throw error_t ();
        }

        inline bool recv (message_t *msg_, int flags_ = 0)
        {
            int nbytes = zmq_msg_recv (&(msg_->msg), ptr, flags_);
            if (nbytes >= 0)
                return true;
            if (zmq_errno () == EAGAIN)
                return false;
            throw error_t ();
        }

    private:
        void *ptr;
        void *ctxptr;

        socket_t (const socket_t&) ZMQ_DELETED_FUNCTION;
        void operator = (const socket_t&) ZMQ_DELETED_FUNCTION;
    };

	class monitor_t
	{
	public:
		virtual ~monitor_t() {}

		void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
		{
			int rc = zmq_socket_monitor(socket.ptr, addr_, events);
			if (rc != 0)
				throw error_t ();

			void *s = zmq_socket (socket.ctxptr, ZMQ_PAIR);
			assert (s);

			rc = zmq_connect (s, addr_);
			assert (rc == 0);
			while (true) {
				zmq_msg_t msg;
				zmq_msg_init (&msg);
				rc = zmq_recvmsg (s, &msg, 0);
				if (rc == -1 && zmq_errno() == ETERM)
					break;
				assert (rc != -1);

				zmq_event_t* event = static_cast<zmq_event_t*>(zmq_msg_data (&msg));

				switch (event->event) {
				case ZMQ_EVENT_CONNECTED:
					on_event_connected(*event);
					break;
				case ZMQ_EVENT_CONNECT_DELAYED:
					on_event_connect_delayed(*event);
					break;
				case ZMQ_EVENT_CONNECT_RETRIED:
					on_event_connect_retried(*event);
					break;
				case ZMQ_EVENT_LISTENING:
					on_event_listening(*event);
					break;
				case ZMQ_EVENT_BIND_FAILED:
					on_event_bind_failed(*event);
					break;
				case ZMQ_EVENT_ACCEPTED:
					on_event_accepted(*event);
					break;
				case ZMQ_EVENT_ACCEPT_FAILED:
					on_event_accept_failed(*event);
					break;
				case ZMQ_EVENT_CLOSED:
					on_event_closed(*event);
					break;
				case ZMQ_EVENT_CLOSE_FAILED:
					on_event_close_failed(*event);
					break;
				case ZMQ_EVENT_DISCONNECTED:
					on_event_disconnected(*event);
					break;
				default:
					on_event_unknown(*event);
					break;
				}
				zmq_msg_close (&msg);
			}
			zmq_close (s);
		}

		virtual void on_event_connected(const zmq_event_t &event_) {}
		virtual void on_event_connect_delayed(const zmq_event_t &event_) {}
		virtual void on_event_connect_retried(const zmq_event_t &event_) {}
		virtual void on_event_listening(const zmq_event_t &event_) {}
		virtual void on_event_bind_failed(const zmq_event_t &event_) {}
		virtual void on_event_accepted(const zmq_event_t &event_) {}
		virtual void on_event_accept_failed(const zmq_event_t &event_) {}
		virtual void on_event_closed(const zmq_event_t &event_) {}
		virtual void on_event_close_failed(const zmq_event_t &event_) {}
		virtual void on_event_disconnected(const zmq_event_t &event_) {}
		virtual void on_event_unknown(const zmq_event_t &event_) {}
	};
}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2015, Galaxy Authors. 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, sunjunyi01@baidu.com

#include <string>
#include <stdint.h>
#include <gflags/gflags.h>

DEFINE_string(master_port, "8101", "master rpc-server listen on this port");
DEFINE_string(agent_port, "8102", "agent rpc-server listen on this port");
DEFINE_int32(agent_http_port, 8089, "agent http-server listen on this port");
DEFINE_int32(agent_http_server_threads, 10, "agent http-server thread pool size");

DEFINE_string(master_addr, "localhost:" + FLAGS_master_port, "master rpc-server endpoint");
DEFINE_int32(task_retry_times, 3, "retry times of task ");
DEFINE_int32(task_deploy_timeout, 20, "task package deploy timeout");
DEFINE_int32(agent_keepalive_timeout, 20, "keepalive timeout of agent");

DEFINE_string(agent_work_dir, "/tmp", "agent work directory");
DEFINE_string(container, "cmd", "container type : cmd or cgroup");

DEFINE_string(cgroup_root, "/cgroups", "cgroup mount point");
DEFINE_int32(agent_curl_recv_buffer_size, 1024 * 10, "agent downloader recv buffer size");

DEFINE_double(cpu_num, 4, "cpu number");

DEFINE_int32(resource_collector_engine_interval, 1000, "rc collect engine interval");

DEFINE_int64(mem_gbytes, 32, "mem in giga bytes");
DEFINE_int64(mem_bytes, FLAGS_mem_gbytes * 1024 * 1024 * 1024, "mem in bytes");
// 5 hour
DEFINE_int32(agent_gc_timeout, 1000 * 60 * 60 * 5, "garbage collection timeout");

DEFINE_string(task_acct, "galaxy", "task user/role of system");

DEFINE_string(master_checkpoint_path, "./data/", "directory of master checkpoint data");
DEFINE_int32(master_max_len_sched_task_list, 30, "max length of scheduled tasks of a job");
DEFINE_int32(master_safe_mode_last, 30, "how many seconds the safe-mode goes on");
DEFINE_int32(agent_cgroup_clear_retry_times, 20, "how many times for retry destroy cgroup");
DEFINE_int32(agent_app_stop_wait_retry_times, 10, "how many times for stop wait");
DEFINE_string(monitor_conf_path, "", "path of monitor conf");

DEFINE_int32(agent_cgroup_clear_retry_times, 50, "how many times for retry destroy cgroup");
DEFINE_string(pam_pwd_dir, "/tmp/", "directory that stores galaxy-ssh passwords on agent node");

/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
<commit_msg>fix merge-conflict<commit_after>// Copyright (c) 2015, Galaxy Authors. 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, sunjunyi01@baidu.com

#include <string>
#include <stdint.h>
#include <gflags/gflags.h>

DEFINE_string(master_port, "8101", "master rpc-server listen on this port");
DEFINE_string(agent_port, "8102", "agent rpc-server listen on this port");
DEFINE_int32(agent_http_port, 8089, "agent http-server listen on this port");
DEFINE_int32(agent_http_server_threads, 10, "agent http-server thread pool size");

DEFINE_string(master_addr, "localhost:" + FLAGS_master_port, "master rpc-server endpoint");
DEFINE_int32(task_retry_times, 3, "retry times of task ");
DEFINE_int32(task_deploy_timeout, 20, "task package deploy timeout");
DEFINE_int32(agent_keepalive_timeout, 20, "keepalive timeout of agent");

DEFINE_string(agent_work_dir, "/tmp", "agent work directory");
DEFINE_string(container, "cmd", "container type : cmd or cgroup");

DEFINE_string(cgroup_root, "/cgroups", "cgroup mount point");
DEFINE_int32(agent_curl_recv_buffer_size, 1024 * 10, "agent downloader recv buffer size");

DEFINE_double(cpu_num, 4, "cpu number");

DEFINE_int32(resource_collector_engine_interval, 1000, "rc collect engine interval");

DEFINE_int64(mem_gbytes, 32, "mem in giga bytes");
DEFINE_int64(mem_bytes, FLAGS_mem_gbytes * 1024 * 1024 * 1024, "mem in bytes");
// 5 hour
DEFINE_int32(agent_gc_timeout, 1000 * 60 * 60 * 5, "garbage collection timeout");

DEFINE_string(task_acct, "galaxy", "task user/role of system");

DEFINE_string(master_checkpoint_path, "./data/", "directory of master checkpoint data");
DEFINE_int32(master_max_len_sched_task_list, 30, "max length of scheduled tasks of a job");
DEFINE_int32(master_safe_mode_last, 30, "how many seconds the safe-mode goes on");
DEFINE_int32(agent_cgroup_clear_retry_times, 20, "how many times for retry destroy cgroup");
DEFINE_int32(agent_app_stop_wait_retry_times, 10, "how many times for stop wait");
DEFINE_string(monitor_conf_path, "", "path of monitor conf");

DEFINE_string(pam_pwd_dir, "/tmp/", "directory that stores galaxy-ssh passwords on agent node");

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


<commit_before>
#include <form.h>
#include <taghelper.h>

Form::Form(Stanza stanza): type() {
	tag = stanza->find("command/x");
	if(tag == 0) {
		tag = new ATXmlTag("x");
		tag->setDefaultNameSpaceAttribute("jabber:x:data");
		tag->setAttribute("type", "submit"); // Считаем, что создаём форму на основе субмита от юзера
		return;
	}
	type = tag->getAttribute("type", "");
}

Form::Form(ATXmlTag *from): type() {
	tag = from;
	type = from->getAttribute("type", "");
}

Form::Form(std::string x_type): type() {
	tag = new ATXmlTag("x");
	tag->setDefaultNameSpaceAttribute("jabber:x:data");
	tag->setAttribute("type", x_type);
	type = x_type;
}

Form::~Form() {
	// Удалять ли tag, и если да, то при каких условиях?
	// TODO: разобраться после реализации ad-hoc
}

ATXmlTag *Form::asTag() {
	return tag;
}

void Form::setTitle(std::string form_title) {
	ATXmlTag *title = new ATXmlTag("title");
	title->insertCharacterData(form_title);
	tag->insertChildElement(title);
}

void Form::setInstructions(std::string form_instructions) {
	ATXmlTag *instructions = new ATXmlTag("instructions");
	instructions->insertCharacterData(form_instructions);
	tag->insertChildElement(instructions);
}

void Form::insertLineEdit(std::string var, std::string label, std::string value, bool required) {
	ATXmlTag *field = new ATXmlTag("field");
	field->setAttribute("type", "text-single");
	field->setAttribute("var", var);
	field->setAttribute("label", label);

	ATXmlTag *value_tag = new ATXmlTag("value");
	value_tag->insertCharacterData(value);
	field->insertChildElement(value_tag);

	if(required) {
		field->insertChildElement(new ATXmlTag("required"));
	}

	tag->insertChildElement(field);
}

void Form::insertTextEdit(std::string var, std::string label, std::string value, bool required) {
	ATXmlTag *field = new ATXmlTag("field");
	field->setAttribute("type", "text-multi");
	field->setAttribute("var", var);
	field->setAttribute("label", label);

	ATXmlTag *value_tag = new ATXmlTag("value");
	value_tag->insertCharacterData(value);
	field->insertChildElement(value_tag);

	if(required) {
		field->insertChildElement(new ATXmlTag("required"));
	}

	tag->insertChildElement(field);
}

std::string Form::getFieldValue(std::string field_name, std::string default_value) {
	// TODO
	ATXmlTag *field = tag->getChildByAttribute("field", "var", field_name);
	if(!field) {
		return std::string("");
	}
	if(!field->hasChild("value")) {
		return std::string("");
	}
	ATXmlTag *value = field->getChild("value");
	return value->getCharacterData();
}

// TODO: другие типы виджетов

<commit_msg>По мелочи: реализовал одну фишку, но забыл убрать TODO<commit_after>
#include <form.h>
#include <taghelper.h>

Form::Form(Stanza stanza): type() {
	tag = stanza->find("command/x");
	if(tag == 0) {
		tag = new ATXmlTag("x");
		tag->setDefaultNameSpaceAttribute("jabber:x:data");
		tag->setAttribute("type", "submit"); // Считаем, что создаём форму на основе субмита от юзера
		return;
	}
	type = tag->getAttribute("type", "");
}

Form::Form(ATXmlTag *from): type() {
	tag = from;
	type = from->getAttribute("type", "");
}

Form::Form(std::string x_type): type() {
	tag = new ATXmlTag("x");
	tag->setDefaultNameSpaceAttribute("jabber:x:data");
	tag->setAttribute("type", x_type);
	type = x_type;
}

Form::~Form() {
	// Удалять ли tag, и если да, то при каких условиях?
	// TODO: разобраться после реализации ad-hoc
}

ATXmlTag *Form::asTag() {
	return tag;
}

void Form::setTitle(std::string form_title) {
	ATXmlTag *title = new ATXmlTag("title");
	title->insertCharacterData(form_title);
	tag->insertChildElement(title);
}

void Form::setInstructions(std::string form_instructions) {
	ATXmlTag *instructions = new ATXmlTag("instructions");
	instructions->insertCharacterData(form_instructions);
	tag->insertChildElement(instructions);
}

void Form::insertLineEdit(std::string var, std::string label, std::string value, bool required) {
	ATXmlTag *field = new ATXmlTag("field");
	field->setAttribute("type", "text-single");
	field->setAttribute("var", var);
	field->setAttribute("label", label);

	ATXmlTag *value_tag = new ATXmlTag("value");
	value_tag->insertCharacterData(value);
	field->insertChildElement(value_tag);

	if(required) {
		field->insertChildElement(new ATXmlTag("required"));
	}

	tag->insertChildElement(field);
}

void Form::insertTextEdit(std::string var, std::string label, std::string value, bool required) {
	ATXmlTag *field = new ATXmlTag("field");
	field->setAttribute("type", "text-multi");
	field->setAttribute("var", var);
	field->setAttribute("label", label);

	ATXmlTag *value_tag = new ATXmlTag("value");
	value_tag->insertCharacterData(value);
	field->insertChildElement(value_tag);

	if(required) {
		field->insertChildElement(new ATXmlTag("required"));
	}

	tag->insertChildElement(field);
}

std::string Form::getFieldValue(std::string field_name, std::string default_value) {
	ATXmlTag *field = tag->getChildByAttribute("field", "var", field_name);
	if(!field) {
		return std::string("");
	}
	if(!field->hasChild("value")) {
		return std::string("");
	}
	ATXmlTag *value = field->getChild("value");
	return value->getCharacterData();
}

// TODO: другие типы виджетов

<|endoftext|>


<commit_before>#include <ncurses.h>

#include <string>
#include <random>

#include "game.h"
#include "InfoPanel.h"

using namespace std;

void menuShow(WINDOW *wnd, string title);
void startGame();

WINDOW *wmenu, *wmain;

InfoPanel *infoPanel = new InfoPanel();

struct {
    vec2i pos;
    rect bounds;
    char disp_char;
} player;

rect game_area;

int init() {

    initscr();

    /*
     * init main window
     */

    wmain = newwin(40, 80, 1, 1);
    box(wmain, 0, 0);

    /*
     * init menu window
     */

    wmenu = newwin(10, 12, 10, 10);
    wborder(wmenu,
            ACS_BULLET, ACS_BULLET, ACS_BULLET, ACS_BULLET,     /* ls, rs, ts, bs */
            '+', '+', '+', '+');                                /* tl, tr, bl, br */

    noecho();
    keypad(wmenu, true);
    curs_set(0);

    return 0;
}

void run() {
    char menuItems[2][10] = {
        "start",
        "quit"
    };
    char menuItem[7];
    int ch, i = 0, width = 7;

    /*
     * init title, menu
     */

    for (i = 0; i < 2; i++) {
        if (i == 0) wattron(wmenu, A_STANDOUT);
        else wattroff(wmenu, A_STANDOUT);

        sprintf(menuItem, "%-7s", menuItems[i]);
        mvwprintw(wmenu, i + 1, 2, "%s", menuItem);
    }

    wrefresh(wmain);
    wrefresh(wmenu);
    infoPanel->update();
    menuShow(wmain, "TERMINAL QUEST");
    i = 0;

    string infoPos, infoKey, infoMsg;
    bool exitRequested = false, gameRequested = false;
    while (( ch = wgetch(wmenu)) != 'q') {
        infoMsg = "";
        infoPos = to_string(ch);
        infoKey = to_string(i);

        sprintf(menuItem, "%-7s", menuItems[i]);
        mvwprintw(wmenu, i + 1, 2, "%s", menuItem);

        switch (ch) {
            case KEY_UP:
            case 'k':
                i--;
                i = (i < 0) ? 1 : i;
                infoMsg = "up";
                break;
            case KEY_DOWN:
            case 'j':
                i++;
                i = (i > 1) ? 0: i;
                infoMsg = "down";
                break;
            case KEY_ENTER: /* numpad enter */
            case '\n':      /* keyboard return */
                if (i == 1) exitRequested = true;
                else if (i == 0) gameRequested = true;
                break;

        }

        infoPanel->push((infoPos + ' ' + infoKey + ' ' + infoMsg));

        wattron(wmenu, A_STANDOUT);
        sprintf(menuItem, "%-7s", menuItems[i]);
        mvwprintw(wmenu, i + 1, 2, "%s", menuItem);
        wattroff(wmenu, A_STANDOUT);

        if (exitRequested == true) {
            break;
        } else if (gameRequested) {
            delwin(wmenu);
            delwin(wmain);

            startGame();
            break;
        }
    }

    /*
     * exit
     */

    endwin();

}

void close() {
    endwin();
}

void menuShow(WINDOW *wnd, string title) {

    wmove(wnd, 5, 5);

    for (size_t i = 0; i < title.size(); i++) {
        waddch(wnd, title[i]);
        waddch(wnd, ' ');
    }

    wrefresh(wnd);
}

void startGame() {

    game_area = {
        {0, 0},
        {80, 40}
    };

    WINDOW *wgame = newwin(40, 80, 1, 1);
    box(wgame, 0, 0);
    keypad(wgame, true);

    /*
     * Randomly place player anywhere in game area
     */
    random_device rd;
    uniform_int_distribution<int> distx(game_area.left(), game_area.right());
    uniform_int_distribution<int> disty(game_area.top(), game_area.bot());
    int randx = distx(rd) + 1;
    int randy = disty(rd) + 1;
    player.pos = {
        randx, randy
    };
    player.disp_char = '@';

    wmove(wgame, player.pos.y, player.pos.x);
    waddch(wgame, player.disp_char);

    int ch, i;
    string infoKey, infoMsg;
    vec2i infoPos;
    while (( ch = wgetch(wgame)) != 'q') {

        infoMsg = "";
        infoKey = to_string(ch);

        werase(wgame);
        box(wgame, 0, 0);

        switch (ch) {
            case KEY_UP:
            case 'k':
                if (player.pos.y > game_area.top() + 1) player.pos.y--;
                break;
            case KEY_DOWN:
            case 'j':
                if (player.pos.y < game_area.bot() - 2) player.pos.y++;
                break;
            case KEY_LEFT:
            case 'h':
                if (player.pos.x > game_area.left() + 1) player.pos.x--;
                break;
            case KEY_RIGHT:
            case 'l':
                if (player.pos.x < game_area.right() - 2) player.pos.x++;
                break;
            case KEY_ENTER: /* numpad enter */
            case '\n':      /* keyboard return */
                break;

        }

        wmove(wgame, player.pos.y, player.pos.x);
        waddch(wgame, player.disp_char);

        infoPanel->push('{'
            + std::to_string(player.pos.x) + ','
            + std::to_string(player.pos.y) + '}'
            + " - right & left: {"
            + std::to_string(game_area.right()) + ','
            + std::to_string(game_area.left()) + '}'
            + " top & bot: {"
            + std::to_string(game_area.top()) + ','
            + std::to_string(game_area.bot()) + '}'
        );

        wrefresh(wgame);

    }

    delwin(wgame);
}

<commit_msg>Add todo note re splitting up game<commit_after>#include <ncurses.h>

#include <string>
#include <random>

#include "game.h"
#include "InfoPanel.h"

using namespace std;

void menuShow(WINDOW *wnd, string title);
void startGame();

WINDOW *wmenu, *wmain;

InfoPanel *infoPanel = new InfoPanel();

struct {
    vec2i pos;
    rect bounds;
    char disp_char;
} player;

rect game_area;

int init() {

    initscr();

    /*
     * init main window
     */

    wmain = newwin(40, 80, 1, 1);
    box(wmain, 0, 0);

    /*
     * init menu window
     */

    wmenu = newwin(10, 12, 10, 10);
    wborder(wmenu,
            ACS_BULLET, ACS_BULLET, ACS_BULLET, ACS_BULLET,     /* ls, rs, ts, bs */
            '+', '+', '+', '+');                                /* tl, tr, bl, br */

    noecho();
    keypad(wmenu, true);
    curs_set(0);

    return 0;
}

void run() {
    char menuItems[2][10] = {
        "start",
        "quit"
    };
    char menuItem[7];
    int ch, i = 0, width = 7;

    /*
     * init title, menu
     */

    for (i = 0; i < 2; i++) {
        if (i == 0) wattron(wmenu, A_STANDOUT);
        else wattroff(wmenu, A_STANDOUT);

        sprintf(menuItem, "%-7s", menuItems[i]);
        mvwprintw(wmenu, i + 1, 2, "%s", menuItem);
    }

    wrefresh(wmain);
    wrefresh(wmenu);
    infoPanel->update();
    menuShow(wmain, "TERMINAL QUEST");
    i = 0;

    string infoPos, infoKey, infoMsg;
    bool exitRequested = false, gameRequested = false;
    while (( ch = wgetch(wmenu)) != 'q') {
        infoMsg = "";
        infoPos = to_string(ch);
        infoKey = to_string(i);

        sprintf(menuItem, "%-7s", menuItems[i]);
        mvwprintw(wmenu, i + 1, 2, "%s", menuItem);

        switch (ch) {
            case KEY_UP:
            case 'k':
                i--;
                i = (i < 0) ? 1 : i;
                infoMsg = "up";
                break;
            case KEY_DOWN:
            case 'j':
                i++;
                i = (i > 1) ? 0: i;
                infoMsg = "down";
                break;
            case KEY_ENTER: /* numpad enter */
            case '\n':      /* keyboard return */
                if (i == 1) exitRequested = true;
                else if (i == 0) gameRequested = true;
                break;

        }

        infoPanel->push((infoPos + ' ' + infoKey + ' ' + infoMsg));

        wattron(wmenu, A_STANDOUT);
        sprintf(menuItem, "%-7s", menuItems[i]);
        mvwprintw(wmenu, i + 1, 2, "%s", menuItem);
        wattroff(wmenu, A_STANDOUT);

        if (exitRequested == true) {
            break;
        } else if (gameRequested) {
            delwin(wmenu);
            delwin(wmain);

            startGame();
            break;
        }
    }

    /*
     * exit
     */

    endwin();

}

void close() {
    endwin();
}

void menuShow(WINDOW *wnd, string title) {

    wmove(wnd, 5, 5);

    for (size_t i = 0; i < title.size(); i++) {
        waddch(wnd, title[i]);
        waddch(wnd, ' ');
    }

    wrefresh(wnd);
}

/*
 * TODO
 *  Split off into own source file
 */
void startGame() {

    game_area = {
        {0, 0},
        {80, 40}
    };

    WINDOW *wgame = newwin(40, 80, 1, 1);
    box(wgame, 0, 0);
    keypad(wgame, true);

    /*
     * Randomly place player anywhere in game area
     */
    random_device rd;
    uniform_int_distribution<int> distx(game_area.left(), game_area.right());
    uniform_int_distribution<int> disty(game_area.top(), game_area.bot());
    int randx = distx(rd) + 1;
    int randy = disty(rd) + 1;
    player.pos = {
        randx, randy
    };
    player.disp_char = '@';

    wmove(wgame, player.pos.y, player.pos.x);
    waddch(wgame, player.disp_char);

    int ch, i;
    string infoKey, infoMsg;
    vec2i infoPos;
    while (( ch = wgetch(wgame)) != 'q') {

        infoMsg = "";
        infoKey = to_string(ch);

        werase(wgame);
        box(wgame, 0, 0);

        switch (ch) {
            case KEY_UP:
            case 'k':
                if (player.pos.y > game_area.top() + 1) player.pos.y--;
                break;
            case KEY_DOWN:
            case 'j':
                if (player.pos.y < game_area.bot() - 2) player.pos.y++;
                break;
            case KEY_LEFT:
            case 'h':
                if (player.pos.x > game_area.left() + 1) player.pos.x--;
                break;
            case KEY_RIGHT:
            case 'l':
                if (player.pos.x < game_area.right() - 2) player.pos.x++;
                break;
            case KEY_ENTER: /* numpad enter */
            case '\n':      /* keyboard return */
                break;

        }

        wmove(wgame, player.pos.y, player.pos.x);
        waddch(wgame, player.disp_char);

        infoPanel->push('{'
            + std::to_string(player.pos.x) + ','
            + std::to_string(player.pos.y) + '}'
            + " - right & left: {"
            + std::to_string(game_area.right()) + ','
            + std::to_string(game_area.left()) + '}'
            + " top & bot: {"
            + std::to_string(game_area.top()) + ','
            + std::to_string(game_area.bot()) + '}'
        );

        wrefresh(wgame);

    }

    delwin(wgame);
}

<|endoftext|>


<commit_before>#ifndef QUORIDOR_GAME_HPP_
#define QUORIDOR_GAME_HPP_

#include <map>
#include <memory>
#include <set>
#include <vector>

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>

#include "board_graph.hpp"
#include "node.hpp"
#include "pawn.hpp"
#include "walk_move.hpp"
#include "wall_grid.hpp"
#include "wall_move.hpp"

namespace Quoridor {

struct pawn_data_t {
    int idx;
    std::shared_ptr<Pawn> pawn;
    Node node;
    std::set<Node> goal_nodes;
};

typedef boost::multi_index_container<
    pawn_data_t,
    boost::multi_index::indexed_by<
        boost::multi_index::ordered_unique<boost::multi_index::member<pawn_data_t, int, &pawn_data_t::idx> >
    >
> pawn_data_list_t;

class Game {
public:
    explicit Game(int board_size);
    virtual ~Game();

    void set_pawns(std::vector<std::shared_ptr<Pawn>> &pawn_list);
    void switch_pawn();
    const pawn_data_t &cur_pawn_data() const;

    int move_pawn(const Node &node);
    int add_wall(const Wall &wall);

    bool is_finished() const;

private:
    int try_add_wall(const Wall &wall,
            std::vector<std::pair<Node, Node>> *edges);

private:
    int board_size_;
    pawn_data_list_t pawn_data_list_;
    int cur_pawn_idx_;
    BoardGraph bg_;
    WallGrid wg_;
};

}  // namespace Quoridor

#endif  // QUORIDOR_GAME_HPP_
<commit_msg>Add index by_pawn to pawn list<commit_after>#ifndef QUORIDOR_GAME_HPP_
#define QUORIDOR_GAME_HPP_

#include <map>
#include <memory>
#include <set>
#include <vector>

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/tag.hpp>

#include "board_graph.hpp"
#include "node.hpp"
#include "pawn.hpp"
#include "walk_move.hpp"
#include "wall_grid.hpp"
#include "wall_move.hpp"

namespace Quoridor {

struct pawn_data_t {
    int idx;
    std::shared_ptr<Pawn> pawn;
    Node node;
    std::set<Node> goal_nodes;
};

struct by_pawn {};

typedef boost::multi_index_container<
    pawn_data_t,
    boost::multi_index::indexed_by<
        boost::multi_index::ordered_unique<boost::multi_index::member<
            pawn_data_t, int, &pawn_data_t::idx>>,
        boost::multi_index::ordered_unique<
            boost::multi_index::tag<by_pawn>,
            boost::multi_index::member<
                pawn_data_t, std::shared_ptr<Pawn>, &pawn_data_t::pawn>>
    >
> pawn_data_list_t;

class Game {
public:
    explicit Game(int board_size);
    virtual ~Game();

    void set_pawns(std::vector<std::shared_ptr<Pawn>> &pawn_list);
    void switch_pawn();
    const pawn_data_t &cur_pawn_data() const;

    int move_pawn(const Node &node);
    int add_wall(const Wall &wall);

    bool is_finished() const;

private:
    int try_add_wall(const Wall &wall,
            std::vector<std::pair<Node, Node>> *edges);

private:
    int board_size_;
    pawn_data_list_t pawn_data_list_;
    int cur_pawn_idx_;
    BoardGraph bg_;
    WallGrid wg_;
};

}  // namespace Quoridor

#endif  // QUORIDOR_GAME_HPP_
<|endoftext|>


<commit_before>#ifndef __HELP_HPP__
#define __HELP_HPP__

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

//TODO make sure this doesn't get messed up if we run on a machine that doesn't
//have less installed
#define HELP_VIEWER "less"

/* !< \brief Class to create pageable help messages instead of print them to
 * stderr
 */

class Help_Pager {
private:
    FILE *help_fp;
    Help_Pager() {
        help_fp = popen(HELP_VIEWER, "w");
    }
    ~Help_Pager() {
        fclose(help_fp);
    }

public:
    static Help_Pager* instance() {
        static Help_Pager help;
        return &help;
    }
    int pagef(const char *format, ...) {
        va_list arg;
        va_start(arg, format);

        int res = vfprintf(help_fp, format, arg);
        va_end(arg);
        return res;
    }
};

#endif // __HELP_HPP__
<commit_msg>Improve help message interface.<commit_after>#ifndef __HELP_HPP__
#define __HELP_HPP__

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "errors.hpp"

//TODO make sure this doesn't get messed up if we run on a machine that doesn't
//have less installed
#define HELP_VIEWER "less"

/* !< \brief Class to create pageable help messages instead of print them to
 * stderr
 */

#define MAX_HELP_MSG_LEN (1024*1024)

class Help_Pager {
private:
    char msg[MAX_HELP_MSG_LEN];
    char *msg_hd;

    /* !< \brief the number of lines in the terminal
     */
    int term_lines() {
#ifdef TIOCGSIZE
        struct ttysize ts;
        ioctl(STDIN_FILENO, TIOCGSIZE, &ts);
        return ts.ts_lines;
#elif defined(TIOCGWINSZ)
        struct winsize ts;
        ioctl(STDIN_FILENO, TIOCGWINSZ, &ts);
        return ts.ws_row;
#endif /* TIOCGSIZE */
    }

    /* !< \brief The number of lines in the message
     */
    int msg_lines() {
        char *c = msg;
        int nlines = 0;

        while (c != msg_hd)
            if (*c++ == '\n') nlines++;

        return nlines;
    }

    Help_Pager() {
        msg[0] = '\0'; //in case someone tries to print an empty message
        msg_hd = msg;
    }

    ~Help_Pager() {
        FILE *print_to;
        if (msg_lines() > term_lines()) {
            print_to = popen(HELP_VIEWER, "w");
        } else {
            print_to = stderr;
        }

        msg_hd = '\0'; //Null terminate it;
        fprintf(print_to, "%s", msg);

        if (print_to != stderr)
            fclose(print_to);
    }

public:
    static Help_Pager* instance() {
        static Help_Pager help;
        return &help;
    }
    int pagef(const char *format, ...) {
        int res;
        va_list arg;
        va_start(arg, format);

        if (msg_hd < msg + MAX_HELP_MSG_LEN - 1)
            res = vsnprintf(msg_hd, (msg + MAX_HELP_MSG_LEN - 1) - msg_hd, format, arg);
        else
            unreachable("Help message is too big, increase MAX_HELP_MSG_LEN");

        msg_hd += res;
        va_end(arg);
        return res;
    }
};

#endif // __HELP_HPP__
<|endoftext|>


<commit_before>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file is part of the wikidata_cpp project:
 *     https://github.com/radupopescu/wikidata_cpp
 */

#include "data.h"

#include <rapidjson/Document.h>

#include <iostream>

namespace rj = rapidjson;

namespace data {

bool parseItem(const Languages& languages, const std::string& line, WikidataElement& elem)
{
  rj::Document j;
  j.Parse(line.substr(0, line.size() - 1).c_str());
  if (! j.HasParseError()) {
    if (j.HasMember("id")) {
      elem.id = j["id"].GetString();
      if (j.HasMember("sitelinks")) {
        const auto& s = j["sitelinks"].GetObject();
        for (const auto& l : languages) {
          const auto sitelink = l + "wiki";
          if (s.HasMember(sitelink.c_str())) {
            if (s[sitelink.c_str()].HasMember("title")) {
              elem.sites[l] = s[sitelink.c_str()]["title"].GetString();
            }
          }
        }
        return elem.sites.size() == languages.size();
      }
    }
  }

  return false;
}

}
<commit_msg>Fix typo in include due to case insensitivity<commit_after>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file is part of the wikidata_cpp project:
 *     https://github.com/radupopescu/wikidata_cpp
 */

#include "data.h"

#include <rapidjson/document.h>

#include <iostream>

namespace rj = rapidjson;

namespace data {

bool parseItem(const Languages& languages, const std::string& line, WikidataElement& elem)
{
  rj::Document j;
  j.Parse(line.substr(0, line.size() - 1).c_str());
  if (! j.HasParseError()) {
    if (j.HasMember("id")) {
      elem.id = j["id"].GetString();
      if (j.HasMember("sitelinks")) {
        const auto& s = j["sitelinks"].GetObject();
        for (const auto& l : languages) {
          const auto sitelink = l + "wiki";
          if (s.HasMember(sitelink.c_str())) {
            if (s[sitelink.c_str()].HasMember("title")) {
              elem.sites[l] = s[sitelink.c_str()]["title"].GetString();
            }
          }
        }
        return elem.sites.size() == languages.size();
      }
    }
  }

  return false;
}

}
<|endoftext|>


<commit_before>#include "yaml-cpp/node/emit.h"
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "nodeevents.h"

namespace YAML
{
	Emitter& operator << (Emitter& out, const Node& node)
	{
		EmitFromEvents emitFromEvents(out);
		NodeEvents events(node);
		events.Emit(emitFromEvents);
		return out;
	}

	std::ostream& operator << (std::ostream& out, const Node& node)
	{
		Emitter emitter;
		emitter << node;
		out << emitter.c_str();
		return out;
	}

	std::string Dump(const Node& node)
	{
		Emitter emitter;
		emitter << node;
		return emitter.c_str();
	}
}
<commit_msg>Updated the ostream emitting overload to user the new ostream-handling emitters<commit_after>#include "yaml-cpp/node/emit.h"
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "nodeevents.h"

namespace YAML
{
	Emitter& operator << (Emitter& out, const Node& node)
	{
		EmitFromEvents emitFromEvents(out);
		NodeEvents events(node);
		events.Emit(emitFromEvents);
		return out;
	}

	std::ostream& operator << (std::ostream& out, const Node& node)
	{
		Emitter emitter(out);
		emitter << node;
		return out;
	}

	std::string Dump(const Node& node)
	{
		Emitter emitter;
		emitter << node;
		return emitter.c_str();
	}
}
<|endoftext|>


<commit_before>#include "draw.hpp"

#include <algorithm>
#include <iostream>
#include <sstream>

#include "args.hpp"
#include "config.hpp"
#include "task.hpp"
#include "todolist.hpp"
#include "typer.hpp"
#include "win.hpp"

using std::string;
using std::stringstream;

// ===================|
// internal functions |
// ===================|
std::string buildTitle(TodoList *list);

void drawTitle(TodoList* list);
void drawControls();
void drawTasks(TodoList* list, unsigned selected);
void drawDivider(string div, int ypos);

// ===================|
// internal variables |
// ===================|
Win *titleWin;
Win *taskWin;
Win *controlWin;
Win* inputWin;

int startX;
int startY;
int width;
int height;

unsigned xpos;
unsigned ypos;
unsigned startTask = 0;
unsigned endTask = 0;
unsigned int listOff = 0;

bool colors = false;

/////////////////////////////////////////
// start curses mode and create windows
void Draw::init()
{
    std::cout << "\033]0;" << "todo" << "\7" << std::flush;
    initscr();
    raw();

    use_default_colors();
    if (useColors() && has_colors()){
        start_color();
        init_pair(TITLE_COLOR_PAIR, TITLE_FOREGROUND, TITLE_BACKGROUND);
        init_pair(GUTTER_COLOR_PAIR, GUTTER_FOREGROUND, GUTTER_BACKGROUND);
        init_pair(SELECT_COLOR_PAIR, SELECT_FOREGROUND, SELECT_BACKGROUND);
        init_pair(BORDER_COLOR_PAIR, BORDER_FOREGROUND, BORDER_BACKGROUND);
        init_pair(MARK_COLOR_PAIR, MARK_FOREGROUND, MARK_BACKGROUND);
        init_pair(MARK_COLOR_PAIR_DONE, MARK_FOREGROUND_DONE,
                  MARK_BACKGROUND_DONE);
        colors = true;
    }
    Win::setColors(colors);

    mouseinterval(0);
    keypad(stdscr, true);
    noecho();

    clear();
    refresh();

    curs_set(0);

    startX = listStartX;
    startY = listStartY;
    width = COLS - startX - 2;
    height = LINES * listHeight;

    int inHeight = inputHeight * LINES;
    inHeight = std::max(inHeight, 4);

    titleWin = new Win(0, 0, COLS, titleHeight, "title", false);
    taskWin = new Win(startX, startY, width, height, "tasks");
    controlWin = new Win(inputStartX, inputStartY, COLS - inputStartX - 2,
                         inHeight, "controls");
    inputWin = new Win(inputStartX, inputStartY, COLS - inputStartX - 2,
                         inHeight, "new task");
}

//////////////////////
// main draw function
void Draw::draw(TodoList *list, unsigned selected)
{
    drawTitle(list);
    drawControls();
    drawTasks(list, selected);
}

////////////////////////
// act on mouse events
void Draw::mouse(MEVENT event, TodoList *list,
                 unsigned &selected, bool button)
{
    int x = event.x;
    int y = event.y;
    if (taskWin->mouse(x, y)){
        unsigned pos = listOff + y - 1;
        if (pos < list->size()){
            list->adjustPos(pos, listOff);
            if (!button){
                selected = pos;
            } else{
                list->at(pos).toggleComplete();
            }
        }
    }
}

///////////////////////////////////////
// get an input string for a new task
string Draw::getInput(string str)
{
    return type(inputWin, 128, str);
}

////////////////////
//  draw the title
void drawTitle(TodoList* list)
{
    titleWin->clear();
    titleWin->inverse();
    titleWin->color(TITLE_COLOR_PAIR);
    titleWin->print(buildTitle(list), 0, 0);
    titleWin->colorOff(TITLE_COLOR_PAIR);
    titleWin->inverseOff();
    titleWin->color(BORDER_COLOR_PAIR, true);
    titleWin->draw();
}

// draw the control panel
void drawControls()
{
    controlWin->clear();
    stringstream line;

    controlWin->move(0, 0);
    line << "[" << ((char) EXIT_KEY) << "] quit          ";
    line << "[Space] new task          ";
    line << "[" << ((char) MOVE_UP_KEY) << "] move task up  ";
    controlWin->print(line.str());
    line.str("");

    controlWin->move(0, 1);
    line << "[" << ((char) REMOVE_KEY) << "] delete task   ";
    line << "[Return] mark task done   ";
    line << "[" << ((char) MOVE_DOWN_KEY) << "] move task down  ";
    controlWin->print(line.str());
    line.str("");

    controlWin->color(BORDER_COLOR_PAIR, true);
    controlWin->draw();
}

void drawTasks(TodoList* list, unsigned selected)
{
    auto tasks = list->tasks();

    taskWin->clear();

    if (tasks && tasks->size()){
        xpos = 1;
        ypos = 1;

        unsigned numTasks = height - 2;
        endTask = tasks->size();
        if (endTask > numTasks)
            endTask = numTasks;

        for (unsigned i = startTask + listOff; i < endTask + listOff &&
                                                 i < tasks->size(); i++){
            if (tasks->at(i).div())
                endTask--;
        }

        if (numTasks <= tasks->size()){
            while (selected > endTask + listOff - 2 && selected != 0)
                listOff++;
            while (selected < startTask + listOff &&
                   selected != list->size() - 1)
                listOff--;
        } else{
            listOff = 0;
        }

        unsigned count = startTask + listOff;

        for (unsigned i = startTask + listOff; i < endTask + listOff &&
                                               i < tasks->size() ; i++){
            Task t = tasks->at(i);

            if (showNumbers){
                taskWin->inverse();
                taskWin->color(GUTTER_COLOR_PAIR);

                std::string number = std::to_string(count);
                if (!zeroIndexNumbers)
                    number = std::to_string(count + 1);
                while (number.size() < 2)
                    number = "0"+number;

                taskWin->print(number + ")", xpos, ypos);
                taskWin->colorOff(GUTTER_COLOR_PAIR);
                taskWin->inverseOff();
                xpos += 5;
            }

            if (i == selected){
                std::string tmp = tasks->at(i).task();
                if (tasks->at(i).div()){
                    taskWin->inverse();
                    taskWin->color(SELECT_COLOR_PAIR);
                    drawDivider(tmp.substr(5, tmp.size() - 5), ypos);
                    taskWin->colorOff(SELECT_COLOR_PAIR);
                    taskWin->inverseOff();
                    ypos+=2;
                    if (showNumbers){
                        xpos -= 5;
                    }
                    continue;
                }
                std::string line = tmp;
                if (highlightWholeLine){
                    for (int k = tmp.size() + xpos; k < width - 2; k++){
                        line += " ";
                    }
                }

                std::string mark = line.substr(0, STRING_COMPLETE.size());
                line = line.substr(mark.size());

                taskWin->inverse();

                taskWin->color(!t.completed() ? MARK_COLOR_PAIR
                                              : MARK_COLOR_PAIR_DONE);
                taskWin->print(mark, xpos, ypos);
                taskWin->colorOff(!t.completed() ? MARK_COLOR_PAIR
                                                 : MARK_COLOR_PAIR_DONE);

                taskWin->color(SELECT_COLOR_PAIR);
                taskWin->print(line, xpos + mark.size(), ypos);
                taskWin->colorOff(SELECT_COLOR_PAIR);

                taskWin->inverseOff();
            } else{
                std::string tmp = tasks->at(i).task();
                if (tasks->at(i).div()){
                    drawDivider(tmp.substr(5, tmp.size() - 5), ypos);
                    ypos+= 2;
                    if (showNumbers){
                        xpos -= 5;
                    }
                    continue;
                }

                std::string text = tmp;
                std::string mark = text.substr(0, STRING_COMPLETE.size());
                text = text.substr(mark.size());

                taskWin->color(!t.completed() ? MARK_COLOR_PAIR
                                              : MARK_COLOR_PAIR_DONE);
                taskWin->print(mark, xpos, ypos);
                taskWin->colorOff(!t.completed() ? MARK_COLOR_PAIR
                                                 : MARK_COLOR_PAIR_DONE);

                taskWin->print(text, xpos + mark.size(), ypos);
            }
            ypos++;
            if (ypos > numTasks || i >= tasks->size() - 1){
                break;
            }
            if (showNumbers){
                xpos -= 5;
                count++;
            }
        }
    }

    taskWin->color(BORDER_COLOR_PAIR, true);
    taskWin->draw();
}

///////////////////////////////////
// stop curses and delete windows
void Draw::stop()
{
    delete titleWin;
    delete taskWin;
    delete controlWin;
    delete inputWin;

    endwin();

    curs_set(1);
}

// create the title string
std::string buildTitle(TodoList *list)
{
    std::string title = "[todo version "+vn+"]";

    unsigned cent = (COLS - list->name.size() - 2) / 2;

    for (unsigned i = title.size(); i < cent; i++){
        title += division;
    }

    title += "[";
    title += list->name;
    title += "]";

    std::string stats = "[" + list->completedStr() + "]";

    for (unsigned i = title.size() + stats.size(); i < (unsigned)COLS; i++){
        title += division;
    }

    title += stats;
    return title;
}

void drawDivider(string div, int ypos)
{
    while ((int) div.size() < width - 3){
        div += division;
    }
    taskWin->print(div, 1, ypos);
}

<commit_msg>tried to fix scrolling with dividers<commit_after>#include "draw.hpp"

#include <algorithm>
#include <iostream>
#include <sstream>

#include "args.hpp"
#include "config.hpp"
#include "task.hpp"
#include "todolist.hpp"
#include "typer.hpp"
#include "win.hpp"

using std::string;
using std::stringstream;

// ===================|
// internal functions |
// ===================|
std::string buildTitle(TodoList *list);

void drawTitle(TodoList* list);
void drawControls();
void drawTasks(TodoList* list, unsigned selected);
void drawDivider(string div, int ypos);

// ===================|
// internal variables |
// ===================|
Win *titleWin;
Win *taskWin;
Win *controlWin;
Win* inputWin;

int startX;
int startY;
int width;
int height;

unsigned xpos;
unsigned ypos;
unsigned startTask = 0;
unsigned endTask = 0;
unsigned int listOff = 0;

bool colors = false;

/////////////////////////////////////////
// start curses mode and create windows
void Draw::init()
{
    std::cout << "\033]0;" << "todo" << "\7" << std::flush;
    initscr();
    raw();

    use_default_colors();
    if (useColors() && has_colors()){
        start_color();
        init_pair(TITLE_COLOR_PAIR, TITLE_FOREGROUND, TITLE_BACKGROUND);
        init_pair(GUTTER_COLOR_PAIR, GUTTER_FOREGROUND, GUTTER_BACKGROUND);
        init_pair(SELECT_COLOR_PAIR, SELECT_FOREGROUND, SELECT_BACKGROUND);
        init_pair(BORDER_COLOR_PAIR, BORDER_FOREGROUND, BORDER_BACKGROUND);
        init_pair(MARK_COLOR_PAIR, MARK_FOREGROUND, MARK_BACKGROUND);
        init_pair(MARK_COLOR_PAIR_DONE, MARK_FOREGROUND_DONE,
                  MARK_BACKGROUND_DONE);
        colors = true;
    }
    Win::setColors(colors);

    mouseinterval(0);
    keypad(stdscr, true);
    noecho();

    clear();
    refresh();

    curs_set(0);

    startX = listStartX;
    startY = listStartY;
    width = COLS - startX - 2;
    height = LINES * listHeight;

    int inHeight = inputHeight * LINES;
    inHeight = std::max(inHeight, 4);

    titleWin = new Win(0, 0, COLS, titleHeight, "title", false);
    taskWin = new Win(startX, startY, width, height, "tasks");
    controlWin = new Win(inputStartX, inputStartY, COLS - inputStartX - 2,
                         inHeight, "controls");
    inputWin = new Win(inputStartX, inputStartY, COLS - inputStartX - 2,
                         inHeight, "new task");
}

//////////////////////
// main draw function
void Draw::draw(TodoList *list, unsigned selected)
{
    drawTitle(list);
    drawControls();
    drawTasks(list, selected);
}

////////////////////////
// act on mouse events
void Draw::mouse(MEVENT event, TodoList *list,
                 unsigned &selected, bool button)
{
    int x = event.x;
    int y = event.y;
    if (taskWin->mouse(x, y)){
        unsigned pos = listOff + y - 1;
        if (pos < list->size()){
            list->adjustPos(pos, listOff);
            if (!button){
                selected = pos;
            } else{
                list->at(pos).toggleComplete();
            }
        }
    }
}

///////////////////////////////////////
// get an input string for a new task
string Draw::getInput(string str)
{
    return type(inputWin, 128, str);
}

////////////////////
//  draw the title
void drawTitle(TodoList* list)
{
    titleWin->clear();
    titleWin->inverse();
    titleWin->color(TITLE_COLOR_PAIR);
    titleWin->print(buildTitle(list), 0, 0);
    titleWin->colorOff(TITLE_COLOR_PAIR);
    titleWin->inverseOff();
    titleWin->color(BORDER_COLOR_PAIR, true);
    titleWin->draw();
}

// draw the control panel
void drawControls()
{
    controlWin->clear();
    stringstream line;

    controlWin->move(0, 0);
    line << "[" << ((char) EXIT_KEY) << "] quit          ";
    line << "[Space] new task          ";
    line << "[" << ((char) MOVE_UP_KEY) << "] move task up  ";
    controlWin->print(line.str());
    line.str("");

    controlWin->move(0, 1);
    line << "[" << ((char) REMOVE_KEY) << "] delete task   ";
    line << "[Return] mark task done   ";
    line << "[" << ((char) MOVE_DOWN_KEY) << "] move task down  ";
    controlWin->print(line.str());
    line.str("");

    controlWin->color(BORDER_COLOR_PAIR, true);
    controlWin->draw();
}

void drawTasks(TodoList* list, unsigned selected)
{
    auto tasks = list->tasks();

    taskWin->clear();

    if (tasks && tasks->size()){
        xpos = 1;
        ypos = 1;

        unsigned numTasks = height - 2;
        endTask = tasks->size();
        if (endTask > numTasks)
            endTask = numTasks;

        for (unsigned i = startTask + listOff; i < endTask + listOff &&
                                                 i < tasks->size(); i++){
            if (tasks->at(i).div())
                endTask--;
        }

        if (numTasks <= tasks->size()){
            while (selected > endTask + listOff - 2 && selected != 0)
                listOff++;
            while (selected < startTask + listOff &&
                   selected != list->size() - 1)
                listOff--;
        } else{
            listOff = 0;
        }

        unsigned count = startTask + listOff;

        if (startTask + listOff != 0){
            if (tasks->at(startTask + listOff - 1).div()){
                ypos++;
                endTask++;
            }
        }

        for (unsigned i = startTask + listOff; i < endTask + listOff &&
                                               i < tasks->size() ; i++){
            Task t = tasks->at(i);

            if (showNumbers){
                taskWin->inverse();
                taskWin->color(GUTTER_COLOR_PAIR);

                std::string number = std::to_string(count);
                if (!zeroIndexNumbers)
                    number = std::to_string(count + 1);
                while (number.size() < 2)
                    number = "0"+number;

                taskWin->print(number + ")", xpos, ypos);
                taskWin->colorOff(GUTTER_COLOR_PAIR);
                taskWin->inverseOff();
                xpos += 5;
            }

            if (i == selected){
                std::string tmp = tasks->at(i).task();
                if (tasks->at(i).div()){
                    taskWin->inverse();
                    taskWin->color(SELECT_COLOR_PAIR);
                    drawDivider(tmp.substr(5, tmp.size() - 5), ypos);
                    taskWin->colorOff(SELECT_COLOR_PAIR);
                    taskWin->inverseOff();
                    ypos+=2;
                    if (showNumbers){
                        xpos -= 5;
                    }
                    continue;
                }
                std::string line = tmp;
                if (highlightWholeLine){
                    for (int k = tmp.size() + xpos; k < width - 2; k++){
                        line += " ";
                    }
                }

                std::string mark = line.substr(0, STRING_COMPLETE.size());
                line = line.substr(mark.size());

                taskWin->inverse();

                taskWin->color(!t.completed() ? MARK_COLOR_PAIR
                                              : MARK_COLOR_PAIR_DONE);
                taskWin->print(mark, xpos, ypos);
                taskWin->colorOff(!t.completed() ? MARK_COLOR_PAIR
                                                 : MARK_COLOR_PAIR_DONE);

                taskWin->color(SELECT_COLOR_PAIR);
                taskWin->print(line, xpos + mark.size(), ypos);
                taskWin->colorOff(SELECT_COLOR_PAIR);

                taskWin->inverseOff();
            } else{
                std::string tmp = tasks->at(i).task();
                if (tasks->at(i).div()){
                    drawDivider(tmp.substr(5, tmp.size() - 5), ypos);
                    ypos+= 2;
                    if (showNumbers){
                        xpos -= 5;
                    }
                    continue;
                }

                std::string text = tmp;
                std::string mark = text.substr(0, STRING_COMPLETE.size());
                text = text.substr(mark.size());

                taskWin->color(!t.completed() ? MARK_COLOR_PAIR
                                              : MARK_COLOR_PAIR_DONE);
                taskWin->print(mark, xpos, ypos);
                taskWin->colorOff(!t.completed() ? MARK_COLOR_PAIR
                                                 : MARK_COLOR_PAIR_DONE);

                taskWin->print(text, xpos + mark.size(), ypos);
            }
            ypos++;
            if (ypos > numTasks || i >= tasks->size() - 1){
                break;
            }
            if (showNumbers){
                xpos -= 5;
                count++;
            }
        }
    }

    taskWin->color(BORDER_COLOR_PAIR, true);
    taskWin->draw();
}

///////////////////////////////////
// stop curses and delete windows
void Draw::stop()
{
    delete titleWin;
    delete taskWin;
    delete controlWin;
    delete inputWin;

    endwin();

    curs_set(1);
}

// create the title string
std::string buildTitle(TodoList *list)
{
    std::string title = "[todo version "+vn+"]";

    unsigned cent = (COLS - list->name.size() - 2) / 2;

    for (unsigned i = title.size(); i < cent; i++){
        title += division;
    }

    title += "[";
    title += list->name;
    title += "]";

    std::string stats = "[" + list->completedStr() + "]";

    for (unsigned i = title.size() + stats.size(); i < (unsigned)COLS; i++){
        title += division;
    }

    title += stats;
    return title;
}

void drawDivider(string div, int ypos)
{
    while ((int) div.size() < width - 3){
        div += division;
    }
    taskWin->print(div, 1, ypos);
}

<|endoftext|>