

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/_/
//_/_/  This file is part of CMSDK version 2.0.0.170915_Beta4 (15 September 2017)
//_/_/  
//_/_/  developed by
//_/_/  
//_/_/  Communicative Machines Ltd. 
//_/_/    http://cmlabs.com/
//_/_/  Copyright (c) 2017
//_/_/  
//_/_/  in collaboration with 
//_/_/  
//_/_/  Icelandic Institute for Intelligent Machines ses
//_/_/    Menntavegur 1
//_/_/    101 Reykjavik
//_/_/    ICELAND
//_/_/    http://www.iiim.is/
//_/_/
//_/_/  and is released under the following
//_/_/  
//_/_/  EXTENDED BSD License
//_/_/
//_/_/  Redistribution and use in source and binary forms, with or without
//_/_/  modification, is permitted provided that the following conditions 
//_/_/  are met:
//_/_/
//_/_/  - Redistributions of source code must retain the above copyright 
//_/_/    and collaboration 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 its copyright holders nor the names of its 
//_/_/    contributors may be used to endorse or promote products derived from 
//_/_/    this software without specific prior written permission.
//_/_/
//_/_/  - CADIA Clause: The license granted in and to the software under this 
//_/_/    agreement is a limited-use license. The software may not be used in 
//_/_/    furtherance of: (i) intentionally causing bodily injury or severe 
//_/_/    emotional harm to any person; (ii) invading the personal privacy or 
//_/_/    violating the human rights of any person; or (iii) committing or 
//_/_/    preparing for any act of war. 
//_/_/
//_/_/  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.
//_/_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
#if !defined(__types_h)              // Sentry, use file only if it's not already included.
#define __types_h

#include "Standard.h"
#include <stdio.h>
#include <string.h>
// #define CNSPORT 10000
// #define FACTORYPORT 10001

#define CNSPRIORITY 90
#define FACTORYPRIORITY 90

#define BITFREE 1
#define BITOCCUPIED 0

#ifdef WINDOWS
#else
#endif

#if defined	ARCH_32

	typedef				bool		bit;
	typedef	signed		char		int8;
	typedef	unsigned	char		uint8;
	typedef				short		int16;
	typedef	unsigned	short		uint16;
	typedef				int			int32;
	typedef	unsigned	int			uint32;
	typedef				long long	int64;
	typedef	unsigned	long long	uint64;
	typedef				float		float32;
	typedef				double		float64;
//	typedef				uint32		paddr;

#elif defined	ARCH_64

	typedef				bool		bit;
	typedef	signed		char		int8;
	typedef	unsigned	char		uint8;
	typedef				short		int16;
	typedef	unsigned	short		uint16;
	typedef				int			int32;
	typedef	unsigned	int			uint32;
	typedef				float		float32;
	typedef				double		float64;
//	typedef				uint32		paddr;

	#ifdef WINDOWS
		typedef				long long	int64;
		typedef	unsigned	long long	uint64;
	#else
		typedef				long long	int64;
		typedef	unsigned	long long	uint64;
	#endif

#endif

#define INT32_NOVALUE		0x12345678
#define INT64_NOVALUE		0x123456789ABCDEF0L
#define FLOAT64_NOVALUE		0.123456789123456789

#define MAXVALUINT8    ((uint8)~((uint8)0))
#define MAXVALINT8     ((int8)(MAXVALUINT8 >> 1))
#define MAXVALUINT16   ((uint16)~((uint16)0))
#define MAXVALINT16    ((int16)(MAXVALUINT16 >> 1))
#define MAXVALUINT32   ((uint32)~((uint32)0))
#define MAXVALINT32    ((int32)(MAXVALUINT32 >> 1))
#define MAXVALUINT64   ((uint64)~((uint64)0))
#define MAXVALINT64    ((int64)(MAXVALUINT64 >> 1))

#define MERGEUINT3264(a,b)	(((uint64)a)<<32)|((uint64)b)
#define GET1UINT3264(a)		(uint32)((a & 0xffffffff00000000L)>>32)
#define GET2UINT3264(a)		(uint32)(a & 0x00000000ffffffffL)
#define MERGEUINT1632(a,b)	(((uint32)a)<<16)|((uint32)b)
#define GET1UINT1632(a)		(uint16)((a & 0xffff0000L)>>16)
#define GET2UINT1632(a)		(uint16)(a & 0x0000ffffL)

#define PSYTYPELEVELS 16

struct PsyType {
	uint16 levels[PSYTYPELEVELS];
	bool isValid() {return (levels[0] != 0);}
	bool operator==(const PsyType &othertype) const {
		return memcmp(levels, othertype.levels, sizeof(PsyType)) == 0;
	}
	bool operator!=(const PsyType &othertype) const {
		return memcmp(levels, othertype.levels, sizeof(PsyType)) != 0;
	}
	bool operator<(const PsyType &othertype) const {
		for (uint32 n = 0; n < PSYTYPELEVELS; n++) {
			if (levels[n] < othertype.levels[n])
				return true;
			else if (levels[n] > othertype.levels[n])
				return false;
		}
		return false;
	}
	bool operator>(const PsyType &othertype) const {
		for (uint32 n = 0; n < PSYTYPELEVELS; n++) {
			if (levels[n] > othertype.levels[n])
				return true;
			else if (levels[n] < othertype.levels[n])
				return false;
		}
		return false;
	}
	uint16 operator[](int i) const {
		if ((i < 0) && (i >= PSYTYPELEVELS))
			return 0;
		return levels[i];
	}
	bool setLevel(int i, uint16 value) {
		if ((i < 0) && (i >= PSYTYPELEVELS))
			return false;
		levels[i] = value;
		return true;
	}
	bool matches(PsyType& otherType) const {
		for (uint32 n = 0; n < PSYTYPELEVELS; n++) {
			if ((levels[n] != otherType.levels[n]) && (levels[n] != 0xFFFF) && (otherType.levels[n] != 0xFFFF))
				return false;
		}
		return true;

			//v = levels[n] & otherType.levels[n];
			//if ( (v != (levels[n] > otherType.levels[n] ? otherType.levels[n] : levels[n])))
			//	return false;
		//uint64 *a = (uint64*)&levels;
		//uint64 *b = (uint64*)&otherType.levels;
		//uint64 v;
		//uint32 n, c = sizeof(levels) / sizeof(uint64);
		//for (n = 0; n < c; n++) {
		//	v = *a++ & *b++;
		//	if ( (v != (*a>*b?*b:*a)))
		//		return false;
		//}
		//return true;
	}
	std::string toString() {
		if (!levels[0])
			return "";
		std::stringstream ss;
		ss << levels[0];
		for (uint32 n = 1; n < PSYTYPELEVELS; n++) {
			if (levels[n])
				ss << '.' << levels[n];
		}
		return ss.str();
	}
	bool fromString(const char* text) {
		if (!text)
			return false;
		memset(levels, 0, sizeof(PsyType));

		const char* pstr = text;
		const char* src = text;
		char *temp = new char[16];
		uint32 n = 0;

		while (pstr = strstr(src, ".")) {
			if (pstr - src) {
				memcpy(temp, src, pstr - src);
				temp[pstr - src] = 0;
				levels[n] = atoi(temp);
				n++;
				if (n == PSYTYPELEVELS)
					return true;
			}
			src = pstr + 1;
		}
		pstr = src + strlen(src);
		if (pstr - src) {
			memcpy(temp, src, pstr - src);
			temp[pstr - src] = 0;
			levels[n] = atoi(temp);
			n++;
		}
		delete[] temp;
		return isValid();
	}
};

#define PSYCONTEXTLEVELS 16

struct PsyContext {
	uint16 levels[PSYCONTEXTLEVELS];
	//bool operator=(const PsyContext &othertype) {
	//	return memcpy(levels, othertype.levels, sizeof(PsyContext));
	//}
	bool isValid() {return (levels[0] != 0);}
	bool operator==(const PsyContext &othercontext) const {
		return memcmp(levels, othercontext.levels, sizeof(PsyContext)) == 0;
	}
	bool operator!=(const PsyContext &othercontext) const {
		return memcmp(levels, othercontext.levels, sizeof(PsyContext)) != 0;
	}
	bool operator<(const PsyContext &othercontext) const {
		for (uint32 n = 0; n < PSYCONTEXTLEVELS; n++) {
			if (levels[n] < othercontext.levels[n])
				return true;
			else if (levels[n] > othercontext.levels[n])
				return false;
		}
		return false;
	}
	bool operator>(const PsyContext &othercontext) const {
		for (uint32 n = 0; n < PSYCONTEXTLEVELS; n++) {
			if (levels[n] > othercontext.levels[n])
				return true;
			else if (levels[n] < othercontext.levels[n])
				return false;
		}
		return false;
	}
	uint16 operator[](int i) const {
		if ((i < 0) && (i >= PSYCONTEXTLEVELS))
			return 0;
		return levels[i];
	}
	bool setLevel(int i, uint16 value) {
		if ((i < 0) && (i >= PSYCONTEXTLEVELS))
			return false;
		levels[i] = value;
		return true;
	}
	bool matches(const PsyContext& othercontext) const {
		for (uint32 n = 0; n < PSYCONTEXTLEVELS; n++) {
			if ((levels[n] != othercontext.levels[n]) &&
				(levels[n] != 0xFFFF) &&
				(othercontext.levels[n] != 0xFFFF) &&
				(levels[n] != 0) &&
				(othercontext.levels[n] != 0)
				)
				return false;
		}
		return true;
	}
	std::string toString() {
		if (!levels[0])
			return "";
		std::stringstream ss;
		ss << levels[0];
		for (uint32 n = 1; n < PSYCONTEXTLEVELS; n++) {
			if (levels[n])
				ss << '.' << levels[n];
		}
		return ss.str();
	}
	bool fromString(const char* text) {
		if (!text)
			return false;
		memset(levels, 0, sizeof(PsyContext));

		const char* pstr = text;
		const char* src = text;
		char *temp = new char[16];
		uint32 n = 0;

		while (pstr = strstr(src, ".")) {
			if (pstr - src) {
				memcpy(temp, src, pstr - src);
				temp[pstr - src] = 0;
				levels[n] = atoi(temp);
				n++;
				if (n == PSYCONTEXTLEVELS)
					return true;
			}
			src = pstr + 1;
		}
		pstr = src + strlen(src);
		if (pstr - src) {
			memcpy(temp, src, pstr - src);
			temp[pstr - src] = 0;
			levels[n] = atoi(temp);
			n++;
		}
		delete[] temp;
		return isValid();
	}

	#define CONTEXT_OTHER_ROOT	0
	#define CONTEXT_EQUAL		1
	#define CONTEXT_SUPERSEDES	2
	#define CONTEXT_INCLUDED	3

	uint8 compare(const PsyContext& othercontext) const {
		for (uint32 n = 0; n < PSYCONTEXTLEVELS; n++) {
			if ((levels[n] != othercontext.levels[n]) && (levels[n] != 0xFFFF) && (othercontext.levels[n] != 0xFFFF)) {
				if (n==0)
					return CONTEXT_OTHER_ROOT;
				else if (levels[n] == 0) {
					if (othercontext.levels[n] == 0)
						return CONTEXT_EQUAL;
					else
						return CONTEXT_INCLUDED;
				}
			//  included in the statement below
			//	else if (otherContext.levels[n] == 0)
			//		return CONTEXT_SUPERSEDES;
				else
					return CONTEXT_SUPERSEDES;
			}
		}
		return CONTEXT_EQUAL;
	}
};

static struct PsyType NOTYPE = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } };
static struct PsyContext NOCONTEXT = { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } };

#endif // TYPES_H
