/*
 * 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 zmqpp.
 * Copyright (c) 2011-2015 Contributors as noted in the AUTHORS file.
 */

/**
 * \file
 *
 * \date   10 Sep 2011
 * \author ron
 * \author Ben Gray (\@benjamg)
 *
 * A fair number of C++0x (or more accurately C++11) features are used in this
 * library and as this project is used where I work on older compilers this
 * file was created to help.
 *
 * C++ features and their workaround where not supported:
 * \li lambda functions - disabled, these are only used in the test anyway.
 * \li typesafe enums   - replaced with enum where comparisons needed.
 * \li nullptr          - defined to null.
 *
 * As of the port to version 3.1 (libzmqpp version 1.1.0) this file will also
 * be used to maintain compatablity with multiple versions of 0mq
 */

#ifndef ZMQPP_COMPATIBILITY_HPP_
#define ZMQPP_COMPATIBILITY_HPP_

#include <zmq.h>

// Include export file if on windows, generated by cmake only
#if _WIN32
	#include "zmqpp_export.h"
#else
	#define ZMQPP_EXPORT
#endif

// Currently we require at least 0mq version 2.2.x
#define ZMQPP_REQUIRED_ZMQ_MAJOR 2
#define ZMQPP_REQUIRED_ZMQ_MINOR 2

#if (ZMQ_VERSION_MAJOR < ZMQPP_REQUIRED_ZMQ_MAJOR) || ((ZMQ_VERSION_MAJOR == ZMQPP_REQUIRED_ZMQ_MAJOR) && (ZMQ_VERSION_MINOR < ZMQPP_REQUIRED_ZMQ_MINOR))
#error zmqpp requires a later version of 0mq
#endif

// Experimental feature support
#if (ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR == 0)
#define ZMQ_EXPERIMENTAL_LABELS
#endif

// Deal with older versions of gcc
#if defined(__GNUC__) && !defined(__clang__)
#if __GNUC__ == 4

// Deal with older gcc not supporting C++0x typesafe enum class name {} comparison
#if __GNUC_MINOR__ < 4
#define ZMQPP_COMPARABLE_ENUM enum
#endif

#if __GNUC_MINOR__ == 4
#if __GNUC_PATCHLEVEL__ < 1
#undef ZMQPP_COMPARABLE_ENUM
#define ZMQPP_COMPARABLE_ENUM enum
#endif // if __GNUC_PATCHLEVEL__ < 1
#endif // if __GNUC_MINOR__ == 4

// Deal with older gcc not supporting C++0x lambda function
#if __GNUC_MINOR__ < 5
#define ZMQPP_IGNORE_LAMBDA_FUNCTION_TESTS
#define ZMQPP_EXPLICITLY_DELETED
#endif // if __GNUC_MINOR__ < 5

// Deal with older gcc not supporting C++0x nullptr
#if __GNUC_MINOR__ < 6
#define nullptr NULL
#define NOEXCEPT
#endif // if __GNUC_MINOR__ < 6

#endif // if __GNUC_ == 4
#endif // if defined(__GNUC__) && !defined(__clang__)

#if defined(_MSC_VER)
#define NOEXCEPT throw()
#if _MSC_VER < 1900
#	define ZMQPP_NO_CONSTEXPR
#endif
#if _MSC_VER < 1800
#define ZMQPP_EXPLICITLY_DELETED
#endif // if _MSC_VER < 1800
#if _MSC_VER < 1600
#define nullptr NULL
#define ZMQPP_IGNORE_LAMBDA_FUNCTION_TESTS
#define ZMQPP_COMPARABLE_ENUM enum
#endif // if _MSC_VER < 1600
#endif // if defined(_MSC_VER)

// Generic state, assume a modern compiler
#ifndef ZMQPP_COMPARABLE_ENUM
#define ZMQPP_COMPARABLE_ENUM enum class
#endif

#ifndef ZMQPP_EXPLICITLY_DELETED
#define ZMQPP_EXPLICITLY_DELETED = delete
#endif

#if __cplusplus >= 201300  // c++14 version. This number worked
                           // on g++ 4.9 when compiling with -std=c++14
#define ZMQPP_DEPRECATED(reason) [[deprecated(#reason)]]
#elif __GNUC__
#define ZMQPP_DEPRECATED(reason) __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define ZMQPP_DEPRECATED(reason) __declspec(deprecated(#reason))
#else
#define ZMQPP_DEPRECATED(reason)
#endif

#ifndef NOEXCEPT
#define NOEXCEPT noexcept
#endif

// There are a couple of methods that take a raw socket in form of a 'file descriptor'. Under POSIX
// this is simply an int. But under Windows this type must be a SOCKET. In order to hide this 
// platform detail we create a raw_socket_t which is a SOCKET under Windows and an int on all the
// other platforms. This is practically the same as libzmq does with its zmq_pollitem_t struct.
namespace zmqpp
{
#ifdef _WIN32
	typedef SOCKET raw_socket_t;
#else
	typedef int raw_socket_t;
#endif
}

#endif /* ZMQPP_COMPATIBILITY_HPP_ */