// distribution boxbackup-0.11.1 (svn version: 2821_2827)
// Box Backup, http://www.boxbackup.org/
// 
// Copyright (c) 2003-2010, Ben Summers and contributors.
// All rights reserved.
// 
// Note that this project uses mixed licensing. Any file with this license
// attached, or where the code LICENSE-DUAL appears on the first line, falls
// under this license. See the file COPYING.txt for more information.
// 
// This file is dual licensed. You may use and distribute it providing that you
// comply EITHER with the terms of the BSD license, OR the GPL license. It is
// not necessary to comply with both licenses, only one.
// 
// The BSD license option follows:
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 
// 2. 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.
//  
// 3. Neither the name of the Box Backup 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 HOLDER 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.
// 
// [http://en.wikipedia.org/wiki/BSD_licenses#3-clause_license_.28.22New_BSD_License.22.29]
// 
// The GPL license option follows:
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// This program 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 General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
// 
// [http://www.gnu.org/licenses/old-licenses/gpl-2.0.html#SEC4]
// --------------------------------------------------------------------------
//
// File
//		Name:    Box.h
//		Purpose: Main header file for the Box project
//		Created: 2003/07/08
//
// --------------------------------------------------------------------------

#ifndef BOX__H
#define BOX__H

// Use the same changes as gcc3 for gcc4
#ifdef PLATFORM_GCC4
	#define PLATFORM_GCC3
#endif

#include "BoxPlatform.h"

// uncomment this line to enable full memory leak finding on all
// malloc-ed blocks (at least, ones used by the STL)
//#define MEMLEAKFINDER_FULL_MALLOC_MONITORING

// Show backtraces on exceptions in release builds until further notice
// (they are only logged at TRACE level anyway)
#ifdef HAVE_EXECINFO_H
	#define SHOW_BACKTRACE_ON_EXCEPTION
#endif

#ifdef SHOW_BACKTRACE_ON_EXCEPTION
	#include "Utils.h"
	#define OPTIONAL_DO_BACKTRACE DumpStackBacktrace();
#else
	#define OPTIONAL_DO_BACKTRACE
#endif

#include "CommonException.h"
#include "Logging.h"

#ifndef BOX_RELEASE_BUILD
	
	extern bool AssertFailuresToSyslog;
	#define ASSERT_FAILS_TO_SYSLOG_ON {AssertFailuresToSyslog = true;}
	void BoxDebugAssertFailed(const char *cond, const char *file, int line);
	#define ASSERT(cond) \
	{ \
		if(!(cond)) \
		{ \
			BoxDebugAssertFailed(#cond, __FILE__, __LINE__); \
			THROW_EXCEPTION_MESSAGE(CommonException, \
				AssertFailed, #cond); \
		} \
	}

	// Note that syslog tracing is independent of BoxDebugTraceOn,
	// but stdout tracing is not
	extern bool BoxDebugTraceToSyslog;
	#define TRACE_TO_SYSLOG(x) {BoxDebugTraceToSyslog = x;}
	extern bool BoxDebugTraceToStdout;
	#define TRACE_TO_STDOUT(x) {BoxDebugTraceToStdout = x;}

	extern bool BoxDebugTraceOn;
	int BoxDebug_printf(const char *format, ...);
	int BoxDebugTrace(const char *format, ...);
	
	#ifndef PLATFORM_DISABLE_MEM_LEAK_TESTING
		#define BOX_MEMORY_LEAK_TESTING
	#endif
	
	// Exception names
	#define EXCEPTION_CODENAMES_EXTENDED
	
#else
	#define ASSERT_FAILS_TO_SYSLOG_ON
	#define ASSERT(cond)

	#define TRACE_TO_SYSLOG(x) {}
	#define TRACE_TO_STDOUT(x) {}

	// Box Backup builds release get extra information for exception logging
	#define EXCEPTION_CODENAMES_EXTENDED
	#define EXCEPTION_CODENAMES_EXTENDED_WITH_DESCRIPTION
	
#endif

#ifdef BOX_MEMORY_LEAK_TESTING
	// Memory leak testing
	#include "MemLeakFinder.h"
	#define DEBUG_NEW new(__FILE__,__LINE__)
	#define MEMLEAKFINDER_NOT_A_LEAK(x)	memleakfinder_notaleak(x);
	#define MEMLEAKFINDER_NO_LEAKS		MemLeakSuppressionGuard _guard;
	#define MEMLEAKFINDER_INIT		memleakfinder_init();
	#define MEMLEAKFINDER_START {memleakfinder_global_enable = true;}
	#define MEMLEAKFINDER_STOP  {memleakfinder_global_enable = false;}
#else
	#define DEBUG_NEW new
	#define MEMLEAKFINDER_NOT_A_LEAK(x)
	#define MEMLEAKFINDER_NO_LEAKS
	#define MEMLEAKFINDER_INIT
	#define MEMLEAKFINDER_START
	#define MEMLEAKFINDER_STOP
#endif

#define THROW_EXCEPTION(type, subtype) \
	{ \
		if(!HideExceptionMessageGuard::ExceptionsHidden()) \
		{ \
			OPTIONAL_DO_BACKTRACE \
			BOX_WARNING("Exception thrown: " \
				#type "(" #subtype ") " \
				"at " __FILE__ "(" << __LINE__ << ")") \
		} \
		throw type(type::subtype); \
	}

#define THROW_EXCEPTION_MESSAGE(type, subtype, message) \
	{ \
		std::ostringstream _box_throw_line; \
		_box_throw_line << message; \
		if(!HideExceptionMessageGuard::ExceptionsHidden()) \
		{ \
			OPTIONAL_DO_BACKTRACE \
			BOX_WARNING("Exception thrown: " \
				#type "(" #subtype ") (" << message << \
				") at " __FILE__ "(" << __LINE__ << ")") \
		} \
		throw type(type::subtype, _box_throw_line.str()); \
	}

// extra macros for converting to network byte order
#ifdef HAVE_NETINET_IN_H
	#include <netinet/in.h>
#endif

// Always define a swap64 function, as it's useful.
inline uint64_t box_swap64(uint64_t x)
{
	return ((x & 0xff) << 56 |
		(x & 0xff00LL) << 40 |
		(x & 0xff0000LL) << 24 |
		(x & 0xff000000LL) << 8 |
		(x & 0xff00000000LL) >> 8 |
		(x & 0xff0000000000LL) >> 24 |
		(x & 0xff000000000000LL) >> 40 |
		(x & 0xff00000000000000LL) >> 56);
}

#ifdef WORDS_BIGENDIAN
	#define box_hton64(x) (x)
	#define box_ntoh64(x) (x)
#elif defined(HAVE_BSWAP64)
	#ifdef HAVE_SYS_ENDIAN_H
		#include <sys/endian.h>
	#endif
	#ifdef HAVE_ASM_BYTEORDER_H
		#include <asm/byteorder.h>
	#endif

	#define box_hton64(x) BSWAP64(x)
	#define box_ntoh64(x) BSWAP64(x)
#else
	#define box_hton64(x) box_swap64(x)
	#define box_ntoh64(x) box_swap64(x)
#endif

// overloaded auto-conversion functions
inline uint64_t hton(uint64_t in) { return box_hton64(in); }
inline uint32_t hton(uint32_t in) { return htonl(in); }
inline uint16_t hton(uint16_t in) { return htons(in); }
inline uint8_t  hton(uint8_t in)  { return in; }
inline int64_t  hton(int64_t in)  { return box_hton64(in); }
inline int32_t  hton(int32_t in)  { return htonl(in); }
inline int16_t  hton(int16_t in)  { return htons(in); }
inline int8_t   hton(int8_t in)   { return in; }
inline uint64_t ntoh(uint64_t in) { return box_ntoh64(in); }
inline uint32_t ntoh(uint32_t in) { return ntohl(in); }
inline uint16_t ntoh(uint16_t in) { return ntohs(in); }
inline uint8_t  ntoh(uint8_t in)  { return in; }
inline int64_t  ntoh(int64_t in)  { return box_ntoh64(in); }
inline int32_t  ntoh(int32_t in)  { return ntohl(in); }
inline int16_t  ntoh(int16_t in)  { return ntohs(in); }
inline int8_t   ntoh(int8_t in)   { return in; }

#endif // BOX__H

