<commit_before>
// FastNBT.cpp

// Implements the fast NBT parser and writer

#include "Globals.h"
#include "FastNBT.h"

// The number of NBT tags that are reserved when an NBT parsing is started.
// You can override this by using a cmdline define
#ifndef NBT_RESERVE_SIZE
	#define NBT_RESERVE_SIZE 200
#endif  // NBT_RESERVE_SIZE

#ifdef _MSC_VER
	// Dodge a C4127 (conditional expression is constant) for this specific macro usage
	#define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while ((false, false))
#else
	#define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while (false)
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cParsedNBT:

#define NEEDBYTES(N) \
	if (m_Length - m_Pos < N) \
	{ \
		return false; \
	}

cParsedNBT::cParsedNBT(const char * a_Data, int a_Length) :
	m_Data(a_Data),
	m_Length(a_Length),
	m_Pos(0)
{
	m_IsValid = Parse();
}

bool cParsedNBT::Parse(void)
{
	if (m_Length < 3)
	{
		// Data too short
		return false;
	}
	if (m_Data[0] != TAG_Compound)
	{
		// The top-level tag must be a Compound
		return false;
	}

	m_Tags.reserve(NBT_RESERVE_SIZE);

	m_Tags.push_back(cFastNBTTag(TAG_Compound, -1));

	m_Pos = 1;

	RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
	RETURN_FALSE_IF_FALSE(ReadCompound());

	return true;
}

bool cParsedNBT::ReadString(int & a_StringStart, int & a_StringLen)
{
	NEEDBYTES(2);
	a_StringStart = m_Pos + 2;
	a_StringLen = GetBEShort(m_Data + m_Pos);
	if (a_StringLen < 0)
	{
		// Invalid string length
		return false;
	}
	m_Pos += 2 + a_StringLen;
	return true;
}

bool cParsedNBT::ReadCompound(void)
{
	// Reads the latest tag as a compound
	int ParentIdx = m_Tags.size() - 1;
	int PrevSibling = -1;
	for (;;)
	{
		NEEDBYTES(1);
		eTagType TagType = (eTagType)(m_Data[m_Pos]);
		m_Pos++;
		if (TagType == TAG_End)
		{
			break;
		}
		m_Tags.push_back(cFastNBTTag(TagType, ParentIdx, PrevSibling));
		if (PrevSibling >= 0)
		{
			m_Tags[PrevSibling].m_NextSibling = m_Tags.size() - 1;
		}
		else
		{
			m_Tags[ParentIdx].m_FirstChild = m_Tags.size() - 1;
		}
		PrevSibling = m_Tags.size() - 1;
		RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
		RETURN_FALSE_IF_FALSE(ReadTag());
	}  // while (true)
	m_Tags[ParentIdx].m_LastChild = PrevSibling;
	return true;
}

bool cParsedNBT::ReadList(eTagType a_ChildrenType)
{
	// Reads the latest tag as a list of items of type a_ChildrenType

	// Read the count:
	NEEDBYTES(4);
	int Count = GetBEInt(m_Data + m_Pos);
	m_Pos += 4;
	if (Count < 0)
	{
		return false;
	}

	// Read items:
	int ParentIdx = m_Tags.size() - 1;
	int PrevSibling = -1;
	for (int i = 0; i < Count; i++)
	{
		m_Tags.push_back(cFastNBTTag(a_ChildrenType, ParentIdx, PrevSibling));
		if (PrevSibling >= 0)
		{
			m_Tags[PrevSibling].m_NextSibling = m_Tags.size() - 1;
		}
		else
		{
			m_Tags[ParentIdx].m_FirstChild = m_Tags.size() - 1;
		}
		PrevSibling = m_Tags.size() - 1;
		RETURN_FALSE_IF_FALSE(ReadTag());
	}  // for (i)
	m_Tags[ParentIdx].m_LastChild = PrevSibling;
	return true;
}

#define CASE_SIMPLE_TAG(TAGTYPE, LEN) \
	case TAG_##TAGTYPE: \
	{ \
		NEEDBYTES(LEN); \
		Tag.m_DataStart = m_Pos; \
		Tag.m_DataLength = LEN; \
		m_Pos += LEN; \
		return true; \
	}

bool cParsedNBT::ReadTag(void)
{
	cFastNBTTag & Tag = m_Tags.back();
	switch (Tag.m_Type)
	{
		CASE_SIMPLE_TAG(Byte,   1)
		CASE_SIMPLE_TAG(Short,  2)
		CASE_SIMPLE_TAG(Int,    4)
		CASE_SIMPLE_TAG(Long,   8)
		CASE_SIMPLE_TAG(Float,  4)
		CASE_SIMPLE_TAG(Double, 8)

		case TAG_String:
		{
			return ReadString(Tag.m_DataStart, Tag.m_DataLength);
		}

		case TAG_ByteArray:
		{
			NEEDBYTES(4);
			int len = GetBEInt(m_Data + m_Pos);
			m_Pos += 4;
			if (len < 0)
			{
				// Invalid length
				return false;
			}
			NEEDBYTES(len);
			Tag.m_DataLength = len;
			Tag.m_DataStart = m_Pos;
			m_Pos += len;
			return true;
		}

		case TAG_List:
		{
			NEEDBYTES(1);
			eTagType ItemType = (eTagType)m_Data[m_Pos];
			m_Pos++;
			RETURN_FALSE_IF_FALSE(ReadList(ItemType));
			return true;
		}

		case TAG_Compound:
		{
			RETURN_FALSE_IF_FALSE(ReadCompound());
			return true;
		}

		case TAG_IntArray:
		{
			NEEDBYTES(4);
			int len = GetBEInt(m_Data + m_Pos);
			m_Pos += 4;
			if (len < 0)
			{
				// Invalid length
				return false;
			}
			len *= 4;
			NEEDBYTES(len);
			Tag.m_DataLength = len;
			Tag.m_DataStart = m_Pos;
			m_Pos += len;
			return true;
		}

		default:
		{
			ASSERT(!"Unhandled NBT tag type");
			return false;
		}
	}  // switch (iType)
}

#undef CASE_SIMPLE_TAG

int cParsedNBT::FindChildByName(int a_Tag, const char * a_Name, size_t a_NameLength) const
{
	if (a_Tag < 0)
	{
		return -1;
	}
	if (m_Tags[a_Tag].m_Type != TAG_Compound)
	{
		return -1;
	}

	if (a_NameLength == 0)
	{
		a_NameLength = strlen(a_Name);
	}
	for (int Child = m_Tags[a_Tag].m_FirstChild; Child != -1; Child = m_Tags[Child].m_NextSibling)
	{
		if (
			(m_Tags[Child].m_NameLength == (int)a_NameLength) &&
			(memcmp(m_Data + m_Tags[Child].m_NameStart, a_Name, a_NameLength) == 0)
		)
		{
			return Child;
		}
	}  // for Child - children of a_Tag
	return -1;
}

int cParsedNBT::FindTagByPath(int a_Tag, const AString & a_Path) const
{
	if (a_Tag < 0)
	{
		return -1;
	}
	size_t Begin = 0;
	size_t Length = a_Path.length();
	int Tag = a_Tag;
	for (size_t i = 0; i < Length; i++)
	{
		if (a_Path[i] != '\\')
		{
			continue;
		}
		Tag = FindChildByName(Tag, a_Path.c_str() + Begin, i - Begin - 1);
		if (Tag < 0)
		{
			return -1;
		}
		Begin = i + 1;
	}  // for i - a_Path[]

	if (Begin < Length)
	{
		Tag = FindChildByName(Tag, a_Path.c_str() + Begin, Length - Begin);
	}
	return Tag;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cFastNBTWriter:

cFastNBTWriter::cFastNBTWriter(const AString & a_RootTagName) :
	m_CurrentStack(0)
{
	m_Stack[0].m_Type = TAG_Compound;
	m_Result.reserve(100 * 1024);
	m_Result.push_back(TAG_Compound);
	WriteString(a_RootTagName.data(), a_RootTagName.size());
}

void cFastNBTWriter::BeginCompound(const AString & a_Name)
{
	if (m_CurrentStack >= MAX_STACK)
	{
		ASSERT(!"Stack overflow");
		return;
	}

	TagCommon(a_Name, TAG_Compound);

	++m_CurrentStack;
	m_Stack[m_CurrentStack].m_Type = TAG_Compound;
}

void cFastNBTWriter::EndCompound(void)
{
	ASSERT(m_CurrentStack > 0);
	ASSERT(IsStackTopCompound());

	m_Result.push_back(TAG_End);
	--m_CurrentStack;
}

void cFastNBTWriter::BeginList(const AString & a_Name, eTagType a_ChildrenType)
{
	if (m_CurrentStack >= MAX_STACK)
	{
		ASSERT(!"Stack overflow");
		return;
	}

	TagCommon(a_Name, TAG_List);

	m_Result.push_back((char)a_ChildrenType);
	m_Result.append(4, (char)0);

	++m_CurrentStack;
	m_Stack[m_CurrentStack].m_Type     = TAG_List;
	m_Stack[m_CurrentStack].m_Pos      = m_Result.size() - 4;
	m_Stack[m_CurrentStack].m_Count    = 0;
	m_Stack[m_CurrentStack].m_ItemType = a_ChildrenType;
}

void cFastNBTWriter::EndList(void)
{
	ASSERT(m_CurrentStack > 0);
	ASSERT(m_Stack[m_CurrentStack].m_Type == TAG_List);

	// Update the list count:
	SetBEInt((char *)(m_Result.c_str() + m_Stack[m_CurrentStack].m_Pos), m_Stack[m_CurrentStack].m_Count);

	--m_CurrentStack;
}

void cFastNBTWriter::AddByte(const AString & a_Name, unsigned char a_Value)
{
	TagCommon(a_Name, TAG_Byte);
	m_Result.push_back(a_Value);
}

void cFastNBTWriter::AddShort(const AString & a_Name, Int16 a_Value)
{
	TagCommon(a_Name, TAG_Short);
	Int16 Value = htons(a_Value);
	m_Result.append((const char *)&Value, 2);
}

void cFastNBTWriter::AddInt(const AString & a_Name, Int32 a_Value)
{
	TagCommon(a_Name, TAG_Int);
	Int32 Value = htonl(a_Value);
	m_Result.append((const char *)&Value, 4);
}

void cFastNBTWriter::AddLong(const AString & a_Name, Int64 a_Value)
{
	TagCommon(a_Name, TAG_Long);
	Int64 Value = HostToNetwork8(&a_Value);
	m_Result.append((const char *)&Value, 8);
}

void cFastNBTWriter::AddFloat(const AString & a_Name, float a_Value)
{
	TagCommon(a_Name, TAG_Float);
	Int32 Value = HostToNetwork4(&a_Value);
	m_Result.append((const char *)&Value, 4);
}

void cFastNBTWriter::AddDouble(const AString & a_Name, double a_Value)
{
	TagCommon(a_Name, TAG_Double);
	Int64 Value = HostToNetwork8(&a_Value);
	m_Result.append((const char *)&Value, 8);
}

void cFastNBTWriter::AddString(const AString & a_Name, const AString & a_Value)
{
	TagCommon(a_Name, TAG_String);
	Int16 len = htons((short)(a_Value.size()));
	m_Result.append((const char *)&len, 2);
	m_Result.append(a_Value.c_str(), a_Value.size());
}

void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value, size_t a_NumElements)
{
	TagCommon(a_Name, TAG_ByteArray);
	Int32 len = htonl(a_NumElements);
	m_Result.append((const char *)&len, 4);
	m_Result.append(a_Value, a_NumElements);
}

void cFastNBTWriter::AddIntArray(const AString & a_Name, const int * a_Value, size_t a_NumElements)
{
	TagCommon(a_Name, TAG_IntArray);
	Int32 len = htonl(a_NumElements);
	m_Result.append((const char *)&len, 4);
#if defined(ANDROID_NDK)
	// Android has alignment issues - cannot byteswap (htonl) an int that is not 32-bit-aligned, which happens in the regular version
	for (size_t i = 0; i < a_NumElements; i++)
	{
		int Element = htonl(a_Value[i]);
		m_Result.append((const char *)&Element, 4);
	}
#else
	int * Elements = (int *)(m_Result.data() + m_Result.size());
	m_Result.append(a_NumElements * 4, (char)0);
	for (size_t i = 0; i < a_NumElements; i++)
	{
		Elements[i] = htonl(a_Value[i]);
	}
#endif
}

void cFastNBTWriter::Finish(void)
{
	ASSERT(m_CurrentStack == 0);
	m_Result.push_back(TAG_End);
}

void cFastNBTWriter::WriteString(const char * a_Data, short a_Length)
{
	Int16 Len = htons(a_Length);
	m_Result.append((const char *)&Len, 2);
	m_Result.append(a_Data, a_Length);
}

<commit_msg>Use string.reserve to avoid the need to do inplace byteswap<commit_after>
// FastNBT.cpp

// Implements the fast NBT parser and writer

#include "Globals.h"
#include "FastNBT.h"

// The number of NBT tags that are reserved when an NBT parsing is started.
// You can override this by using a cmdline define
#ifndef NBT_RESERVE_SIZE
	#define NBT_RESERVE_SIZE 200
#endif  // NBT_RESERVE_SIZE

#ifdef _MSC_VER
	// Dodge a C4127 (conditional expression is constant) for this specific macro usage
	#define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while ((false, false))
#else
	#define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while (false)
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cParsedNBT:

#define NEEDBYTES(N) \
	if (m_Length - m_Pos < N) \
	{ \
		return false; \
	}

cParsedNBT::cParsedNBT(const char * a_Data, int a_Length) :
	m_Data(a_Data),
	m_Length(a_Length),
	m_Pos(0)
{
	m_IsValid = Parse();
}

bool cParsedNBT::Parse(void)
{
	if (m_Length < 3)
	{
		// Data too short
		return false;
	}
	if (m_Data[0] != TAG_Compound)
	{
		// The top-level tag must be a Compound
		return false;
	}

	m_Tags.reserve(NBT_RESERVE_SIZE);

	m_Tags.push_back(cFastNBTTag(TAG_Compound, -1));

	m_Pos = 1;

	RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
	RETURN_FALSE_IF_FALSE(ReadCompound());

	return true;
}

bool cParsedNBT::ReadString(int & a_StringStart, int & a_StringLen)
{
	NEEDBYTES(2);
	a_StringStart = m_Pos + 2;
	a_StringLen = GetBEShort(m_Data + m_Pos);
	if (a_StringLen < 0)
	{
		// Invalid string length
		return false;
	}
	m_Pos += 2 + a_StringLen;
	return true;
}

bool cParsedNBT::ReadCompound(void)
{
	// Reads the latest tag as a compound
	int ParentIdx = m_Tags.size() - 1;
	int PrevSibling = -1;
	for (;;)
	{
		NEEDBYTES(1);
		eTagType TagType = (eTagType)(m_Data[m_Pos]);
		m_Pos++;
		if (TagType == TAG_End)
		{
			break;
		}
		m_Tags.push_back(cFastNBTTag(TagType, ParentIdx, PrevSibling));
		if (PrevSibling >= 0)
		{
			m_Tags[PrevSibling].m_NextSibling = m_Tags.size() - 1;
		}
		else
		{
			m_Tags[ParentIdx].m_FirstChild = m_Tags.size() - 1;
		}
		PrevSibling = m_Tags.size() - 1;
		RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
		RETURN_FALSE_IF_FALSE(ReadTag());
	}  // while (true)
	m_Tags[ParentIdx].m_LastChild = PrevSibling;
	return true;
}

bool cParsedNBT::ReadList(eTagType a_ChildrenType)
{
	// Reads the latest tag as a list of items of type a_ChildrenType

	// Read the count:
	NEEDBYTES(4);
	int Count = GetBEInt(m_Data + m_Pos);
	m_Pos += 4;
	if (Count < 0)
	{
		return false;
	}

	// Read items:
	int ParentIdx = m_Tags.size() - 1;
	int PrevSibling = -1;
	for (int i = 0; i < Count; i++)
	{
		m_Tags.push_back(cFastNBTTag(a_ChildrenType, ParentIdx, PrevSibling));
		if (PrevSibling >= 0)
		{
			m_Tags[PrevSibling].m_NextSibling = m_Tags.size() - 1;
		}
		else
		{
			m_Tags[ParentIdx].m_FirstChild = m_Tags.size() - 1;
		}
		PrevSibling = m_Tags.size() - 1;
		RETURN_FALSE_IF_FALSE(ReadTag());
	}  // for (i)
	m_Tags[ParentIdx].m_LastChild = PrevSibling;
	return true;
}

#define CASE_SIMPLE_TAG(TAGTYPE, LEN) \
	case TAG_##TAGTYPE: \
	{ \
		NEEDBYTES(LEN); \
		Tag.m_DataStart = m_Pos; \
		Tag.m_DataLength = LEN; \
		m_Pos += LEN; \
		return true; \
	}

bool cParsedNBT::ReadTag(void)
{
	cFastNBTTag & Tag = m_Tags.back();
	switch (Tag.m_Type)
	{
		CASE_SIMPLE_TAG(Byte,   1)
		CASE_SIMPLE_TAG(Short,  2)
		CASE_SIMPLE_TAG(Int,    4)
		CASE_SIMPLE_TAG(Long,   8)
		CASE_SIMPLE_TAG(Float,  4)
		CASE_SIMPLE_TAG(Double, 8)

		case TAG_String:
		{
			return ReadString(Tag.m_DataStart, Tag.m_DataLength);
		}

		case TAG_ByteArray:
		{
			NEEDBYTES(4);
			int len = GetBEInt(m_Data + m_Pos);
			m_Pos += 4;
			if (len < 0)
			{
				// Invalid length
				return false;
			}
			NEEDBYTES(len);
			Tag.m_DataLength = len;
			Tag.m_DataStart = m_Pos;
			m_Pos += len;
			return true;
		}

		case TAG_List:
		{
			NEEDBYTES(1);
			eTagType ItemType = (eTagType)m_Data[m_Pos];
			m_Pos++;
			RETURN_FALSE_IF_FALSE(ReadList(ItemType));
			return true;
		}

		case TAG_Compound:
		{
			RETURN_FALSE_IF_FALSE(ReadCompound());
			return true;
		}

		case TAG_IntArray:
		{
			NEEDBYTES(4);
			int len = GetBEInt(m_Data + m_Pos);
			m_Pos += 4;
			if (len < 0)
			{
				// Invalid length
				return false;
			}
			len *= 4;
			NEEDBYTES(len);
			Tag.m_DataLength = len;
			Tag.m_DataStart = m_Pos;
			m_Pos += len;
			return true;
		}

		default:
		{
			ASSERT(!"Unhandled NBT tag type");
			return false;
		}
	}  // switch (iType)
}

#undef CASE_SIMPLE_TAG

int cParsedNBT::FindChildByName(int a_Tag, const char * a_Name, size_t a_NameLength) const
{
	if (a_Tag < 0)
	{
		return -1;
	}
	if (m_Tags[a_Tag].m_Type != TAG_Compound)
	{
		return -1;
	}

	if (a_NameLength == 0)
	{
		a_NameLength = strlen(a_Name);
	}
	for (int Child = m_Tags[a_Tag].m_FirstChild; Child != -1; Child = m_Tags[Child].m_NextSibling)
	{
		if (
			(m_Tags[Child].m_NameLength == (int)a_NameLength) &&
			(memcmp(m_Data + m_Tags[Child].m_NameStart, a_Name, a_NameLength) == 0)
		)
		{
			return Child;
		}
	}  // for Child - children of a_Tag
	return -1;
}

int cParsedNBT::FindTagByPath(int a_Tag, const AString & a_Path) const
{
	if (a_Tag < 0)
	{
		return -1;
	}
	size_t Begin = 0;
	size_t Length = a_Path.length();
	int Tag = a_Tag;
	for (size_t i = 0; i < Length; i++)
	{
		if (a_Path[i] != '\\')
		{
			continue;
		}
		Tag = FindChildByName(Tag, a_Path.c_str() + Begin, i - Begin - 1);
		if (Tag < 0)
		{
			return -1;
		}
		Begin = i + 1;
	}  // for i - a_Path[]

	if (Begin < Length)
	{
		Tag = FindChildByName(Tag, a_Path.c_str() + Begin, Length - Begin);
	}
	return Tag;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cFastNBTWriter:

cFastNBTWriter::cFastNBTWriter(const AString & a_RootTagName) :
	m_CurrentStack(0)
{
	m_Stack[0].m_Type = TAG_Compound;
	m_Result.reserve(100 * 1024);
	m_Result.push_back(TAG_Compound);
	WriteString(a_RootTagName.data(), a_RootTagName.size());
}

void cFastNBTWriter::BeginCompound(const AString & a_Name)
{
	if (m_CurrentStack >= MAX_STACK)
	{
		ASSERT(!"Stack overflow");
		return;
	}

	TagCommon(a_Name, TAG_Compound);

	++m_CurrentStack;
	m_Stack[m_CurrentStack].m_Type = TAG_Compound;
}

void cFastNBTWriter::EndCompound(void)
{
	ASSERT(m_CurrentStack > 0);
	ASSERT(IsStackTopCompound());

	m_Result.push_back(TAG_End);
	--m_CurrentStack;
}

void cFastNBTWriter::BeginList(const AString & a_Name, eTagType a_ChildrenType)
{
	if (m_CurrentStack >= MAX_STACK)
	{
		ASSERT(!"Stack overflow");
		return;
	}

	TagCommon(a_Name, TAG_List);

	m_Result.push_back((char)a_ChildrenType);
	m_Result.append(4, (char)0);

	++m_CurrentStack;
	m_Stack[m_CurrentStack].m_Type     = TAG_List;
	m_Stack[m_CurrentStack].m_Pos      = m_Result.size() - 4;
	m_Stack[m_CurrentStack].m_Count    = 0;
	m_Stack[m_CurrentStack].m_ItemType = a_ChildrenType;
}

void cFastNBTWriter::EndList(void)
{
	ASSERT(m_CurrentStack > 0);
	ASSERT(m_Stack[m_CurrentStack].m_Type == TAG_List);

	// Update the list count:
	SetBEInt((char *)(m_Result.c_str() + m_Stack[m_CurrentStack].m_Pos), m_Stack[m_CurrentStack].m_Count);

	--m_CurrentStack;
}

void cFastNBTWriter::AddByte(const AString & a_Name, unsigned char a_Value)
{
	TagCommon(a_Name, TAG_Byte);
	m_Result.push_back(a_Value);
}

void cFastNBTWriter::AddShort(const AString & a_Name, Int16 a_Value)
{
	TagCommon(a_Name, TAG_Short);
	Int16 Value = htons(a_Value);
	m_Result.append((const char *)&Value, 2);
}

void cFastNBTWriter::AddInt(const AString & a_Name, Int32 a_Value)
{
	TagCommon(a_Name, TAG_Int);
	Int32 Value = htonl(a_Value);
	m_Result.append((const char *)&Value, 4);
}

void cFastNBTWriter::AddLong(const AString & a_Name, Int64 a_Value)
{
	TagCommon(a_Name, TAG_Long);
	Int64 Value = HostToNetwork8(&a_Value);
	m_Result.append((const char *)&Value, 8);
}

void cFastNBTWriter::AddFloat(const AString & a_Name, float a_Value)
{
	TagCommon(a_Name, TAG_Float);
	Int32 Value = HostToNetwork4(&a_Value);
	m_Result.append((const char *)&Value, 4);
}

void cFastNBTWriter::AddDouble(const AString & a_Name, double a_Value)
{
	TagCommon(a_Name, TAG_Double);
	Int64 Value = HostToNetwork8(&a_Value);
	m_Result.append((const char *)&Value, 8);
}

void cFastNBTWriter::AddString(const AString & a_Name, const AString & a_Value)
{
	TagCommon(a_Name, TAG_String);
	Int16 len = htons((short)(a_Value.size()));
	m_Result.append((const char *)&len, 2);
	m_Result.append(a_Value.c_str(), a_Value.size());
}

void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value, size_t a_NumElements)
{
	TagCommon(a_Name, TAG_ByteArray);
	Int32 len = htonl(a_NumElements);
	m_Result.append((const char *)&len, 4);
	m_Result.append(a_Value, a_NumElements);
}

void cFastNBTWriter::AddIntArray(const AString & a_Name, const int * a_Value, size_t a_NumElements)
{
	TagCommon(a_Name, TAG_IntArray);
	Int32 len = htonl(a_NumElements);
	size_t cap = m_Result.capacity();
	size_t size = m_Result.length();
	if ((cap - size) < (4 + a_NumElements * 4))
	{
		m_Result.reserve(size +4 + a_NumElements * 4);
	}
	m_Result.append((const char *)&len, 4);
	for (size_t i = 0; i < a_NumElements; i++)
	{
		int Element = htonl(a_Value[i]);
		m_Result.append((const char *)&Element, 4);
	}
}

void cFastNBTWriter::Finish(void)
{
	ASSERT(m_CurrentStack == 0);
	m_Result.push_back(TAG_End);
}

void cFastNBTWriter::WriteString(const char * a_Data, short a_Length)
{
	Int16 Len = htons(a_Length);
	m_Result.append((const char *)&Len, 2);
	m_Result.append(a_Data, a_Length);
}

<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * 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. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * $ Id: $
 *
 */

#include "XSLTInputSource.hpp"

#include <cassert>

#include <framework/URLInputSource.hpp>
#include <util/BinFileInputStream.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/StdBinInputStream.hpp>
#include <PlatformSupport/URISupport.hpp>

XSLTInputSource::XSLTInputSource() :
	InputSource(""),
	m_stream(0),
	m_node(0)
{
}

XSLTInputSource::XSLTInputSource(const XMLCh*	systemId) :
	InputSource(systemId),
	m_stream(0),
	m_node(0)
{
}

XSLTInputSource::XSLTInputSource(
			const XMLCh*	systemId,
			const XMLCh*	publicId) :
	InputSource(systemId, publicId),
	m_stream(0),
	m_node(0)
{
}

XSLTInputSource::XSLTInputSource(const char*	systemId) :
	InputSource(systemId),
	m_stream(0),
	m_node(0)
{
}

XSLTInputSource::XSLTInputSource(
			const char*		systemId,
			const char*		publicId) :
	InputSource(systemId,
				publicId),
	m_stream(0),
	m_node(0)
{
}

XSLTInputSource::XSLTInputSource(XalanNode*		node) :
	InputSource(""),
	m_stream(0),
	m_node(node)
{
}

#if defined(XALAN_NO_NAMESPACES)
XSLTInputSource::XSLTInputSource(istream*		stream) :
#else
XSLTInputSource::XSLTInputSource(std::istream*	stream) :
#endif
	InputSource(""),
	m_stream(stream),
	m_node(0)
{
}

BinInputStream*
XSLTInputSource::makeStream() const
{
	BinInputStream*		theResult = 0;

	if (m_stream != 0)
	{
		theResult = new StdBinInputStream(*m_stream);
	}
	else if (m_node == 0)
	{
#if 1
		URISupport::URLAutoPtrType	theURL = URISupport::getURLFromString(getSystemId());

		theResult = theURL->makeNewStream();
#else
		const XMLCh* const	theSystemID =
			getSystemId();

		const unsigned int	theColonIndex = indexOf(theSystemID, ':');
		const unsigned int	theLength = length(theSystemID);

		if (theColonIndex == theLength)
		{
			// No ':', so assume it's a file.
			theResult = new BinFileInputStream(theSystemID);
		}
		else
		{
			// It could be a DOS-style file spec...
			const unsigned int	theBackslashIndex = indexOf(theSystemID, '\\');

			if (theBackslashIndex < theLength && theBackslashIndex == 2)
			{
				// OK, another shot at a file...
				theResult = new BinFileInputStream(theSystemID);
			}
			else
			{
				URLInputSource inputSource(getSystemId());

				theResult = inputSource.makeStream();
			}
		}
#endif
	}

	return theResult;
}

void
XSLTInputSource::setNode(XalanNode*		node)
{
	m_node = node;
}

XalanNode*
XSLTInputSource::getNode() const
{
	return m_node;
}
<commit_msg>Fixed default constructor problem.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * 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. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * $ Id: $
 *
 */

#include "XSLTInputSource.hpp"

#include <cassert>

#include <framework/URLInputSource.hpp>
#include <util/BinFileInputStream.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/StdBinInputStream.hpp>
#include <PlatformSupport/URISupport.hpp>

XSLTInputSource::XSLTInputSource() :
	InputSource(),
	m_stream(0),
	m_node(0)
{
}

XSLTInputSource::XSLTInputSource(const XMLCh*	systemId) :
	InputSource(systemId),
	m_stream(0),
	m_node(0)
{
}

XSLTInputSource::XSLTInputSource(
			const XMLCh*	systemId,
			const XMLCh*	publicId) :
	InputSource(systemId, publicId),
	m_stream(0),
	m_node(0)
{
}

XSLTInputSource::XSLTInputSource(const char*	systemId) :
	InputSource(systemId),
	m_stream(0),
	m_node(0)
{
}

XSLTInputSource::XSLTInputSource(
			const char*		systemId,
			const char*		publicId) :
	InputSource(systemId,
				publicId),
	m_stream(0),
	m_node(0)
{
}

XSLTInputSource::XSLTInputSource(XalanNode*		node) :
	InputSource(""),
	m_stream(0),
	m_node(node)
{
}

#if defined(XALAN_NO_NAMESPACES)
XSLTInputSource::XSLTInputSource(istream*		stream) :
#else
XSLTInputSource::XSLTInputSource(std::istream*	stream) :
#endif
	InputSource(""),
	m_stream(stream),
	m_node(0)
{
}

BinInputStream*
XSLTInputSource::makeStream() const
{
	BinInputStream*		theResult = 0;

	if (m_stream != 0)
	{
		theResult = new StdBinInputStream(*m_stream);
	}
	else if (m_node == 0)
	{
#if 1
		URISupport::URLAutoPtrType	theURL = URISupport::getURLFromString(getSystemId());

		theResult = theURL->makeNewStream();
#else
		const XMLCh* const	theSystemID =
			getSystemId();

		const unsigned int	theColonIndex = indexOf(theSystemID, ':');
		const unsigned int	theLength = length(theSystemID);

		if (theColonIndex == theLength)
		{
			// No ':', so assume it's a file.
			theResult = new BinFileInputStream(theSystemID);
		}
		else
		{
			// It could be a DOS-style file spec...
			const unsigned int	theBackslashIndex = indexOf(theSystemID, '\\');

			if (theBackslashIndex < theLength && theBackslashIndex == 2)
			{
				// OK, another shot at a file...
				theResult = new BinFileInputStream(theSystemID);
			}
			else
			{
				URLInputSource inputSource(getSystemId());

				theResult = inputSource.makeStream();
			}
		}
#endif
	}

	return theResult;
}

void
XSLTInputSource::setNode(XalanNode*		node)
{
	m_node = node;
}

XalanNode*
XSLTInputSource::getNode() const
{
	return m_node;
}
<|endoftext|>


<commit_before>#include "controller.h"
#include "animation/animation.h"
#include "engine/resource_manager.h"
#include "engine/resource_manager_base.h"

namespace Lumix
{

static const ResourceType ANIMATION_TYPE("animation");

namespace Anim
{

ControllerResource::ControllerResource(const Path& path, ResourceManagerBase& resource_manager, IAllocator& allocator)
	: Resource(path, resource_manager, allocator)
	, m_root(nullptr)
	, m_allocator(allocator)
	, m_anim_set(allocator)
{
}

ControllerResource::~ControllerResource()
{
	unload();
}

void ControllerResource::unload()
{
	LUMIX_DELETE(m_allocator, m_root);
	m_root = nullptr;
	for (Animation* anim : m_anim_set)
	{
		if(anim) anim->getResourceManager().unload(*anim);
	}
	m_anim_set.clear();
}

bool ControllerResource::load(FS::IFile& file)
{
	InputBlob blob(file.getBuffer(), (int)file.size());
	deserialize(blob);
	return true;
}

void ControllerResource::setRoot(Component* component)
{
	ASSERT(m_root == nullptr);
	m_root = component;
}

void ControllerResource::deserialize(InputBlob& blob)
{
	Component::Type type;
	blob.read(type);
	m_root = createComponent(type, m_allocator);
	m_root->deserialize(blob, nullptr);
	blob.read(m_input_decl.inputs_count);
	for (int i = 0; i < m_input_decl.inputs_count; ++i)
	{
		auto& input = m_input_decl.inputs[i];
		blob.readString(input.name, lengthOf(input.name));
		blob.read(input.type);
		blob.read(input.offset);
	}

	blob.read(m_input_decl.constants_count);
	for (int i = 0; i < m_input_decl.constants_count; ++i)
	{
		auto& constant = m_input_decl.constants[i];
		blob.readString(constant.name, lengthOf(constant.name));
		blob.read(constant.type);
		switch (constant.type)
		{
			case InputDecl::BOOL: blob.read(constant.b_value); break;
			case InputDecl::INT: blob.read(constant.i_value); break;
			case InputDecl::FLOAT: blob.read(constant.f_value); break;
			default: ASSERT(false); return;
		}
	}

	m_anim_set.clear();
	int count;
	blob.read(count);
	auto* manager = m_resource_manager.getOwner().get(ANIMATION_TYPE);
	for (int i = 0; i < count; ++i)
	{
		uint32 key;
		char path[MAX_PATH_LENGTH];
		blob.read(key);
		blob.readString(path, lengthOf(path));
		Animation* anim = path[0] ? (Animation*)manager->load(Path(path)) : nullptr;
		if(anim) addDependency(*anim);
		m_anim_set.insert(key, anim);
	}
}

void ControllerResource::serialize(OutputBlob& blob)
{
	blob.write(m_root->type);
	m_root->serialize(blob);
	blob.write(m_input_decl.inputs_count);
	for (int i = 0; i < m_input_decl.inputs_count; ++i)
	{
		auto& input = m_input_decl.inputs[i];
		blob.writeString(input.name);
		blob.write(input.type);
		blob.write(input.offset);
	}
	blob.write(m_input_decl.constants_count);
	for (int i = 0; i < m_input_decl.constants_count; ++i)
	{
		auto& constant = m_input_decl.constants[i];
		blob.writeString(constant.name);
		blob.write(constant.type);
		switch (constant.type)
		{
			case InputDecl::BOOL: blob.write(constant.b_value); break;
			case InputDecl::INT: blob.write(constant.i_value); break;
			case InputDecl::FLOAT: blob.write(constant.f_value); break;
			default: ASSERT(false); return;
		}

	}
	blob.write(m_anim_set.size());
	for (auto iter = m_anim_set.begin(), end = m_anim_set.end(); iter != end; ++iter)
	{
		blob.write(iter.key());
		blob.writeString(iter.value() ? iter.value()->getPath().c_str() : "");
	}
}

ComponentInstance* ControllerResource::createInstance(IAllocator& allocator)
{
	return m_root ? m_root->createInstance(allocator) : nullptr;
}

Resource* ControllerManager::createResource(const Path& path)
{
	return LUMIX_NEW(m_allocator, ControllerResource)(path, *this, m_allocator);
}

void ControllerManager::destroyResource(Resource& resource)
{
	LUMIX_DELETE(m_allocator, (ControllerResource*)&resource);
}

} // namespace Anim

} // namespace Lumix<commit_msg>fixed crash when unloading anim controller<commit_after>#include "controller.h"
#include "animation/animation.h"
#include "engine/resource_manager.h"
#include "engine/resource_manager_base.h"

namespace Lumix
{

static const ResourceType ANIMATION_TYPE("animation");

namespace Anim
{

ControllerResource::ControllerResource(const Path& path, ResourceManagerBase& resource_manager, IAllocator& allocator)
	: Resource(path, resource_manager, allocator)
	, m_root(nullptr)
	, m_allocator(allocator)
	, m_anim_set(allocator)
{
}

ControllerResource::~ControllerResource()
{
	unload();
}

void ControllerResource::unload()
{
	LUMIX_DELETE(m_allocator, m_root);
	m_root = nullptr;
	for (Animation* anim : m_anim_set)
	{
		if (anim)
		{
			removeDependency(*anim);
			anim->getResourceManager().unload(*anim);
		}
	}
	m_anim_set.clear();
}

bool ControllerResource::load(FS::IFile& file)
{
	InputBlob blob(file.getBuffer(), (int)file.size());
	deserialize(blob);
	return true;
}

void ControllerResource::setRoot(Component* component)
{
	ASSERT(m_root == nullptr);
	m_root = component;
}

void ControllerResource::deserialize(InputBlob& blob)
{
	Component::Type type;
	blob.read(type);
	m_root = createComponent(type, m_allocator);
	m_root->deserialize(blob, nullptr);
	blob.read(m_input_decl.inputs_count);
	for (int i = 0; i < m_input_decl.inputs_count; ++i)
	{
		auto& input = m_input_decl.inputs[i];
		blob.readString(input.name, lengthOf(input.name));
		blob.read(input.type);
		blob.read(input.offset);
	}

	blob.read(m_input_decl.constants_count);
	for (int i = 0; i < m_input_decl.constants_count; ++i)
	{
		auto& constant = m_input_decl.constants[i];
		blob.readString(constant.name, lengthOf(constant.name));
		blob.read(constant.type);
		switch (constant.type)
		{
			case InputDecl::BOOL: blob.read(constant.b_value); break;
			case InputDecl::INT: blob.read(constant.i_value); break;
			case InputDecl::FLOAT: blob.read(constant.f_value); break;
			default: ASSERT(false); return;
		}
	}

	m_anim_set.clear();
	int count;
	blob.read(count);
	auto* manager = m_resource_manager.getOwner().get(ANIMATION_TYPE);
	for (int i = 0; i < count; ++i)
	{
		uint32 key;
		char path[MAX_PATH_LENGTH];
		blob.read(key);
		blob.readString(path, lengthOf(path));
		Animation* anim = path[0] ? (Animation*)manager->load(Path(path)) : nullptr;
		if(anim) addDependency(*anim);
		m_anim_set.insert(key, anim);
	}
}

void ControllerResource::serialize(OutputBlob& blob)
{
	blob.write(m_root->type);
	m_root->serialize(blob);
	blob.write(m_input_decl.inputs_count);
	for (int i = 0; i < m_input_decl.inputs_count; ++i)
	{
		auto& input = m_input_decl.inputs[i];
		blob.writeString(input.name);
		blob.write(input.type);
		blob.write(input.offset);
	}
	blob.write(m_input_decl.constants_count);
	for (int i = 0; i < m_input_decl.constants_count; ++i)
	{
		auto& constant = m_input_decl.constants[i];
		blob.writeString(constant.name);
		blob.write(constant.type);
		switch (constant.type)
		{
			case InputDecl::BOOL: blob.write(constant.b_value); break;
			case InputDecl::INT: blob.write(constant.i_value); break;
			case InputDecl::FLOAT: blob.write(constant.f_value); break;
			default: ASSERT(false); return;
		}

	}
	blob.write(m_anim_set.size());
	for (auto iter = m_anim_set.begin(), end = m_anim_set.end(); iter != end; ++iter)
	{
		blob.write(iter.key());
		blob.writeString(iter.value() ? iter.value()->getPath().c_str() : "");
	}
}

ComponentInstance* ControllerResource::createInstance(IAllocator& allocator)
{
	return m_root ? m_root->createInstance(allocator) : nullptr;
}

Resource* ControllerManager::createResource(const Path& path)
{
	return LUMIX_NEW(m_allocator, ControllerResource)(path, *this, m_allocator);
}

void ControllerManager::destroyResource(Resource& resource)
{
	LUMIX_DELETE(m_allocator, (ControllerResource*)&resource);
}

} // namespace Anim

} // namespace Lumix<|endoftext|>


<commit_before>//
// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#define BOOST_TEST_MODULE UnitTests
#include <boost/test/unit_test.hpp>

#include "UnitTests.hpp"
#include <armnn/Logging.hpp>
#include <armnn/utility/NumericCast.hpp>

struct ConfigureLoggingFixture
{
    ConfigureLoggingFixture()
    {
        ConfigureLoggingTest();
    }
};

BOOST_GLOBAL_FIXTURE(ConfigureLoggingFixture);

// On Windows, duplicate the boost test logging output to the Visual Studio output window using OutputDebugString.
#if defined(_MSC_VER)

#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/tee.hpp>
#include <iostream>
#include <common/include/WindowsWrapper.hpp>

using namespace boost::iostreams;
using namespace std;

struct DebugOutputSink : boost::iostreams::sink
{
    std::streamsize write(const char* s, std::streamsize n)
    {
        // The given string is not null-terminated, so we need to copy it.
        std::string s2(s, armnn::numeric_cast<size_t>(n));
        OutputDebugString(s2.c_str());
        return n;
    }
};

class SetupDebugOutput
{
public:
    SetupDebugOutput()
    {
        // Sends the output to both cout (as standard) and the debug output.
        m_OutputStream.push(tee(std::cout));
        m_OutputStream.push(m_DebugOutputSink);

        boost::unit_test::unit_test_log.set_stream(m_OutputStream);
    }
private:
    filtering_ostream m_OutputStream;
    DebugOutputSink m_DebugOutputSink;
};

BOOST_GLOBAL_FIXTURE(SetupDebugOutput);

#endif // defined(_MSC_VER)

BOOST_AUTO_TEST_SUITE(LoggerSuite)

BOOST_AUTO_TEST_CASE(LoggerTest)
{
    std::stringstream ss;

    {
        struct StreamRedirector
        {
        public:
            StreamRedirector(std::ostream& stream, std::streambuf* newStreamBuffer)
                : m_Stream(stream)
                , m_BackupBuffer(m_Stream.rdbuf(newStreamBuffer))
            {}
            ~StreamRedirector() { m_Stream.rdbuf(m_BackupBuffer); }

        private:
            std::ostream& m_Stream;
            std::streambuf* m_BackupBuffer;
        };

        StreamRedirector redirect(std::cout, ss.rdbuf());

        using namespace armnn;
        SetLogFilter(LogSeverity::Trace);
        SetAllLoggingSinks(true, false, false);

        ARMNN_LOG(trace) << "My trace message; " << -2;
        ARMNN_LOG(debug) << "My debug message; " << -1;
        ARMNN_LOG(info) << "My info message; " << 0;
        ARMNN_LOG(warning) << "My warning message; "  << 1;
        ARMNN_LOG(error) << "My error message; " << 2;
        ARMNN_LOG(fatal) << "My fatal message; "  << 3;

        SetLogFilter(LogSeverity::Fatal);

    }

    BOOST_CHECK(ss.str().find("Trace: My trace message; -2") != std::string::npos);
    BOOST_CHECK(ss.str().find("Debug: My debug message; -1") != std::string::npos);
    BOOST_CHECK(ss.str().find("Info: My info message; 0") != std::string::npos);
    BOOST_CHECK(ss.str().find("Warning: My warning message; 1") != std::string::npos);
    BOOST_CHECK(ss.str().find("Error: My error message; 2") != std::string::npos);
    BOOST_CHECK(ss.str().find("Fatal: My fatal message; 3") != std::string::npos);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>IVGCVSW-5964 As part of Boost removal this Windows only code is obsolete.<commit_after>//
// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#define BOOST_TEST_MODULE UnitTests
#include <boost/test/unit_test.hpp>

#include "UnitTests.hpp"
#include <armnn/Logging.hpp>
#include <armnn/utility/NumericCast.hpp>

struct ConfigureLoggingFixture
{
    ConfigureLoggingFixture()
    {
        ConfigureLoggingTest();
    }
};

BOOST_GLOBAL_FIXTURE(ConfigureLoggingFixture);

BOOST_AUTO_TEST_SUITE(LoggerSuite)

BOOST_AUTO_TEST_CASE(LoggerTest)
{
    std::stringstream ss;

    {
        struct StreamRedirector
        {
        public:
            StreamRedirector(std::ostream& stream, std::streambuf* newStreamBuffer)
                : m_Stream(stream)
                , m_BackupBuffer(m_Stream.rdbuf(newStreamBuffer))
            {}
            ~StreamRedirector() { m_Stream.rdbuf(m_BackupBuffer); }

        private:
            std::ostream& m_Stream;
            std::streambuf* m_BackupBuffer;
        };

        StreamRedirector redirect(std::cout, ss.rdbuf());

        using namespace armnn;
        SetLogFilter(LogSeverity::Trace);
        SetAllLoggingSinks(true, false, false);

        ARMNN_LOG(trace) << "My trace message; " << -2;
        ARMNN_LOG(debug) << "My debug message; " << -1;
        ARMNN_LOG(info) << "My info message; " << 0;
        ARMNN_LOG(warning) << "My warning message; "  << 1;
        ARMNN_LOG(error) << "My error message; " << 2;
        ARMNN_LOG(fatal) << "My fatal message; "  << 3;

        SetLogFilter(LogSeverity::Fatal);

    }

    BOOST_CHECK(ss.str().find("Trace: My trace message; -2") != std::string::npos);
    BOOST_CHECK(ss.str().find("Debug: My debug message; -1") != std::string::npos);
    BOOST_CHECK(ss.str().find("Info: My info message; 0") != std::string::npos);
    BOOST_CHECK(ss.str().find("Warning: My warning message; 1") != std::string::npos);
    BOOST_CHECK(ss.str().find("Error: My error message; 2") != std::string::npos);
    BOOST_CHECK(ss.str().find("Fatal: My fatal message; 3") != std::string::npos);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2015 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   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.
*/

#include <Testing/ModuleTestBase/ModuleTestBase.h>
#include <Modules/Factory/HardCodedModuleFactory.h>
#include <Dataflow/Engine/Controller/NetworkEditorController.h>
#include <sstream>
#include <map>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

using boost::property_tree::ptree;
using boost::property_tree::read_json;
using boost::property_tree::write_json;

using namespace SCIRun;
using namespace Testing;
using namespace Modules::Factory;
using namespace Dataflow::Networks;
using namespace ReplacementImpl;
using namespace Dataflow::Engine;
using namespace Core::Algorithms;

TEST(FactoryGeneratorTests, GenerateSomeJsonFromModuleProperties)
{
  HardCodedModuleFactory factory;

  auto descMap = factory.getDirectModuleDescriptionLookupMap();

  int i = 0;
  for (const auto& mod : descMap)
  {
    ++i;
    std::cout << mod.first << " -> " << mod.second << std::endl;

    // Write json.
    ptree pt;
    pt.put("module.name", mod.first.module_name_);
    pt.put("module.namespace", "<ns>");
    pt.put("module.status", mod.second.moduleStatus_);
    pt.put("module.description", mod.second.moduleInfo_);
    std::ostringstream buf;
    write_json(buf, pt, false);
    std::string json = buf.str(); // {"foo":"bar"}
    std::cout << json << std::endl;

    if (i > 3)
      break;
  }

  //FAIL() << "foo";
}

TEST(FactoryGeneratorTests, ReadFullModuleJsonDescription)
{
  std::string moduleJson =
    "{\n"
    "\t\"module\": {\n"
    "\t\t\"name\": \"CreateLatVol\",\n"
    "\t\t\"namespace\" : \"Fields\",\n"
    "\t\t\"status\" : \"Ported module\",\n"
    "\t\t\"description\" : \"Creates Lattice Volumes\",\n"
    "\t\t\"header\" : \"Modules/Legacy/Fields/CreateLatVol.h\"\n"
    "\t},\n"
    "\t\"algorithm\": {\n"
    "\t\t\"name\": \"CreateLatVolAlgo\",\n"
    "\t\t\"namespace\" : \"Fields\",\n"
    "\t\t\"header\" : \"Core/Algorithms/Legacy/Fields/CreateLatVolAlgo.h\"\n"
    "\t},\n"
    "\t\"UI\" : {\n"
    "\t\t\"name\": \"CreateLatVolDialog\",\n"
    "\t\t\"header\" : \"Interface/Modules/Fields/CreateLatVolDialog.h\"\n"
    "\t}\n"
    "}\n";

  std::cout << moduleJson << std::endl;

  ptree modProps;
  std::istringstream is(moduleJson);
  read_json(is, modProps);

  EXPECT_EQ("CreateLatVol", modProps.get<std::string>("module.name"));
  EXPECT_EQ("Fields", modProps.get<std::string>("module.namespace"));
  EXPECT_EQ("Ported module", modProps.get<std::string>("module.status"));
  EXPECT_EQ("Creates Lattice Volumes", modProps.get<std::string>("module.description"));
  EXPECT_EQ("Modules/Legacy/Fields/CreateLatVol.h", modProps.get<std::string>("module.header"));

  EXPECT_EQ("CreateLatVolAlgo", modProps.get<std::string>("algorithm.name"));
  EXPECT_EQ("Fields", modProps.get<std::string>("algorithm.namespace"));
  EXPECT_EQ("Core/Algorithms/Legacy/Fields/CreateLatVolAlgo.h", modProps.get<std::string>("algorithm.header"));

  EXPECT_EQ("CreateLatVolDialog", modProps.get<std::string>("UI.name"));
  EXPECT_EQ("Interface/Modules/Fields/CreateLatVolDialog.h", modProps.get<std::string>("UI.header"));

  EXPECT_THROW(modProps.get<std::string>("UI.namespace"), std::exception);

  //FAIL() << "json";
}
<commit_msg>Steps<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2015 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   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.
*/

#include <Testing/ModuleTestBase/ModuleTestBase.h>
#include <Modules/Factory/HardCodedModuleFactory.h>
#include <Dataflow/Engine/Controller/NetworkEditorController.h>
#include <sstream>
#include <map>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

using boost::property_tree::ptree;
using boost::property_tree::read_json;
using boost::property_tree::write_json;

using namespace SCIRun;
using namespace Testing;
using namespace Modules::Factory;
using namespace Dataflow::Networks;
using namespace ReplacementImpl;
using namespace Dataflow::Engine;
using namespace Core::Algorithms;

TEST(FactoryGeneratorTests, GenerateSomeJsonFromModuleProperties)
{
  HardCodedModuleFactory factory;

  auto descMap = factory.getDirectModuleDescriptionLookupMap();

  int i = 0;
  for (const auto& mod : descMap)
  {
    ++i;
    std::cout << mod.first << " -> " << mod.second << std::endl;

    // Write json.
    ptree pt;
    pt.put("module.name", mod.first.module_name_);
    pt.put("module.namespace", "<ns>");
    pt.put("module.status", mod.second.moduleStatus_);
    pt.put("module.description", mod.second.moduleInfo_);
    std::ostringstream buf;
    write_json(buf, pt, false);
    std::string json = buf.str(); // {"foo":"bar"}
    std::cout << json << std::endl;

    if (i > 3)
      break;
  }

  //FAIL() << "foo";
}

TEST(FactoryGeneratorTests, ReadFullModuleJsonDescription)
{
  std::string moduleJson =
    "{\n"
    "\t\"module\": {\n"
    "\t\t\"name\": \"CreateLatVol\",\n"
    "\t\t\"namespace\" : \"Fields\",\n"
    "\t\t\"status\" : \"Ported module\",\n"
    "\t\t\"description\" : \"Creates Lattice Volumes\",\n"
    "\t\t\"header\" : \"Modules/Legacy/Fields/CreateLatVol.h\"\n"
    "\t},\n"
    "\t\"algorithm\": {\n"
    "\t\t\"name\": \"CreateLatVolAlgo\",\n"
    "\t\t\"namespace\" : \"Fields\",\n"
    "\t\t\"header\" : \"Core/Algorithms/Legacy/Fields/CreateLatVolAlgo.h\"\n"
    "\t},\n"
    "\t\"UI\" : {\n"
    "\t\t\"name\": \"CreateLatVolDialog\",\n"
    "\t\t\"header\" : \"Interface/Modules/Fields/CreateLatVolDialog.h\"\n"
    "\t}\n"
    "}\n";

  std::cout << moduleJson << std::endl;

  ptree modProps;
  std::istringstream is(moduleJson);
  read_json(is, modProps);

  EXPECT_EQ("CreateLatVol", modProps.get<std::string>("module.name"));
  EXPECT_EQ("Fields", modProps.get<std::string>("module.namespace"));
  EXPECT_EQ("Ported module", modProps.get<std::string>("module.status"));
  EXPECT_EQ("Creates Lattice Volumes", modProps.get<std::string>("module.description"));
  EXPECT_EQ("Modules/Legacy/Fields/CreateLatVol.h", modProps.get<std::string>("module.header"));

  EXPECT_EQ("CreateLatVolAlgo", modProps.get<std::string>("algorithm.name"));
  EXPECT_EQ("Fields", modProps.get<std::string>("algorithm.namespace"));
  EXPECT_EQ("Core/Algorithms/Legacy/Fields/CreateLatVolAlgo.h", modProps.get<std::string>("algorithm.header"));

  EXPECT_EQ("CreateLatVolDialog", modProps.get<std::string>("UI.name"));
  EXPECT_EQ("Interface/Modules/Fields/CreateLatVolDialog.h", modProps.get<std::string>("UI.header"));

  EXPECT_THROW(modProps.get<std::string>("UI.namespace"), std::exception);

  //FAIL() << "json";
}

/*
Steps:
1. CMake flag for "build module list" is turned on
2. CMake gets path to .module descriptor files, and passes it to C++ program
3. C++ program receives path and iterates over all .module files
4. For each json.module, call read code above and construct a map of structures (worry about lookup efficiency later)
5. Loop over map of module desc structures and generate code lines
6. Output of C++ code is ModuleFactory_Generated.cc file with one generated method, to be called by existing C++ factory impl
7. Once that's working, extend to generate Algo and Dialog factory functions as well
8. Then start converting old HardCodedModuleFactory lines to new way. Write some python code for this
*/
<|endoftext|>


<commit_before>#include "stdafx.h"

#include "P23.MetaTrader4.Manager.ClrWrapper.h"

IList<P23::MetaTrader4::Manager::Contracts::BackupInfo^>^ P23::MetaTrader4::Manager::ClrWrapper::BackupInfoUsers(int mode)
{
	int total = 0;
	BackupInfo* result = _manager->Manager->BackupInfoUsers(mode, &total);
	IList<P23::MetaTrader4::Manager::Contracts::BackupInfo^>^ output = gcnew List<P23::MetaTrader4::Manager::Contracts::BackupInfo^>(total);
	for (int i = 0; i < total; i++)
		output->Add(Convert(&result[i]));

	_manager->Manager->MemFree(result);

	return output;
}

IList<P23::MetaTrader4::Manager::Contracts::BackupInfo^>^  P23::MetaTrader4::Manager::ClrWrapper::BackupInfoOrders(int mode)
{
	int total = 0;
	BackupInfo* result = _manager->Manager->BackupInfoOrders(mode, &total);
	IList<P23::MetaTrader4::Manager::Contracts::BackupInfo^>^ output = gcnew List<P23::MetaTrader4::Manager::Contracts::BackupInfo^>(total);
	for (int i = 0; i < total; i++)
		output->Add(Convert(&result[i]));

	_manager->Manager->MemFree(result);

	return output;
}

IList<P23::MetaTrader4::Manager::Contracts::UserRecord^>^  P23::MetaTrader4::Manager::ClrWrapper::BackupRequestUsers(String^ file, String^ request)
{
	int total = 0;

	char* f = Convert(file);
	char* r = Convert(request);
	if (f == NULL || r == NULL)
		throw gcnew ArgumentException("File and request mandatory parameters");

	UserRecord* result = _manager->Manager->BackupRequestUsers(f, r, &total);
	IList<P23::MetaTrader4::Manager::Contracts::UserRecord^>^ output = gcnew List<P23::MetaTrader4::Manager::Contracts::UserRecord^>(total);
	for (int i = 0; i < total; i++)
		output->Add(Convert(&result[i]));

	_manager->Manager->MemFree(result);
	Marshal::FreeHGlobal(IntPtr(f));
	Marshal::FreeHGlobal(IntPtr(r));

	return output;
}

IList<P23::MetaTrader4::Manager::Contracts::TradeRecord^>^ P23::MetaTrader4::Manager::ClrWrapper::BackupRequestOrders(String^ file, String^ request)
{
	int total = 0;

	char* f = Convert(file);
	char* r = Convert(request);
	if (f == NULL || r == NULL)
		throw gcnew ArgumentException("File and request mandatory parameters");

	TradeRecord* result = _manager->Manager->BackupRequestOrders(f, r, &total);
	IList<P23::MetaTrader4::Manager::Contracts::TradeRecord^>^ output = gcnew List<P23::MetaTrader4::Manager::Contracts::TradeRecord^>(total);
	for (int i = 0; i < total; i++)
		output->Add(Convert(&result[i]));

	_manager->Manager->MemFree(result);
	Marshal::FreeHGlobal(IntPtr(f));
	Marshal::FreeHGlobal(IntPtr(r));

	return output;
}

int P23::MetaTrader4::Manager::ClrWrapper::BackupRestoreUsers(IList<P23::MetaTrader4::Manager::Contracts::UserRecord^>^ users)
{
	int total = 0;

	UserRecord* u = new UserRecord[users->Count];
	for (int i = 0; i < users->Count; i++)
		u[i] = *Convert(users[i]);

	int result = _manager->Manager->BackupRestoreUsers(u, total);

	delete[] u;

	return result;
}

IList<P23::MetaTrader4::Manager::Contracts::TradeRestoreResult^>^ P23::MetaTrader4::Manager::ClrWrapper::BackupRestoreOrders(IList<P23::MetaTrader4::Manager::Contracts::TradeRecord^>^ trades)
{
	int total = trades->Count;

	TradeRecord* t = new TradeRecord[total];
	for (int i = 0; i < total; i++)
		t[i] = *Convert(trades[i]);

	TradeRestoreResult* result = _manager->Manager->BackupRestoreOrders(t, &total);

	IList<P23::MetaTrader4::Manager::Contracts::TradeRestoreResult^>^ output = gcnew List<P23::MetaTrader4::Manager::Contracts::TradeRestoreResult^>(total);
	for (int i = 0; i < total; i++)
		output->Add(Convert(&result[i]));

	_manager->Manager->MemFree(result);
	delete[] t;

	return output;
}<commit_msg>Fixed bug with BackupRestoreUsers<commit_after>#include "stdafx.h"

#include "P23.MetaTrader4.Manager.ClrWrapper.h"

IList<P23::MetaTrader4::Manager::Contracts::BackupInfo^>^ P23::MetaTrader4::Manager::ClrWrapper::BackupInfoUsers(int mode)
{
	int total = 0;
	BackupInfo* result = _manager->Manager->BackupInfoUsers(mode, &total);
	IList<P23::MetaTrader4::Manager::Contracts::BackupInfo^>^ output = gcnew List<P23::MetaTrader4::Manager::Contracts::BackupInfo^>(total);
	for (int i = 0; i < total; i++)
		output->Add(Convert(&result[i]));

	_manager->Manager->MemFree(result);

	return output;
}

IList<P23::MetaTrader4::Manager::Contracts::BackupInfo^>^  P23::MetaTrader4::Manager::ClrWrapper::BackupInfoOrders(int mode)
{
	int total = 0;
	BackupInfo* result = _manager->Manager->BackupInfoOrders(mode, &total);
	IList<P23::MetaTrader4::Manager::Contracts::BackupInfo^>^ output = gcnew List<P23::MetaTrader4::Manager::Contracts::BackupInfo^>(total);
	for (int i = 0; i < total; i++)
		output->Add(Convert(&result[i]));

	_manager->Manager->MemFree(result);

	return output;
}

IList<P23::MetaTrader4::Manager::Contracts::UserRecord^>^  P23::MetaTrader4::Manager::ClrWrapper::BackupRequestUsers(String^ file, String^ request)
{
	int total = 0;

	char* f = Convert(file);
	char* r = Convert(request);
	if (f == NULL || r == NULL)
		throw gcnew ArgumentException("File and request mandatory parameters");

	UserRecord* result = _manager->Manager->BackupRequestUsers(f, r, &total);
	IList<P23::MetaTrader4::Manager::Contracts::UserRecord^>^ output = gcnew List<P23::MetaTrader4::Manager::Contracts::UserRecord^>(total);
	for (int i = 0; i < total; i++)
		output->Add(Convert(&result[i]));

	_manager->Manager->MemFree(result);
	Marshal::FreeHGlobal(IntPtr(f));
	Marshal::FreeHGlobal(IntPtr(r));

	return output;
}

IList<P23::MetaTrader4::Manager::Contracts::TradeRecord^>^ P23::MetaTrader4::Manager::ClrWrapper::BackupRequestOrders(String^ file, String^ request)
{
	int total = 0;

	char* f = Convert(file);
	char* r = Convert(request);
	if (f == NULL || r == NULL)
		throw gcnew ArgumentException("File and request mandatory parameters");

	TradeRecord* result = _manager->Manager->BackupRequestOrders(f, r, &total);
	IList<P23::MetaTrader4::Manager::Contracts::TradeRecord^>^ output = gcnew List<P23::MetaTrader4::Manager::Contracts::TradeRecord^>(total);
	for (int i = 0; i < total; i++)
		output->Add(Convert(&result[i]));

	_manager->Manager->MemFree(result);
	Marshal::FreeHGlobal(IntPtr(f));
	Marshal::FreeHGlobal(IntPtr(r));

	return output;
}

int P23::MetaTrader4::Manager::ClrWrapper::BackupRestoreUsers(IList<P23::MetaTrader4::Manager::Contracts::UserRecord^>^ users)
{
	int total = users->Count;

	UserRecord* u = new UserRecord[total];
	for (int i = 0; i < total; i++)
		u[i] = *Convert(users[i]);

	int result = _manager->Manager->BackupRestoreUsers(u, total);

	delete[] u;

	return result;
}

IList<P23::MetaTrader4::Manager::Contracts::TradeRestoreResult^>^ P23::MetaTrader4::Manager::ClrWrapper::BackupRestoreOrders(IList<P23::MetaTrader4::Manager::Contracts::TradeRecord^>^ trades)
{
	int total = trades->Count;

	TradeRecord* t = new TradeRecord[total];
	for (int i = 0; i < total; i++)
		t[i] = *Convert(trades[i]);

	TradeRestoreResult* result = _manager->Manager->BackupRestoreOrders(t, &total);

	IList<P23::MetaTrader4::Manager::Contracts::TradeRestoreResult^>^ output = gcnew List<P23::MetaTrader4::Manager::Contracts::TradeRestoreResult^>(total);
	for (int i = 0; i < total; i++)
		output->Add(Convert(&result[i]));

	_manager->Manager->MemFree(result);
	delete[] t;

	return output;
}<|endoftext|>


<commit_before>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  @file JPetManager.cpp
 */

#include "./JPetManager.h"

#include <cassert>
#include <string>
#include <exception>

#include "../JPetLoggerInclude.h"
#include "../JPetCommonTools/JPetCommonTools.h"
#include "../DBHandler/HeaderFiles/DBHandler.h"
#include "../JPetCmdParser/JPetCmdParser.h"
#include "../JPetOptionsGenerator/JPetOptionsGenerator.h"

#include <TThread.h>

using namespace jpet_options_tools;

JPetManager::JPetManager()
{
  fTaskGeneratorChain = new TaskGeneratorChain;
}

JPetManager& JPetManager::getManager()
{
  static JPetManager instance;
  return instance;
}

bool JPetManager::areThreadsEnabled() const
{
  return fThreadsEnabled;
}

void JPetManager::setThreadsEnabled(bool enable)
{
  fThreadsEnabled = enable;
}

bool JPetManager::run(int argc, const char** argv)
{
  if (!parseCmdLine(argc, argv)) {
    ERROR("While parsing command line arguments");
    return false;
  }
  INFO( "======== Starting processing all tasks: " + JPetCommonTools::getTimeString() + " ========\n" );
  std::vector<JPetTaskChainExecutor*> executors;
  std::vector<TThread*> threads;
  auto inputDataSeq = 0;
  /// For every input option, new TaskChainExecutor is created, which creates the chain of previously
  /// registered tasks. The inputDataSeq is the identifier of given chain.
  for (auto opt : fOptions) {
    JPetTaskChainExecutor* executor = new JPetTaskChainExecutor(fTaskGeneratorChain, inputDataSeq, opt.second);
    executors.push_back(executor);
    if (areThreadsEnabled()) {
      auto thr = executor->run();
      if (thr) {
        threads.push_back(thr);
      } else {
        ERROR("thread pointer is null");
      }
    } else {
      if (!executor->process()) {
        ERROR("While running process");
        return false;
      }
    }
    inputDataSeq++;
  }
  if (areThreadsEnabled()) {
    for (auto thread : threads) {
      assert(thread);
      thread->Join();
    }
  }
  for (auto& executor : executors) {
    if (executor) {
      delete executor;
      executor = 0;
    }
  }
  INFO( "======== Finished processing all tasks: " + JPetCommonTools::getTimeString() + " ========\n" );
  return true;
}

bool JPetManager::parseCmdLine(int argc, const char** argv)
{
  try {
    JPetOptionsGenerator optionsGenerator;
    JPetCmdParser parser;
    auto optionsFromCmdLine = parser.parseCmdLineArgs(argc, argv);
    int numberOfRegisteredTasks = 1;
    if (fTaskGeneratorChain) {
      numberOfRegisteredTasks = fTaskGeneratorChain->size();
    }
    fOptions  = optionsGenerator.generateOptions(optionsFromCmdLine, numberOfRegisteredTasks);
  } catch (std::exception& e) {
    ERROR(e.what());
    return false;
  }
  return true;
}

JPetManager::~JPetManager()
{
  /// delete shared caches for paramBanks
  /// @todo I think that should be changed
  JPetDBParamGetter::clearParamCache();
}

void JPetManager::registerTask(const TaskGenerator& taskGen)
{
  assert(fTaskGeneratorChain);
  fTaskGeneratorChain->push_back(taskGen);
}

JPetManager::Options JPetManager::getOptions() const
{
  return fOptions;
}

/**
 * @brief Initialize connection to database if such connection is necessary
 *
 * @param configFilePath path to the config file with database connection details
 *
 * @return true if database connection was required and initialization was called,
 * false if database connection was not required and its initialization was skipped
 *
 * Database connection is only initialized if the user provided the run number
 * ("-i" option) and did not provide local database ("-l") at the same time.
 */
bool JPetManager::initDBConnection(const char* configFilePath)
{
  bool isDBrequired = false;

  if (fOptions.size() > 0) { // If at least one input file to process.
    auto optsVect = fOptions.begin()->second;
    if (optsVect.size() > 0) {
      auto opt = optsVect.front();
      if (getRunNumber(opt) >= 0) { // if run number is not default -1
        if (!isLocalDB(opt)) { // unless local DB file was provided
          isDBrequired = true;
        }
      }
    }
  }
  if (isDBrequired) {
    INFO("Attempting to set up connection to the database.");
    DB::SERVICES::DBHandler::createDBConnection(configFilePath);
  } else {
    INFO("Setting connection to database skipped.");
  }
  return isDBrequired;
}
<commit_msg>Add lambda to express adding scope module in JPetManager<commit_after>/**
 *  @copyright Copyright 2016 The J-PET Framework Authors. All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may find a copy of the License in the LICENCE file.
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  @file JPetManager.cpp
 */

#include "./JPetManager.h"

#include <cassert>
#include <string>
#include <exception>

#include "../JPetLoggerInclude.h"
#include "../JPetCommonTools/JPetCommonTools.h"
#include "../DBHandler/HeaderFiles/DBHandler.h"
#include "../JPetCmdParser/JPetCmdParser.h"
#include "../JPetScopeLoader/JPetScopeLoader.h"
#include "../JPetOptionsGenerator/JPetOptionsGenerator.h"

#include <TThread.h>

using namespace jpet_options_tools;

JPetManager::JPetManager()
{
  fTaskGeneratorChain = new TaskGeneratorChain;
}

JPetManager& JPetManager::getManager()
{
  static JPetManager instance;
  return instance;
}

bool JPetManager::areThreadsEnabled() const
{
  return fThreadsEnabled;
}

void JPetManager::setThreadsEnabled(bool enable)
{
  fThreadsEnabled = enable;
}

bool JPetManager::run(int argc, const char** argv)
{
  if (!parseCmdLine(argc, argv)) {
    ERROR("While parsing command line arguments");
    return false;
  }
  INFO( "======== Starting processing all tasks: " + JPetCommonTools::getTimeString() + " ========\n" );
  std::vector<JPetTaskChainExecutor*> executors;
  std::vector<TThread*> threads;
  auto inputDataSeq = 0;
  /// For every input option, new TaskChainExecutor is created, which creates the chain of previously
  /// registered tasks. The inputDataSeq is the identifier of given chain.
  for (auto opt : fOptions) {
    JPetTaskChainExecutor* executor = new JPetTaskChainExecutor(fTaskGeneratorChain, inputDataSeq, opt.second);
    executors.push_back(executor);
    if (areThreadsEnabled()) {
      auto thr = executor->run();
      if (thr) {
        threads.push_back(thr);
      } else {
        ERROR("thread pointer is null");
      }
    } else {
      if (!executor->process()) {
        ERROR("While running process");
        return false;
      }
    }
    inputDataSeq++;
  }
  if (areThreadsEnabled()) {
    for (auto thread : threads) {
      assert(thread);
      thread->Join();
    }
  }
  for (auto& executor : executors) {
    if (executor) {
      delete executor;
      executor = 0;
    }
  }
  INFO( "======== Finished processing all tasks: " + JPetCommonTools::getTimeString() + " ========\n" );
  return true;
}

bool JPetManager::parseCmdLine(int argc, const char** argv)
{
  auto addDefaultTasksFromOptions = [&](const boost::program_options::variables_map & optionsFromCmdLine) {
    auto it = optionsFromCmdLine.find("type");
    if (it != optionsFromCmdLine.end()) {
      if (boost::any_cast<std::string>(it->second.value()) == "scope") {
        auto task = []() {
          return new JPetScopeLoader(std::unique_ptr<JPetScopeTask>(new JPetScopeTask("JPetScopeReader")));
        };
        fTaskGeneratorChain->push_back(task);
      }
    }
  };

  try {
    JPetOptionsGenerator optionsGenerator;
    JPetCmdParser parser;
    auto optionsFromCmdLine = parser.parseCmdLineArgs(argc, argv);
    addDefaultTasksFromOptions(optionsFromCmdLine); /// Currently only scope task can be added.
    int numberOfRegisteredTasks = 1;
    if (fTaskGeneratorChain) {
      numberOfRegisteredTasks = fTaskGeneratorChain->size();
    }
    fOptions  = optionsGenerator.generateOptions(optionsFromCmdLine, numberOfRegisteredTasks);
  } catch (std::exception& e) {
    ERROR(e.what());
    return false;
  }
  return true;
}

//
JPetManager::~JPetManager()
{
  /// delete shared caches for paramBanks
  /// @todo I think that should be changed
  JPetDBParamGetter::clearParamCache();
}

void JPetManager::registerTask(const TaskGenerator& taskGen)
{
  assert(fTaskGeneratorChain);
  fTaskGeneratorChain->push_back(taskGen);
}

JPetManager::Options JPetManager::getOptions() const
{
  return fOptions;
}

/**
 * @brief Initialize connection to database if such connection is necessary
 *
 * @param configFilePath path to the config file with database connection details
 *
 * @return true if database connection was required and initialization was called,
 * false if database connection was not required and its initialization was skipped
 *
 * Database connection is only initialized if the user provided the run number
 * ("-i" option) and did not provide local database ("-l") at the same time.
 */
bool JPetManager::initDBConnection(const char* configFilePath)
{
  bool isDBrequired = false;

  if (fOptions.size() > 0) { // If at least one input file to process.
    auto optsVect = fOptions.begin()->second;
    if (optsVect.size() > 0) {
      auto opt = optsVect.front();
      if (getRunNumber(opt) >= 0) { // if run number is not default -1
        if (!isLocalDB(opt)) { // unless local DB file was provided
          isDBrequired = true;
        }
      }
    }
  }
  if (isDBrequired) {
    INFO("Attempting to set up connection to the database.");
    DB::SERVICES::DBHandler::createDBConnection(configFilePath);
  } else {
    INFO("Setting connection to database skipped.");
  }
  return isDBrequired;
}
<|endoftext|>


<commit_before>/*
    Yojimbo Client/Server Network Library.

    Copyright © 2016, The Network Protocol Company, Inc.

    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 copyright holder 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 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 "yojimbo_network.h"

#if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

    #define NOMINMAX
    #define _WINSOCK_DEPRECATED_NO_WARNINGS
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <ws2ipdef.h>
    #pragma comment( lib, "WS2_32.lib" )

    #ifdef SetPort
    #undef SetPort
    #endif // #ifdef SetPort

    #if YOJIMBO_SOCKETS
    #include <iphlpapi.h>
    #pragma comment( lib, "IPHLPAPI.lib" )
    #endif // #if YOJIMBO_SOCKETS

#elif YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_MAC || YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_UNIX

    #include <netdb.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <ifaddrs.h>
    #include <net/if.h>
    #include <fcntl.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <errno.h>

#endif

#include <memory.h>
#include <string.h>

namespace yojimbo
{
    static bool s_networkInitialized = false;

    bool InitializeNetwork()
    {
        assert( !s_networkInitialized );

#if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS
        WSADATA WsaData;
        const bool result = WSAStartup( MAKEWORD(2,2), &WsaData ) == NO_ERROR;
#else // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS
        const bool result = true;
#endif // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

        if ( result )
            s_networkInitialized = result;

        return result;
    }

    void ShutdownNetwork()
    {
        assert( s_networkInitialized );

#if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS
        WSACleanup();
#endif // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

        s_networkInitialized = false;
    }

    bool IsNetworkInitialized()
    {
        return s_networkInitialized;
    }

#if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

    #define WORKING_BUFFER_SIZE 15000
    #define MAX_TRIES 3

    void GetNetworkAddresses( Address * addresses, int & numAddresses, int maxAddresses )
    {
        assert( addresses );
        assert( maxAddresses >= 0 );

        numAddresses = 0;

        DWORD dwRetVal = 0;

        ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;

        ULONG family = AF_UNSPEC;

        PIP_ADAPTER_ADDRESSES pAddresses = NULL;
        ULONG outBufLen = 0;
        ULONG Iterations = 0;

        PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
        PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;

        outBufLen = WORKING_BUFFER_SIZE;

        do
        {
            pAddresses = (IP_ADAPTER_ADDRESSES*) malloc( outBufLen );
            if ( pAddresses == NULL )
                return;

            dwRetVal = GetAdaptersAddresses( family, flags, NULL, pAddresses, &outBufLen );

            if ( dwRetVal == ERROR_BUFFER_OVERFLOW )
            {
                free( pAddresses );
                pAddresses = NULL;
            }
            else
            {
                break;
            }

            Iterations++;

        } while ( ( dwRetVal == ERROR_BUFFER_OVERFLOW ) && ( Iterations < MAX_TRIES ) );

        if ( dwRetVal == NO_ERROR )
        {
            pCurrAddresses = pAddresses;

            while ( pCurrAddresses && numAddresses < maxAddresses )
            {
                if ( pCurrAddresses->OperStatus != IfOperStatusUp )
                    goto next;

                pUnicast = pCurrAddresses->FirstUnicastAddress;
                if (pUnicast != NULL)
                {
                    for ( int i = 0; pUnicast != NULL; i++ )
                    {
                        Address address( (sockaddr_storage*) pUnicast->Address.lpSockaddr );

                        if ( !address.IsValid() )
                            goto next_unicast;

                        if ( address.IsLoopback() )
                            goto next_unicast;

                        if ( address.GetType() == ADDRESS_IPV6 && !address.IsGlobalUnicast() )
                            goto next_unicast;

                        addresses[numAddresses++] = address;

                        if ( numAddresses >= maxAddresses )
                            break;

                    next_unicast:

                        pUnicast = pUnicast->Next;
                    }
                }

            next:

                pCurrAddresses = pCurrAddresses->Next;
            }
        }

        if ( pAddresses)
        {
            free( pAddresses );
        }
    }

    Address GetFirstNetworkAddress_IPV4()
    {
        DWORD dwRetVal = 0;

        ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;

        ULONG family = AF_INET;

        PIP_ADAPTER_ADDRESSES pAddresses = NULL;
        ULONG outBufLen = 0;
        ULONG Iterations = 0;

        PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
        PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;

        outBufLen = WORKING_BUFFER_SIZE;

        do
        {
            pAddresses = (IP_ADAPTER_ADDRESSES*) malloc( outBufLen );
            if ( pAddresses == NULL )
                return Address();

            dwRetVal = GetAdaptersAddresses( family, flags, NULL, pAddresses, &outBufLen );

            if ( dwRetVal == ERROR_BUFFER_OVERFLOW )
            {
                free( pAddresses );
                pAddresses = NULL;
            }
            else
            {
                break;
            }

            Iterations++;

        } while ( ( dwRetVal == ERROR_BUFFER_OVERFLOW ) && ( Iterations < MAX_TRIES ) );

        if ( dwRetVal == NO_ERROR )
        {
            pCurrAddresses = pAddresses;

            while ( pCurrAddresses )
            {
                if ( pCurrAddresses->OperStatus != IfOperStatusUp )
                    goto next;

                pUnicast = pCurrAddresses->FirstUnicastAddress;
                if (pUnicast != NULL)
                {
                    for ( int i = 0; pUnicast != NULL; i++ )
                    {
                        Address address( (sockaddr_storage*) pUnicast->Address.lpSockaddr );

                        if ( !address.IsValid() )
                            goto next_unicast;

                        if ( address.IsLoopback() )
                            goto next_unicast;

                        if ( pAddresses )
                            free( pAddresses );

                        return address;

                    next_unicast:

                        pUnicast = pUnicast->Next;
                    }
                }

            next:

                pCurrAddresses = pCurrAddresses->Next;
            }
        }

        if ( pAddresses)
        {
            free( pAddresses );
        }

        return Address();
    }

    Address GetFirstNetworkAddress_IPV6()
    {
        DWORD dwRetVal = 0;

        ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;

        ULONG family = AF_INET6;

        PIP_ADAPTER_ADDRESSES pAddresses = NULL;
        ULONG outBufLen = 0;
        ULONG Iterations = 0;

        PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
        PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;

        outBufLen = WORKING_BUFFER_SIZE;

        do
        {
            pAddresses = (IP_ADAPTER_ADDRESSES*) malloc( outBufLen );
            if ( pAddresses == NULL )
                return Address();

            dwRetVal = GetAdaptersAddresses( family, flags, NULL, pAddresses, &outBufLen );

            if ( dwRetVal == ERROR_BUFFER_OVERFLOW )
            {
                free( pAddresses );
                pAddresses = NULL;
            }
            else
            {
                break;
            }

            Iterations++;

        } while ( ( dwRetVal == ERROR_BUFFER_OVERFLOW ) && ( Iterations < MAX_TRIES ) );

        if ( dwRetVal == NO_ERROR )
        {
            pCurrAddresses = pAddresses;

            while ( pCurrAddresses )
            {
                if ( pCurrAddresses->OperStatus != IfOperStatusUp )
                    goto next;

                pUnicast = pCurrAddresses->FirstUnicastAddress;
                if (pUnicast != NULL)
                {
                    for ( int i = 0; pUnicast != NULL; i++ )
                    {
                        Address address( (sockaddr_storage*) pUnicast->Address.lpSockaddr );

                        if ( !address.IsValid() )
                            goto next_unicast;

                        if ( address.IsLoopback() )
                            goto next_unicast;

                        if ( !address.IsGlobalUnicast() )
                            goto next_unicast;

                        if ( pAddresses )
                            free( pAddresses );

                        return address;

                    next_unicast:

                        pUnicast = pUnicast->Next;
                    }
                }

            next:

                pCurrAddresses = pCurrAddresses->Next;
            }
        }

        if ( pAddresses)
        {
            free( pAddresses );
        }

        return Address();
    }

#elif YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_MAC || YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_UNIX // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

    void GetNetworkAddresses( Address * addresses, int & numAddresses, int maxAddresses )
    {
        assert( addresses );
        assert( maxAddresses >= 0 );

        struct ifaddrs *ifaddr, *ifa;

        numAddresses = 0;

        if ( getifaddrs( &ifaddr ) == -1 )
            return;

        for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next )
        {
            if ( numAddresses >= maxAddresses )
                break;

            if ( ifa->ifa_addr == NULL || ( ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6 ) )
                continue;

            if ( ( ifa->ifa_flags & IFF_RUNNING ) == 0 )
                continue;

            Address address( (sockaddr_storage*) ifa->ifa_addr );

            if ( !address.IsValid() )
                continue;

            if ( address.IsLoopback() )
                continue;

            if ( address.GetType() == ADDRESS_IPV6 && !address.IsGlobalUnicast() )
                continue;

            addresses[numAddresses++] = address;
        }

        freeifaddrs( ifaddr );
    }

    Address GetFirstNetworkAddress_IPV4()
    {
        struct ifaddrs *ifaddr, *ifa;

        if ( getifaddrs( &ifaddr ) == -1 )
            return Address();

        for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next )
        {
            if ( ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET )
                continue;

            if ( ( ifa->ifa_flags & IFF_RUNNING ) == 0 )
                continue;

            Address address( (sockaddr_storage*) ifa->ifa_addr );

            if ( !address.IsValid() )
                continue;

            if ( address.IsLoopback() )
                continue;

            assert( address.GetType() == ADDRESS_IPV4 );

            freeifaddrs( ifaddr );

            return address;
        }

        freeifaddrs( ifaddr );

        return Address();
    }

    Address GetFirstNetworkAddress_IPV6()
    {
        struct ifaddrs *ifaddr, *ifa;

        if ( getifaddrs( &ifaddr ) == -1 )
            return Address();

        for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next )
        {
            if ( ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6 )
                continue;

            if ( ( ifa->ifa_flags & IFF_RUNNING ) == 0 )
                continue;

            Address address( (sockaddr_storage*) ifa->ifa_addr );

            if ( !address.IsValid() )
                continue;

            if ( address.IsLoopback() )
                continue;

            assert( address.GetType() == ADDRESS_IPV6 );

            if ( !address.IsGlobalUnicast() )
                continue;

            freeifaddrs( ifaddr );

            return address;
        }

        freeifaddrs( ifaddr );

        return Address();
    }

#else // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

    void GetNetworkAddresses( Address * /*addresses*/, int & numAddresses, int /*maxAddresses*/ )
    {
        numAddresses = 0;
    }

    Address GetFirstNetworkAddress_IPV4()
    {
        return Address();
    }

    Address GetFirstNetworkAddress_IPV6()
    {
        return Address();
    }

#endif // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS
}
<commit_msg>tabs to spaces<commit_after>/*
    Yojimbo Client/Server Network Library.

    Copyright © 2016, The Network Protocol Company, Inc.

    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 copyright holder 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 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 "yojimbo_network.h"

#if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

    #define NOMINMAX
    #define _WINSOCK_DEPRECATED_NO_WARNINGS
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <ws2ipdef.h>
    #pragma comment( lib, "WS2_32.lib" )

    #ifdef SetPort
    #undef SetPort
    #endif // #ifdef SetPort

    #if YOJIMBO_SOCKETS
    #include <iphlpapi.h>
    #pragma comment( lib, "IPHLPAPI.lib" )
    #endif // #if YOJIMBO_SOCKETS

#elif YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_MAC || YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_UNIX

    #include <netdb.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <ifaddrs.h>
    #include <net/if.h>
    #include <fcntl.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <errno.h>

#endif

#include <memory.h>
#include <string.h>

namespace yojimbo
{
    static bool s_networkInitialized = false;

    bool InitializeNetwork()
    {
        assert( !s_networkInitialized );

#if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS
        WSADATA WsaData;
        const bool result = WSAStartup( MAKEWORD(2,2), &WsaData ) == NO_ERROR;
#else // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS
        const bool result = true;
#endif // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

        if ( result )
            s_networkInitialized = result;

        return result;
    }

    void ShutdownNetwork()
    {
        assert( s_networkInitialized );

#if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS
        WSACleanup();
#endif // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

        s_networkInitialized = false;
    }

    bool IsNetworkInitialized()
    {
        return s_networkInitialized;
    }

#if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

    #define WORKING_BUFFER_SIZE 15000
    #define MAX_TRIES 3

    void GetNetworkAddresses( Address * addresses, int & numAddresses, int maxAddresses )
    {
        assert( addresses );
        assert( maxAddresses >= 0 );

        numAddresses = 0;

        DWORD dwRetVal = 0;

        ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;

        ULONG family = AF_UNSPEC;

        PIP_ADAPTER_ADDRESSES pAddresses = NULL;
        ULONG outBufLen = 0;
        ULONG Iterations = 0;

        PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
        PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;

        outBufLen = WORKING_BUFFER_SIZE;

        do
        {
            pAddresses = (IP_ADAPTER_ADDRESSES*) malloc( outBufLen );
            if ( pAddresses == NULL )
                return;

            dwRetVal = GetAdaptersAddresses( family, flags, NULL, pAddresses, &outBufLen );

            if ( dwRetVal == ERROR_BUFFER_OVERFLOW )
            {
                free( pAddresses );
                pAddresses = NULL;
            }
            else
            {
                break;
            }

            Iterations++;

        } while ( ( dwRetVal == ERROR_BUFFER_OVERFLOW ) && ( Iterations < MAX_TRIES ) );

        if ( dwRetVal == NO_ERROR )
        {
            pCurrAddresses = pAddresses;

            while ( pCurrAddresses && numAddresses < maxAddresses )
            {
                if ( pCurrAddresses->OperStatus != IfOperStatusUp )
                    goto next;

                pUnicast = pCurrAddresses->FirstUnicastAddress;
                if (pUnicast != NULL)
                {
                    for ( int i = 0; pUnicast != NULL; i++ )
                    {
                        Address address( (sockaddr_storage*) pUnicast->Address.lpSockaddr );

                        if ( !address.IsValid() )
                            goto next_unicast;

                        if ( address.IsLoopback() )
                            goto next_unicast;

                        if ( address.GetType() == ADDRESS_IPV6 && !address.IsGlobalUnicast() )
                            goto next_unicast;

                        addresses[numAddresses++] = address;

                        if ( numAddresses >= maxAddresses )
                            break;

                    next_unicast:

                        pUnicast = pUnicast->Next;
                    }
                }

            next:

                pCurrAddresses = pCurrAddresses->Next;
            }
        }

        if ( pAddresses)
        {
            free( pAddresses );
        }
    }

    Address GetFirstNetworkAddress_IPV4()
    {
        DWORD dwRetVal = 0;

        ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;

        ULONG family = AF_INET;

        PIP_ADAPTER_ADDRESSES pAddresses = NULL;
        ULONG outBufLen = 0;
        ULONG Iterations = 0;

        PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
        PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;

        outBufLen = WORKING_BUFFER_SIZE;

        do
        {
            pAddresses = (IP_ADAPTER_ADDRESSES*) malloc( outBufLen );
            if ( pAddresses == NULL )
                return Address();

            dwRetVal = GetAdaptersAddresses( family, flags, NULL, pAddresses, &outBufLen );

            if ( dwRetVal == ERROR_BUFFER_OVERFLOW )
            {
                free( pAddresses );
                pAddresses = NULL;
            }
            else
            {
                break;
            }

            Iterations++;

        } while ( ( dwRetVal == ERROR_BUFFER_OVERFLOW ) && ( Iterations < MAX_TRIES ) );

        if ( dwRetVal == NO_ERROR )
        {
            pCurrAddresses = pAddresses;

            while ( pCurrAddresses )
            {
                if ( pCurrAddresses->OperStatus != IfOperStatusUp )
                    goto next;

                pUnicast = pCurrAddresses->FirstUnicastAddress;

                if ( pUnicast != NULL )
                {
                    for ( int i = 0; pUnicast != NULL; i++ )
                    {
                        Address address( (sockaddr_storage*) pUnicast->Address.lpSockaddr );

                        if ( !address.IsValid() )
                            goto next_unicast;

                        if ( address.IsLoopback() )
                            goto next_unicast;

                        if ( pAddresses )
                            free( pAddresses );

                        return address;

                    next_unicast:

                        pUnicast = pUnicast->Next;
                    }
                }

            next:

                pCurrAddresses = pCurrAddresses->Next;
            }
        }

        if ( pAddresses)
        {
            free( pAddresses );
        }

        return Address();
    }

    Address GetFirstNetworkAddress_IPV6()
    {
        DWORD dwRetVal = 0;

        ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;

        ULONG family = AF_INET6;

        PIP_ADAPTER_ADDRESSES pAddresses = NULL;
        ULONG outBufLen = 0;
        ULONG Iterations = 0;

        PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
        PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;

        outBufLen = WORKING_BUFFER_SIZE;

        do
        {
            pAddresses = (IP_ADAPTER_ADDRESSES*) malloc( outBufLen );
            if ( pAddresses == NULL )
                return Address();

            dwRetVal = GetAdaptersAddresses( family, flags, NULL, pAddresses, &outBufLen );

            if ( dwRetVal == ERROR_BUFFER_OVERFLOW )
            {
                free( pAddresses );
                pAddresses = NULL;
            }
            else
            {
                break;
            }

            Iterations++;

        } while ( ( dwRetVal == ERROR_BUFFER_OVERFLOW ) && ( Iterations < MAX_TRIES ) );

        if ( dwRetVal == NO_ERROR )
        {
            pCurrAddresses = pAddresses;

            while ( pCurrAddresses )
            {
                if ( pCurrAddresses->OperStatus != IfOperStatusUp )
                    goto next;

                pUnicast = pCurrAddresses->FirstUnicastAddress;
                if (pUnicast != NULL)
                {
                    for ( int i = 0; pUnicast != NULL; i++ )
                    {
                        Address address( (sockaddr_storage*) pUnicast->Address.lpSockaddr );

                        if ( !address.IsValid() )
                            goto next_unicast;

                        if ( address.IsLoopback() )
                            goto next_unicast;

                        if ( !address.IsGlobalUnicast() )
                            goto next_unicast;

                        if ( pAddresses )
                            free( pAddresses );

                        return address;

                    next_unicast:

                        pUnicast = pUnicast->Next;
                    }
                }

            next:

                pCurrAddresses = pCurrAddresses->Next;
            }
        }

        if ( pAddresses)
        {
            free( pAddresses );
        }

        return Address();
    }

#elif YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_MAC || YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_UNIX // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

    void GetNetworkAddresses( Address * addresses, int & numAddresses, int maxAddresses )
    {
        assert( addresses );
        assert( maxAddresses >= 0 );

        struct ifaddrs *ifaddr, *ifa;

        numAddresses = 0;

        if ( getifaddrs( &ifaddr ) == -1 )
            return;

        for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next )
        {
            if ( numAddresses >= maxAddresses )
                break;

            if ( ifa->ifa_addr == NULL || ( ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6 ) )
                continue;

            if ( ( ifa->ifa_flags & IFF_RUNNING ) == 0 )
                continue;

            Address address( (sockaddr_storage*) ifa->ifa_addr );

            if ( !address.IsValid() )
                continue;

            if ( address.IsLoopback() )
                continue;

            if ( address.GetType() == ADDRESS_IPV6 && !address.IsGlobalUnicast() )
                continue;

            addresses[numAddresses++] = address;
        }

        freeifaddrs( ifaddr );
    }

    Address GetFirstNetworkAddress_IPV4()
    {
        struct ifaddrs *ifaddr, *ifa;

        if ( getifaddrs( &ifaddr ) == -1 )
            return Address();

        for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next )
        {
            if ( ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET )
                continue;

            if ( ( ifa->ifa_flags & IFF_RUNNING ) == 0 )
                continue;

            Address address( (sockaddr_storage*) ifa->ifa_addr );

            if ( !address.IsValid() )
                continue;

            if ( address.IsLoopback() )
                continue;

            assert( address.GetType() == ADDRESS_IPV4 );

            freeifaddrs( ifaddr );

            return address;
        }

        freeifaddrs( ifaddr );

        return Address();
    }

    Address GetFirstNetworkAddress_IPV6()
    {
        struct ifaddrs *ifaddr, *ifa;

        if ( getifaddrs( &ifaddr ) == -1 )
            return Address();

        for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next )
        {
            if ( ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6 )
                continue;

            if ( ( ifa->ifa_flags & IFF_RUNNING ) == 0 )
                continue;

            Address address( (sockaddr_storage*) ifa->ifa_addr );

            if ( !address.IsValid() )
                continue;

            if ( address.IsLoopback() )
                continue;

            assert( address.GetType() == ADDRESS_IPV6 );

            if ( !address.IsGlobalUnicast() )
                continue;

            freeifaddrs( ifaddr );

            return address;
        }

        freeifaddrs( ifaddr );

        return Address();
    }

#else // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS

    void GetNetworkAddresses( Address * /*addresses*/, int & numAddresses, int /*maxAddresses*/ )
    {
        numAddresses = 0;
    }

    Address GetFirstNetworkAddress_IPV4()
    {
        return Address();
    }

    Address GetFirstNetworkAddress_IPV6()
    {
        return Address();
    }

#endif // #if YOJIMBO_PLATFORM == YOJIMBO_PLATFORM_WINDOWS
}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s

namespace PR10622 {
  struct foo {
    const int first;
    foo(const foo&) = default;
  };
  void find_or_insert(const foo& __obj) {
    foo x(__obj);
  }
}
<commit_msg>Expand test of C++0x [class.copymove]p15 to make sure we're actually calling the copy constructor of a base/member from an explicitly-defaulted copy constructor, rather than the default constructor<commit_after>// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s

namespace PR10622 {
  struct foo {
    const int first;
    foo(const foo&) = default;
  };
  void find_or_insert(const foo& __obj) {
    foo x(__obj);
  }

  struct bar : foo {
    bar(const bar&) = default;
  };
  void test_bar(const bar &obj) {
    bar obj2(obj);
  }
}
<|endoftext|>