/*
 * This file is part of libtqtvd_astronav
 *
 * Copyright (C) 2008-2017 TQTVD Software
 * Copyright (C) 2017 Mirakulo Software (mirakulo@mirakulo.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#ifndef TQTVD_COMMON_INC
#define TQTVD_COMMON_INC

#include "utf8_util.h"

//=================================================================
// External includes
//=================================================================

//std, system

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>

#ifdef __cplusplus

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <string>

//stl
#include <deque>
#include <list>
#include <map>
#include <set>

//Boost
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/scoped_ptr.hpp>

#endif

// Pthread
#include <pthread.h>
#include <sys/types.h>      /* gettid() */

#ifdef __cplusplus

namespace boost {

template <typename T>
  boost::shared_ptr<T> ptr_base(boost::shared_ptr<T> p) { return p; }

}

#endif

// Have the compiler spit out warnings for todo messages
#define DO_PRAGMA(x) _Pragma (#x)
#define TODO(x) DO_PRAGMA(message ("TODO - " #x))


/**
 *  This tells a C++ compiler that a function has C linkage.
 */
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif

#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#elif defined(__LCLINT__)
# define UNUSED(x) /*@unused@*/ x
#else
# define UNUSED(x) x
#endif

#ifdef __FreeBSD__
#define fflush_unlocked(x) 
#endif


#ifdef NDEBUG

#define TQDEBUG_DEBUG(format, args...)
#define TQDEBUG_DEBUGF(format, args...)

#define TQDEBUG_ERROR(format, args...)
#define TQDEBUG_ERRORF(format, args...)


#define TQDEBUG_FUNC_IN


#else

#define TQDEBUG_DEBUG(format, args...) fprintf(stderr, "%s:%d [%s] " format "\n", basename(__FILE__), __LINE__, __FUNCTION__, args)
#define TQDEBUG_DEBUGF(format, args...) TQDEBUG_DEBUG(format, args)

#define TQDEBUG_ERROR(format, args...) TQDEBUG_DEBUG(":ERROR: " format, args)
#define TQDEBUG_ERRORF(format, args...) TQDEBUG_DEBUG(":ERROR: " format, args)

#define TQDEBUG_FUNC_IN TQDEBUG_DEBUG("IN")

#endif


#define D_NULL        0x00

#define GET_32(A) (              \
                     (A << 24) | \
                     (A << 16) | \
                     (A <<  8) | \
                     (A)         \
                  )
#define GET_24(A) (              \
                     (A << 16) | \
                     (A <<  8) | \
                     (A)         \
                  )
#define GET_16(A) (              \
                     (A << 8) |  \
                     (A)         \
                  )
#define GET_8(A)  (  ((_u8) A) )


#define GET_B4(A) ( (_u8)(A >> 24) )
#define GET_B3(A) ( (_u8)(A >> 16) )
#define GET_B2(A) ( (_u8)(A >>  8) )
#define GET_B1(A) ( (_u8)A )




//=================================================================
//  Global Macros
//=================================================================
#ifdef __cplusplus

#define TQTVD_SHARED_PTR boost::shared_ptr
#define TQTVD_WEAK_PTR boost::weak_ptr

#define DECLARE_SHARE_PTR(classname) \
	class classname; \
	typedef TQTVD_SHARED_PTR<classname> classname##Ptr;  \
    typedef TQTVD_WEAK_PTR<classname> classname##WPtr;

#define DECLARE_STATIC_INLINE( PP_MemberT, PP_member, PP_value) \
	static const PP_MemberT PP_member(){ PP_MemberT member( PP_value ); return member; }

#define DECLARE_CLASS_COMMON( PP_ClassName) \
	DECLARE_STATIC_INLINE(std::string, NAME, #PP_ClassName); \
	typedef TQTVD_SHARED_PTR< PP_ClassName > SPtr;\
	typedef TQTVD_WEAK_PTR< PP_ClassName > WPtr;

#endif

#ifndef _BIG_ENDIAN
#define _LITTLE_ENDIAN
#endif

#ifdef _LITTLE_ENDIAN
#define FIX_WORD(A)   ((((_u16)(A) & 0xff00) >> 8) | ( ((_u16)(A) & 0x00ff) << 8))
#define FIX_DWORD(A)  ((((_u32)(A) & 0xff000000) >> 24) | \
                       (((_u32)(A) & 0x00ff0000) >>  8) | \
                       (((_u32)(A) & 0x0000ff00) <<  8) | \
                       (((_u32)(A) & 0x000000ff) << 24) )
#else
#define FIX_WORD(A)   (A)
#define FIX_DWORD(A)  (A)
#endif

#define TQ_ARRAY_SIZE(x) ((int)(sizeof(x) / sizeof(x[0])))

#ifndef MIN
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif

#ifndef MAX
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif

#ifdef _MSC_VER
    #ifdef BUILDING_DLL
        #define DLLEXPORT __declspec(dllexport)
    #else
        #define DLLEXPORT __declspec(dllimport)
    #endif
    #define DLLLOCAL
#else
    #if __GNUC__ >= 4
        #define DLLEXPORT __attribute__ ((visibility("default")))
        #define DLLLOCAL __attribute__ ((visibility("hidden")))
    #else
        #define DLLEXPORT
        #define DLLLOCAL
    #endif
#endif

#ifndef SYS_DLL
    #ifdef _MSC_VER
        #define SYS_DLL __declspec( dllimport)
    #else
        #define SYS_DLL
    #endif
#endif

#ifdef __cplusplus

#define CAST_CONST_STATIC_FROM_THIS( type) \
    const_cast< type>( static_cast< type>( this));

#define DECLARE_ENABLE_SHARED_FROM_THIS( classname) \
    public boost::enable_shared_from_this< classname>

#define DECLARE_VIRTUAL_ENABLE_SHARED_FROM_THIS( classname) \
    public virtual boost::enable_shared_from_this< classname>

#define IMPLEMENT_ENABLE_SHARED_FROM_THIS( classname) \
    boost::enable_shared_from_this< classname>()

#define SHARED_FROM_THIS() \
    shared_from_this()

#define DYNAMIC_POINTER_CAST( to, from) \
  boost::dynamic_pointer_cast< to>( from)

#define STATIC_POINTER_CAST( to, from) \
  boost::static_pointer_cast< to>( from)

#endif

#ifdef __cplusplus

////////////////////////////////////////////////////////////////////////////////
///                              Type use by Uiid
///
typedef unsigned long ulong;

#endif

#define try_free(x)  if (x != NULL) { free(x);  x=NULL; }
#define try_delete x if (x != NULL) { delete x; x=NULL; }


#ifndef TQTVD_END_OF_LINE
#define TQTVD_END_OF_LINE "\n"
#endif

#endif // TQTVD_COMMON_INC
