text:
/**
 * @file llxuiparser.cpp
 * @brief Utility functions for handling XUI structures in XML
 *
 * $LicenseInfo:firstyear=2003&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "linden_common.h"

#include "llxuiparser.h"

#include "llxmlnode.h"
#include "llfasttimer.h"
#ifdef LL_USESYSTEMLIBS
#include <expat.h>
#else
#include "expat/expat.h"
#endif

#include <fstream>
#include <boost/tokenizer.hpp>
#include <boost/bind.hpp>
//#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/classic_core.hpp>

#include "lluicolor.h"
#include "v3math.h"
using namespace BOOST_SPIRIT_CLASSIC_NS;

const S32 MAX_STRING_ATTRIBUTE_SIZE = 40;

static 	LLInitParam::Parser::parser_read_func_map_t sXSDReadFuncs;
static 	LLInitParam::Parser::parser_write_func_map_t sXSDWriteFuncs;
static 	LLInitParam::Parser::parser_inspect_func_map_t sXSDInspectFuncs;

static 	LLInitParam::Parser::parser_read_func_map_t sSimpleXUIReadFuncs;
static 	LLInitParam::Parser::parser_write_func_map_t sSimpleXUIWriteFuncs;
static 	LLInitParam::Parser::parser_inspect_func_map_t sSimpleXUIInspectFuncs;

const char* NO_VALUE_MARKER = "no_value";

struct MaxOccursValues : public LLInitParam::TypeValuesHelper<U32, MaxOccursValues>
{
	static void declareValues()
	{
		declare("unbounded", U32_MAX);
	}
};

struct Occurs : public LLInitParam::Block<Occurs>
{
	Optional<U32>					minOccurs;
	Optional<U32, MaxOccursValues>	maxOccurs;

	Occurs()
	:	minOccurs("minOccurs", 0),
		maxOccurs("maxOccurs", U32_MAX)

	{}
};

typedef enum
{
	USE_REQUIRED,
	USE_OPTIONAL
} EUse;

namespace LLInitParam
{
	template<>
	struct TypeValues<EUse> : public TypeValuesHelper<EUse>
	{
		static void declareValues()
		{
			declare("required", USE_REQUIRED);
			declare("optional", USE_OPTIONAL);
		}
	};
}

struct Element;
struct Group;
struct Sequence;

struct All : public LLInitParam::Block<All, Occurs>
{
	Multiple< Lazy<Element, IS_A_BLOCK> > elements;

	All()
	:	elements("element")
	{
		maxOccurs = 1;
	}
};

struct Attribute : public LLInitParam::Block<Attribute>
{
	Mandatory<std::string>	name,
							type;
	Mandatory<EUse>			use;

	Attribute()
	:	name("name"),
		type("type"),
		use("use")
	{}
};

struct Any : public LLInitParam::Block<Any, Occurs>
{
	Optional<std::string> _namespace;

	Any()
	:	_namespace("namespace")
	{}
};

struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs>
{
	Alternative< Lazy<Element, IS_A_BLOCK> >	element;
	Alternative< Lazy<Group, IS_A_BLOCK> >		group;
	Alternative< Lazy<Choice, IS_A_BLOCK> >		choice;
	Alternative< Lazy<Sequence, IS_A_BLOCK> >	sequence;
	Alternative< Lazy<Any> >					any;

	Choice()
	:	element("element"),
		group("group"),
		choice("choice"),
		sequence("sequence"),
		any("any")
	{}

};

struct Sequence : public LLInitParam::ChoiceBlock<Sequence, Occurs>
{
	Alternative< Lazy<Element, IS_A_BLOCK> >	element;
	Alternative< Lazy<Group, IS_A_BLOCK> >		group;
	Alternative< Lazy<Choice> >					choice;
	Alternative< Lazy<Sequence, IS_A_BLOCK> >	sequence;
	Alternative< Lazy<Any> >					any;
};

struct GroupContents : public LLInitParam::ChoiceBlock<GroupContents, Occurs>
{
	Alternative<All>		all;
	Alternative<Choice>		choice;
	Alternative<Sequence>	sequence;

	GroupContents()
	:	all("all"),
		choice("choice"),
		sequence("sequence")
	{}
};

struct Group : public LLInitParam::Block<Group, GroupContents>
{
	Optional<std::string>	name,
							ref;

	Group()
	:	name("name"),
		ref("ref")
	{}
};

struct Restriction : public LLInitParam::Block<Restriction>
{
};

struct Extension : public LLInitParam::Block<Extension>
{
};

struct SimpleContent : public LLInitParam::ChoiceBlock<SimpleContent>
{
	Alternative<Restriction> restriction;
	Alternative<Extension> extension;

	SimpleContent()
	:	restriction("restriction"),
		extension("extension")
	{}
};

struct SimpleType : public LLInitParam::Block<SimpleType>
{
	// TODO
};

struct ComplexContent : public LLInitParam::Block<ComplexContent, SimpleContent>
{
	Optional<bool> mixed;

	ComplexContent()
	:	mixed("mixed", true)
	{}
};

struct ComplexTypeContents : public LLInitParam::ChoiceBlock<ComplexTypeContents>
{
	Alternative<SimpleContent>	simple_content;
	Alternative<ComplexContent> complex_content;
	Alternative<Group>			group;
	Alternative<All>			all;
	Alternative<Choice>			choice;
	Alternative<Sequence>		sequence;

	ComplexTypeContents()
	:	simple_content("simpleContent"),
		complex_content("complexContent"),
		group("group"),
		all("all"),
		choice("choice"),
		sequence("sequence")
	{}
};

struct ComplexType : public LLInitParam::Block<ComplexType, ComplexTypeContents>
{
	Optional<std::string>			name;
	Optional<bool>					mixed;

	Multiple<Attribute>				attribute;
	Multiple< Lazy<Element, IS_A_BLOCK > >			elements;

	ComplexType()
	:	name("name"),
		attribute("xs:attribute"),
		elements("xs:element"),
		mixed("mixed")
	{
	}
};

struct ElementContents : public LLInitParam::ChoiceBlock<ElementContents, Occurs>
{
	Alternative<SimpleType>		simpleType;
	Alternative<ComplexType>	complexType;

	ElementContents()
	:	simpleType("simpleType"),
		complexType("complexType")
	{}
};

struct Element : public LLInitParam::Block<Element, ElementContents>
{
	Optional<std::string>	name,
							ref,
							type;

	Element()
	:	name("xs:name"),
		ref("xs:ref"),
		type("xs:type")
	{}
};

struct Schema : public LLInitParam::Block<Schema>
{
private:
	Mandatory<std::string>	targetNamespace,
							xmlns,
							xs;

public:
	Optional<std::string>	attributeFormDefault,
							elementFormDefault;

	Mandatory<Element>		root_element;

	void setNameSpace(const std::string& ns) {targetNamespace = ns; xmlns = ns;}

	Schema(const std::string& ns = LLStringUtil::null)
	:	attributeFormDefault("attributeFormDefault"),
		elementFormDefault("elementFormDefault"),
		xs("xmlns:xs"),
		targetNamespace("targetNamespace"),
		xmlns("xmlns"),
		root_element("xs:element")
	{
		attributeFormDefault = "unqualified";
		elementFormDefault = "qualified";
		xs = "http://www.w3.org/2001/XMLSchema";
		if (!ns.empty())
		{
			setNameSpace(ns);
		};
	}
};

//
// LLXSDWriter
//
LLXSDWriter::LLXSDWriter()
: Parser(sXSDReadFuncs, sXSDWriteFuncs, sXSDInspectFuncs)
{
	registerInspectFunc<bool>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:boolean", _1, _2, _3, _4));
	registerInspectFunc<std::string>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
	registerInspectFunc<U8>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedByte", _1, _2, _3, _4));
	registerInspectFunc<S8>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedByte", _1, _2, _3, _4));
	registerInspectFunc<U16>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedShort", _1, _2, _3, _4));
	registerInspectFunc<S16>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedShort", _1, _2, _3, _4));
	registerInspectFunc<U32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedInt", _1, _2, _3, _4));
	registerInspectFunc<S32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:integer", _1, _2, _3, _4));
	registerInspectFunc<F32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:float", _1, _2, _3, _4));
	registerInspectFunc<F64>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:double", _1, _2, _3, _4));
	registerInspectFunc<LLColor4>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
	registerInspectFunc<LLUIColor>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
	registerInspectFunc<LLUUID>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
	registerInspectFunc<LLSD>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
}

LLXSDWriter::~LLXSDWriter() {}

void LLXSDWriter::writeXSD(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace)
{
	Schema schema(xml_namespace);

	schema.root_element.name = type_name;
	Choice& choice = schema.root_element.complexType.choice;

	choice.minOccurs = 0;
	choice.maxOccurs = "unbounded";

	mSchemaNode = node;
	//node->setName("xs:schema");
	//node->createChild("attributeFormDefault", true)->setStringValue("unqualified");
	//node->createChild("elementFormDefault", true)->setStringValue("qualified");
	//node->createChild("targetNamespace", true)->setStringValue(xml_namespace);
	//node->createChild("xmlns:xs", true)->setStringValue("http://www.w3.org/2001/XMLSchema");
	//node->createChild("xmlns", true)->setStringValue(xml_namespace);

	//node = node->createChild("xs:complexType", false);
	//node->createChild("name", true)->setStringValue(type_name);
	//node->createChild("mixed", true)->setStringValue("true");

	//mAttributeNode = node;
	//mElementNode = node->createChild("xs:choice", false);
	//mElementNode->createChild("minOccurs", true)->setStringValue("0");
	//mElementNode->createChild("maxOccurs", true)->setStringValue("unbounded");
	block.inspectBlock(*this);

	// duplicate element choices
	LLXMLNodeList children;
	mElementNode->getChildren("xs:element", children, FALSE);
	for (LLXMLNodeList::iterator child_it = children.begin(); child_it != children.end(); ++child_it)
	{
		LLXMLNodePtr child_copy = child_it->second->deepCopy();
		std::string child_name;
		child_copy->getAttributeString("name", child_name);
		child_copy->setAttributeString("name", type_name + "." + child_name);
		mElementNode->addChild(child_copy);
	}

	LLXMLNodePtr element_declaration_node = mSchemaNode->createChild("xs:element", false);
	element_declaration_node->createChild("name", true)->setStringValue(type_name);
	element_declaration_node->createChild("type", true)->setStringValue(type_name);
}

void LLXSDWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values)
{
	name_stack_t non_empty_names;
	std::string attribute_name;
	for (name_stack_t::const_iterator it = stack.begin();
		it != stack.end();
		++it)
	{
		const std::string& name = it->first;
		if (!name.empty())
		{
			non_empty_names.push_back(*it);
		}
	}

	for (name_stack_t::const_iterator it = non_empty_names.begin();
		it != non_empty_names.end();
		++it)
	{
		if (!attribute_name.empty())
		{
			attribute_name += ".";
		}
		attribute_name += it->first;
	}

	// only flag non-nested attributes as mandatory, nested attributes have variant syntax
	// that can't be properly constrained in XSD
	// e.g. <foo mandatory.value="bar"/> vs <foo><mandatory value="bar"/></foo>
	bool attribute_mandatory = min_count == 1 && max_count == 1 && non_empty_names.size() == 1;

	// don't bother supporting "Multiple" params as xml attributes
	if (max_count <= 1)
	{
		// add compound attribute to root node
		addAttributeToSchema(mAttributeNode, attribute_name, type, attribute_mandatory, possible_values);
	}

	// now generated nested elements for compound attributes
	if (non_empty_names.size() > 1 && !attribute_mandatory)
	{
		std::string element_name;

		// traverse all but last element, leaving that as an attribute name
		name_stack_t::const_iterator end_it = non_empty_names.end();
		end_it--;

		for (name_stack_t::const_iterator it = non_empty_names.begin();
			it != end_it;
			++it)
		{
			if (it != non_empty_names.begin())
			{
				element_name += ".";
			}
			element_name += it->first;
		}

		std::string short_attribute_name = non_empty_names.back().first;

		LLXMLNodePtr complex_type_node;

		// find existing element node here, starting at tail of child list
		if (mElementNode->mChildren.notNull())
		{
			for(LLXMLNodePtr element = mElementNode->mChildren->tail;
				element.notNull();
				element = element->mPrev)
			{
				std::string name;
				if(element->getAttributeString("name", name) && name == element_name)
				{
					complex_type_node = element->mChildren->head;
					break;
				}
			}
		}
		//create complex_type node
		//
		//<xs:element
        //    maxOccurs="1"
        //    minOccurs="0"
        //    name="name">
        //       <xs:complexType>
        //       </xs:complexType>
        //</xs:element>
		if(complex_type_node.isNull())
		{
			complex_type_node = mElementNode->createChild("xs:element", false);

			complex_type_node->createChild("minOccurs", true)->setIntValue(min_count);
			complex_type_node->createChild("maxOccurs", true)->setIntValue(max_count);
			complex_type_node->createChild("name",		true)->setStringValue(element_name);
			complex_type_node = complex_type_node->createChild("xs:complexType", false);
		}

		addAttributeToSchema(complex_type_node, short_attribute_name, type, false, possible_values);
	}
}

void LLXSDWriter::addAttributeToSchema(LLXMLNodePtr type_declaration_node, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector<std::string>* possible_values)
{
	if (!attribute_name.empty())
	{
		LLXMLNodePtr new_enum_type_node;
		if (possible_values != NULL)
		{
			// custom attribute type, for example
			//<xs:simpleType>
			 // <xs:restriction
			 //    base="xs:string">
			 //     <xs:enumeration
			 //      value="a" />
			 //     <xs:enumeration
			 //      value="b" />
			 //   </xs:restriction>
			 // </xs:simpleType>
			new_enum_type_node = new LLXMLNode("xs:simpleType", false);

			LLXMLNodePtr restriction_node = new_enum_type_node->createChild("xs:restriction", false);
			restriction_node->createChild("base", true)->setStringValue("xs:string");

			for (std::vector<std::string>::const_iterator it = possible_values->begin();
				it != possible_values->end();
				++it)
			{
				LLXMLNodePtr enum_node = restriction_node->createChild("xs:enumeration", false);
				enum_node->createChild("value", true)->setStringValue(*it);
			}
		}

		string_set_t& attributes_written = mAttributesWritten[type_declaration_node];

		string_set_t::iterator found_it = attributes_written.lower_bound(attribute_name);

		// attribute not yet declared
		if (found_it == attributes_written.end() || attributes_written.key_comp()(attribute_name, *found_it))
		{
			attributes_written.insert(found_it, attribute_name);

			LLXMLNodePtr attribute_node = type_declaration_node->createChild("xs:attribute", false);

			// attribute name
			attribute_node->createChild("name", true)->setStringValue(attribute_name);

			if (new_enum_type_node.notNull())
			{
				attribute_node->addChild(new_enum_type_node);
			}
			else
			{
				// simple attribute type
				attribute_node->createChild("type", true)->setStringValue(type);
			}

			// required or optional
			attribute_node->createChild("use", true)->setStringValue(mandatory ? "required" : "optional");
		}
		 // attribute exists...handle collision of same name attributes with potentially different types
		else
		{
			LLXMLNodePtr attribute_declaration;
			if (type_declaration_node.notNull())
			{
				for(LLXMLNodePtr node = type_declaration_node->mChildren->tail;
					node.notNull();
					node = node->mPrev)
				{
					std::string name;
					if (node->getAttributeString("name", name) && name == attribute_name)
					{
						attribute_declaration = node;
						break;
					}
				}
			}

			bool new_type_is_enum = new_enum_type_node.notNull();
			bool existing_type_is_enum = !attribute_declaration->hasAttribute("type");

			// either type is enum, revert to string in collision
			// don't bother to check for enum equivalence
			if (new_type_is_enum || existing_type_is_enum)
			{
				if (attribute_declaration->hasAttribute("type"))
				{
					attribute_declaration->setAttributeString("type", "xs:string");
				}
				else
				{
					attribute_declaration->createChild("type", true)->setStringValue("xs:string");
				}
				attribute_declaration->deleteChildren("xs:simpleType");
			}
			else
			{
				// check for collision of different standard types
				std::string existing_type;
				attribute_declaration->getAttributeString("type", existing_type);
				// if current type is not the same as the new type, revert to strnig
				if (existing_type != type)
				{
					// ...than use most general type, string
					attribute_declaration->setAttributeString("type", "string");
				}
			}
		}
	}
}

//
// LLXUIXSDWriter
//
void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& path, const LLInitParam::BaseBlock& block)
{
	std::string file_name(path);
	file_name += type_name + ".xsd";
	LLXMLNodePtr root_nodep = new LLXMLNode();

	LLXSDWriter::writeXSD(type_name, root_nodep, block, "http://www.lindenlab.com/xui");

	// add includes for all possible children
	const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name);
	const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type);

	// add choices for valid children
	if (widget_registryp)
	{
		// add include declarations for all valid children
		for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
		     it != widget_registryp->currentRegistrar().endItems();
		     ++it)
		{
			std::string widget_name = it->first;
			if (widget_name == type_name)
			{
				continue;
			}
			LLXMLNodePtr nodep = new LLXMLNode("xs:include", false);
			nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd");

			// add to front of schema
			mSchemaNode->addChild(nodep);
		}

		for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
			it != widget_registryp->currentRegistrar().endItems();
			++it)
		{
			std::string widget_name = it->first;
			//<xs:element name="widget_name" type="widget_name">
			LLXMLNodePtr widget_node = mElementNode->createChild("xs:element", false);
			widget_node->createChild("name", true)->setStringValue(widget_name);
			widget_node->createChild("type", true)->setStringValue(widget_name);
		}
	}

	LLFILE* xsd_file = LLFile::fopen(file_name.c_str(), "w");
	LLXMLNode::writeHeaderToFile(xsd_file);
	root_nodep->writeToFile(xsd_file);
	fclose(xsd_file);
}

static 	LLInitParam::Parser::parser_read_func_map_t sXUIReadFuncs;
static 	LLInitParam::Parser::parser_write_func_map_t sXUIWriteFuncs;
static 	LLInitParam::Parser::parser_inspect_func_map_t sXUIInspectFuncs;

//
// LLXUIParser
//
LLXUIParser::LLXUIParser()
:	Parser(sXUIReadFuncs, sXUIWriteFuncs, sXUIInspectFuncs),
	mCurReadDepth(0)
{
	if (sXUIReadFuncs.empty())
	{
		registerParserFuncs<LLInitParam::Flag>(readFlag, writeFlag);
		registerParserFuncs<bool>(readBoolValue, writeBoolValue);
		registerParserFuncs<std::string>(readStringValue, writeStringValue);
		registerParserFuncs<U8>(readU8Value, writeU8Value);
		registerParserFuncs<S8>(readS8Value, writeS8Value);
		registerParserFuncs<U16>(readU16Value, writeU16Value);
		registerParserFuncs<S16>(readS16Value, writeS16Value);
		registerParserFuncs<U32>(readU32Value, writeU32Value);
		registerParserFuncs<S32>(readS32Value, writeS32Value);
		registerParserFuncs<F32>(readF32Value, writeF32Value);
		registerParserFuncs<F64>(readF64Value, writeF64Value);
		registerParserFuncs<LLVector3>(readVector3Value, writeVector3Value);
		registerParserFuncs<LLColor4>(readColor4Value, writeColor4Value);
		registerParserFuncs<LLUIColor>(readUIColorValue, writeUIColorValue);
		registerParserFuncs<LLUUID>(readUUIDValue, writeUUIDValue);
		registerParserFuncs<LLSD>(readSDValue, writeSDValue);
	}
}

static LLTrace::BlockTimerStatHandle FTM_PARSE_XUI("XUI Parsing");
const LLXMLNodePtr DUMMY_NODE = new LLXMLNode();

void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename, bool silent)
{
	LL_RECORD_BLOCK_TIME(FTM_PARSE_XUI);
	mNameStack.clear();
	mRootNodeName = node->getName()->mString;
	mCurFileName = filename;
	mCurReadDepth = 0;
	setParseSilently(silent);

	if (node.isNull())
	{
		parserWarning("Invalid node");
	}
	else
	{
		readXUIImpl(node, block);
	}
}

bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
{
	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
	boost::char_separator<char> sep(".");

	bool values_parsed = false;
	bool silent = mCurReadDepth > 0;

	if (nodep->getFirstChild().isNull()
		&& nodep->mAttributes.empty()
		&& nodep->getSanitizedValue().empty())
	{
		// empty node, just parse as flag
		mCurReadNode = DUMMY_NODE;
		return block.submitValue(mNameStack, *this, silent);
	}

	// submit attributes for current node
	values_parsed |= readAttributes(nodep, block);

	// treat text contents of xml node as "value" parameter
	std::string text_contents = nodep->getSanitizedValue();
	if (!text_contents.empty())
	{
		mCurReadNode = nodep;
		mNameStack.push_back(std::make_pair(std::string("value"), true));
		// child nodes are not necessarily valid parameters (could be a child widget)
		// so don't complain once we've recursed
		if (!block.submitValue(mNameStack, *this, true))
		{
			mNameStack.pop_back();
			block.submitValue(mNameStack, *this, silent);
		}
		else
		{
			mNameStack.pop_back();
		}
	}

	// then traverse children
	// child node must start with last name of parent node (our "scope")
	// for example: "<button><button.param nested_param1="foo"><param.nested_param2 nested_param3="bar"/></button.param></button>"
	// which equates to the following nesting:
	// button
	//     param
	//         nested_param1
	//         nested_param2
	//             nested_param3
	mCurReadDepth++;
	for(LLXMLNodePtr childp = nodep->getFirstChild(); childp.notNull();)
	{
		std::string child_name(childp->getName()->mString);
		S32 num_tokens_pushed = 0;

		// for non "dotted" child nodes	check to see if child node maps to another widget type
		// and if not, treat as a child element of the current node
		// e.g. <button><rect left="10"/></button> will interpret <rect> as "button.rect"
		// since there is no widget named "rect"
		if (child_name.find(".") == std::string::npos)
		{
			mNameStack.push_back(std::make_pair(child_name, true));
			num_tokens_pushed++;
		}
		else
		{
			// parse out "dotted" name into individual tokens
			tokenizer name_tokens(child_name, sep);

			tokenizer::iterator name_token_it = name_tokens.begin();
			if(name_token_it == name_tokens.end())
			{
				childp = childp->getNextSibling();
				continue;
			}

			// check for proper nesting
			if (mNameStack.empty())
			{
				if (*name_token_it != mRootNodeName)
				{
					childp = childp->getNextSibling();
					continue;
				}
			}
			else if(mNameStack.back().first != *name_token_it)
			{
				childp = childp->getNextSibling();
				continue;
			}

			// now ignore first token
			++name_token_it;

			// copy remaining tokens on to our running token list
			for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
			{
				mNameStack.push_back(std::make_pair(*token_to_push, true));
				num_tokens_pushed++;
			}
		}

		// recurse and visit children XML nodes
		if(readXUIImpl(childp, block))
		{
			// child node successfully parsed, remove from DOM

			values_parsed = true;
			LLXMLNodePtr node_to_remove = childp;
			childp = childp->getNextSibling();

			nodep->deleteChild(node_to_remove);
		}
		else
		{
			childp = childp->getNextSibling();
		}

		while(num_tokens_pushed-- > 0)
		{
			mNameStack.pop_back();
		}
	}
	mCurReadDepth--;
	return values_parsed;
}

bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
{
	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
	boost::char_separator<char> sep(".");

	bool any_parsed = false;
	bool silent = mCurReadDepth > 0;

	for(LLXMLAttribList::const_iterator attribute_it = nodep->mAttributes.begin();
		attribute_it != nodep->mAttributes.end();
		++attribute_it)
	{
		S32 num_tokens_pushed = 0;
		std::string attribute_name(attribute_it->first->mString);
		mCurReadNode = attribute_it->second;

		tokenizer name_tokens(attribute_name, sep);
		// copy remaining tokens on to our running token list
		for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
		{
			mNameStack.push_back(std::make_pair(*token_to_push, true));
			num_tokens_pushed++;
		}

		// child nodes are not necessarily valid attributes, so don't complain once we've recursed
		any_parsed |= block.submitValue(mNameStack, *this, silent);

		while(num_tokens_pushed-- > 0)
		{
			mNameStack.pop_back();
		}
	}

	return any_parsed;
}

void LLXUIParser::writeXUIImpl(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::predicate_rule_t rules, const LLInitParam::BaseBlock* diff_block)
{
	mWriteRootNode = node;
	name_stack_t name_stack = Parser::name_stack_t();
	block.serializeBlock(*this, name_stack, rules, diff_block);
	mOutNodes.clear();
}

// go from a stack of names to a specific XML node
LLXMLNodePtr LLXUIParser::getNode(name_stack_t& stack)
{
	LLXMLNodePtr out_node = mWriteRootNode;

	name_stack_t::iterator next_it = stack.begin();
	for (name_stack_t::iterator it = stack.begin();
		it != stack.end();
		it = next_it)
	{
		++next_it;
		bool force_new_node = false;

		if (it->first.empty())
		{
			it->second = false;
			continue;
		}

		if (next_it != stack.end() && next_it->first.empty() && next_it->second)
		{
			force_new_node = true;
		}

		out_nodes_t::iterator found_it = mOutNodes.find(it->first);

		// node with this name not yet written
		if (found_it == mOutNodes.end() || it->second || force_new_node)
		{
			// make an attribute if we are the last element on the name stack
			bool is_attribute = next_it == stack.end();
			LLXMLNodePtr new_node = new LLXMLNode(it->first.c_str(), is_attribute);
			out_node->addChild(new_node);
			mOutNodes[it->first] = new_node;
			out_node = new_node;
			it->second = false;
		}
		else
		{
			out_node = found_it->second;
		}
	}

	return (out_node == mWriteRootNode ? LLXMLNodePtr(NULL) : out_node);
}

bool LLXUIParser::readFlag(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	return self.mCurReadNode == DUMMY_NODE;
}

bool LLXUIParser::writeFlag(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	// just create node
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	return node.notNull();
}

bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr)
{
	S32 value;
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	bool success = self.mCurReadNode->getBoolValue(1, &value);
	*((bool*)val_ptr) = (value != FALSE);
	return success;
}

bool LLXUIParser::writeBoolValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		node->setBoolValue(*((bool*)val_ptr));
		return true;
	}
	return false;
}

bool LLXUIParser::readStringValue(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	*((std::string*)val_ptr) = self.mCurReadNode->getSanitizedValue();
	return true;
}

bool LLXUIParser::writeStringValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		const std::string* string_val = reinterpret_cast<const std::string*>(val_ptr);
		if (string_val->find('\n') != std::string::npos
			|| string_val->size() > MAX_STRING_ATTRIBUTE_SIZE)
		{
			// don't write strings with newlines into attributes
			std::string attribute_name = node->getName()->mString;
			LLXMLNodePtr parent_node = node->mParent;
			parent_node->deleteChild(node);
			// write results in text contents of node
			if (attribute_name == "value")
			{
				// "value" is implicit, just write to parent
				node = parent_node;
			}
			else
			{
				// create a child that is not an attribute, but with same name
				node = parent_node->createChild(attribute_name.c_str(), false);
			}
		}
		node->setStringValue(*string_val);
		return true;
	}
	return false;
}

bool LLXUIParser::readU8Value(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	return self.mCurReadNode->getByteValue(1, (U8*)val_ptr);
}

bool LLXUIParser::writeU8Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		node->setUnsignedValue(*((U8*)val_ptr));
		return true;
	}
	return false;
}

bool LLXUIParser::readS8Value(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	S32 value;
	if(self.mCurReadNode->getIntValue(1, &value))
	{
		*((S8*)val_ptr) = value;
		return true;
	}
	return false;
}

bool LLXUIParser::writeS8Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		node->setIntValue(*((S8*)val_ptr));
		return true;
	}
	return false;
}

bool LLXUIParser::readU16Value(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	U32 value;
	if(self.mCurReadNode->getUnsignedValue(1, &value))
	{
		*((U16*)val_ptr) = value;
		return true;
	}
	return false;
}

bool LLXUIParser::writeU16Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		node->setUnsignedValue(*((U16*)val_ptr));
		return true;
	}
	return false;
}

bool LLXUIParser::readS16Value(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	S32 value;
	if(self.mCurReadNode->getIntValue(1, &value))
	{
		*((S16*)val_ptr) = value;
		return true;
	}
	return false;
}

bool LLXUIParser::writeS16Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		node->setIntValue(*((S16*)val_ptr));
		return true;
	}
	return false;
}

bool LLXUIParser::readU32Value(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	return self.mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);
}

bool LLXUIParser::writeU32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		node->setUnsignedValue(*((U32*)val_ptr));
		return true;
	}
	return false;
}

bool LLXUIParser::readS32Value(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	return self.mCurReadNode->getIntValue(1, (S32*)val_ptr);
}

bool LLXUIParser::writeS32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		node->setIntValue(*((S32*)val_ptr));
		return true;
	}
	return false;
}

bool LLXUIParser::readF32Value(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	return self.mCurReadNode->getFloatValue(1, (F32*)val_ptr);
}

bool LLXUIParser::writeF32Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		node->setFloatValue(*((F32*)val_ptr));
		return true;
	}
	return false;
}

bool LLXUIParser::readF64Value(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	return self.mCurReadNode->getDoubleValue(1, (F64*)val_ptr);
}

bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		node->setDoubleValue(*((F64*)val_ptr));
		return true;
	}
	return false;
}

bool LLXUIParser::readVector3Value(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLVector3* vecp = (LLVector3*)val_ptr;
	if(self.mCurReadNode->getFloatValue(3, vecp->mV) >= 3)
	{
		return true;
	}

	return false;
}

bool LLXUIParser::writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		LLVector3 vector = *((LLVector3*)val_ptr);
		node->setFloatValue(3, vector.mV);
		return true;
	}
	return false;
}

bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLColor4* colorp = (LLColor4*)val_ptr;
	if(self.mCurReadNode->getFloatValue(4, colorp->mV) >= 3)
	{
		return true;
	}

	return false;
}

bool LLXUIParser::writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		LLColor4 color = *((LLColor4*)val_ptr);
		node->setFloatValue(4, color.mV);
		return true;
	}
	return false;
}

bool LLXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLUIColor* param = (LLUIColor*)val_ptr;
	LLColor4 color;
	bool success =  self.mCurReadNode->getFloatValue(4, color.mV) >= 3;
	if (success)
	{
		param->set(color);
		return true;
	}
	return false;
}

bool LLXUIParser::writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		LLUIColor color = *((LLUIColor*)val_ptr);
		//RN: don't write out the color that is represented by a function
		// rely on param block exporting to get the reference to the color settings
		if (color.isReference()) return false;
		node->setFloatValue(4, color.get().mV);
		return true;
	}
	return false;
}

bool LLXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLUUID temp_id;
	// LLUUID::set is destructive, so use temporary value
	if (temp_id.set(self.mCurReadNode->getSanitizedValue()))
	{
		*(LLUUID*)(val_ptr) = temp_id;
		return true;
	}
	return false;
}

bool LLXUIParser::writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		node->setStringValue(((LLUUID*)val_ptr)->asString());
		return true;
	}
	return false;
}

bool LLXUIParser::readSDValue(Parser& parser, void* val_ptr)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
	*((LLSD*)val_ptr) = LLSD(self.mCurReadNode->getSanitizedValue());
	return true;
}

bool LLXUIParser::writeSDValue(Parser& parser, const void* val_ptr, name_stack_t& stack)
{
	LLXUIParser& self = static_cast<LLXUIParser&>(parser);

	LLXMLNodePtr node = self.getNode(stack);
	if (node.notNull())
	{
		std::string string_val = ((LLSD*)val_ptr)->asString();
		if (string_val.find('\n') != std::string::npos || string_val.size() > MAX_STRING_ATTRIBUTE_SIZE)
		{
			// don't write strings with newlines into attributes
			std::string attribute_name = node->getName()->mString;
			LLXMLNodePtr parent_node = node->mParent;
			parent_node->deleteChild(node);
			// write results in text contents of node
			if (attribute_name == "value")
			{
				// "value" is implicit, just write to parent
				node = parent_node;
			}
			else
			{
				node = parent_node->createChild(attribute_name.c_str(), false);
			}
		}

		node->setStringValue(string_val);
		return true;
	}
	return false;
}

/*virtual*/ std::string LLXUIParser::getCurrentElementName()
{
	std::string full_name;
	for (name_stack_t::iterator it = mNameStack.begin();
		it != mNameStack.end();
		++it)
	{
		full_name += it->first + "."; // build up dotted names: "button.param.nestedparam."
	}

	return full_name;
}

void LLXUIParser::parserWarning(const std::string& message)
{
	std::string warning_msg = llformat("%s:\t%s(%d)", message.c_str(), mCurFileName.c_str(), mCurReadNode->getLineNumber());
	Parser::parserWarning(warning_msg);
}

void LLXUIParser::parserError(const std::string& message)
{
	std::string error_msg = llformat("%s:\t%s(%d)", message.c_str(), mCurFileName.c_str(), mCurReadNode->getLineNumber());
	Parser::parserError(error_msg);
}

//
// LLSimpleXUIParser
//

struct ScopedFile
{
	ScopedFile( const std::string& filename, const char* accessmode )
	{
		mFile = LLFile::fopen(filename, accessmode);
	}

	~ScopedFile()
	{
		fclose(mFile);
		mFile = NULL;
	}

	S32 getRemainingBytes()
	{
		if (!isOpen()) return 0;

		S32 cur_pos = ftell(mFile);
		fseek(mFile, 0L, SEEK_END);
		S32 file_size = ftell(mFile);
		fseek(mFile, cur_pos, SEEK_SET);
		return file_size - cur_pos;
	}

	bool isOpen() { return mFile != NULL; }

	LLFILE* mFile;
};
LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t element_cb)
:	Parser(sSimpleXUIReadFuncs, sSimpleXUIWriteFuncs, sSimpleXUIInspectFuncs),
	mCurReadDepth(0),
	mElementCB(element_cb)
{
	if (sSimpleXUIReadFuncs.empty())
	{
		registerParserFuncs<LLInitParam::Flag>(readFlag);
		registerParserFuncs<bool>(readBoolValue);
		registerParserFuncs<std::string>(readStringValue);
		registerParserFuncs<U8>(readU8Value);
		registerParserFuncs<S8>(readS8Value);
		registerParserFuncs<U16>(readU16Value);
		registerParserFuncs<S16>(readS16Value);
		registerParserFuncs<U32>(readU32Value);
		registerParserFuncs<S32>(readS32Value);
		registerParserFuncs<F32>(readF32Value);
		registerParserFuncs<F64>(readF64Value);
		registerParserFuncs<LLColor4>(readColor4Value);
		registerParserFuncs<LLUIColor>(readUIColorValue);
		registerParserFuncs<LLUUID>(readUUIDValue);
		registerParserFuncs<LLSD>(readSDValue);
	}
}

LLSimpleXUIParser::~LLSimpleXUIParser()
{
}

bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent)
{
	LL_RECORD_BLOCK_TIME(FTM_PARSE_XUI);

	mParser = XML_ParserCreate(NULL);
	XML_SetUserData(mParser, this);
	XML_SetElementHandler(			mParser,	startElementHandler, endElementHandler);
	XML_SetCharacterDataHandler(	mParser,	characterDataHandler);

	mOutputStack.push_back(std::make_pair(&block, 0));
	mNameStack.clear();
	mCurFileName = filename;
	mCurReadDepth = 0;
	setParseSilently(silent);

	ScopedFile file(filename, "rb");
	if( !file.isOpen() )
	{
		LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL;
		XML_ParserFree( mParser );
		return false;
	}

	S32 bytes_read = 0;

	S32 buffer_size = file.getRemainingBytes();
	void* buffer = XML_GetBuffer(mParser, buffer_size);
	if( !buffer )
	{
		LL_WARNS("ReadXUI") << "Unable to allocate XML buffer while reading file " << filename << LL_ENDL;
		XML_ParserFree( mParser );
		return false;
	}

	bytes_read = (S32)fread(buffer, 1, buffer_size, file.mFile);
	if( bytes_read <= 0 )
	{
		LL_WARNS("ReadXUI") << "Error while reading file  " << filename << LL_ENDL;
		XML_ParserFree( mParser );
		return false;
	}

	mEmptyLeafNode.push_back(false);

	if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) )
	{
		LL_WARNS("ReadXUI") << "Error while parsing file  " << filename << LL_ENDL;
		XML_ParserFree( mParser );
		return false;
	}

	mEmptyLeafNode.pop_back();

	XML_ParserFree( mParser );
	return true;
}

void LLSimpleXUIParser::startElementHandler(void *userData, const char *name, const char **atts)
{
	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
	self->startElement(name, atts);
}

void LLSimpleXUIParser::endElementHandler(void *userData, const char *name)
{
	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
	self->endElement(name);
}

void LLSimpleXUIParser::characterDataHandler(void *userData, const char *s, int len)
{
	LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
	self->characterData(s, len);
}

void LLSimpleXUIParser::characterData(const char *s, int len)
{
	mTextContents += std::string(s, len);
}

void LLSimpleXUIParser::startElement(const char *name, const char **atts)
{
	processText();

	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
	boost::char_separator<char> sep(".");

	if (mElementCB)
	{
		LLInitParam::BaseBlock* blockp = mElementCB(*this, name);
		if (blockp)
		{
			mOutputStack.push_back(std::make_pair(blockp, 0));
		}
	}

	mOutputStack.back().second++;
	S32 num_tokens_pushed = 0;
	std::string child_name(name);

	if (mOutputStack.back().second == 1)
	{	// root node for this block
		mScope.push_back(child_name);
	}
	else
	{	// compound attribute
		if (child_name.find(".") == std::string::npos)
		{
			mNameStack.push_back(std::make_pair(child_name, true));
			num_tokens_pushed++;
			mScope.push_back(child_name);
		}
		else
		{
			// parse out "dotted" name into individual tokens
			tokenizer name_tokens(child_name, sep);

			tokenizer::iterator name_token_it = name_tokens.begin();
			if(name_token_it == name_tokens.end())
			{
				return;
			}

			// check for proper nesting
			if(!mScope.empty() && *name_token_it != mScope.back())
			{
				return;
			}

			// now ignore first token
			++name_token_it;

			// copy remaining tokens on to our running token list
			for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
			{
				mNameStack.push_back(std::make_pair(*token_to_push, true));
				num_tokens_pushed++;
			}
			mScope.push_back(mNameStack.back().first);
		}
	}

	// parent node is not empty
	mEmptyLeafNode.back() = false;
	// we are empty if we have no attributes
	mEmptyLeafNode.push_back(atts[0] == NULL);

	mTokenSizeStack.push_back(num_tokens_pushed);
	readAttributes(atts);

}

void LLSimpleXUIParser::endElement(const char *name)
{
	bool has_text = processText();

	// no text, attributes, or children
	if (!has_text && mEmptyLeafNode.back())
	{
		// submit this as a valueless name (even though there might be text contents we haven't seen yet)
		mCurAttributeValueBegin = NO_VALUE_MARKER;
		mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
	}

	if (--mOutputStack.back().second == 0)
	{
		if (mOutputStack.empty())
		{
			LL_ERRS("ReadXUI") << "Parameter block output stack popped while empty." << LL_ENDL;
		}
		mOutputStack.pop_back();
	}

	S32 num_tokens_to_pop = mTokenSizeStack.back();
	mTokenSizeStack.pop_back();
	while(num_tokens_to_pop-- > 0)
	{
		mNameStack.pop_back();
	}
	mScope.pop_back();
	mEmptyLeafNode.pop_back();
}

bool LLSimpleXUIParser::readAttributes(const char **atts)
{
	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
	boost::char_separator<char> sep(".");

	bool any_parsed = false;
	for(S32 i = 0; atts[i] && atts[i+1]; i += 2 )
	{
		std::string attribute_name(atts[i]);
		mCurAttributeValueBegin = atts[i+1];

		S32 num_tokens_pushed = 0;
		tokenizer name_tokens(attribute_name, sep);
		// copy remaining tokens on to our running token list
		for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
		{
			mNameStack.push_back(std::make_pair(*token_to_push, true));
			num_tokens_pushed++;
		}

		// child nodes are not necessarily valid attributes, so don't complain once we've recursed
		any_parsed |= mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);

		while(num_tokens_pushed-- > 0)
		{
			mNameStack.pop_back();
		}
	}
	return any_parsed;
}

bool LLSimpleXUIParser::processText()
{
	if (!mTextContents.empty())
	{
		LLStringUtil::trim(mTextContents);
		if (!mTextContents.empty())
		{
			mNameStack.push_back(std::make_pair(std::string("value"), true));
			mCurAttributeValueBegin = mTextContents.c_str();
			mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
			mNameStack.pop_back();
		}
		mTextContents.clear();
		return true;
	}
	return false;
}

/*virtual*/ std::string LLSimpleXUIParser::getCurrentElementName()
{
	std::string full_name;
	for (name_stack_t::iterator it = mNameStack.begin();
		it != mNameStack.end();
		++it)
	{
		full_name += it->first + "."; // build up dotted names: "button.param.nestedparam."
	}

	return full_name;
}

void LLSimpleXUIParser::parserWarning(const std::string& message)
{
	std::string warning_msg = llformat("%s:\t%s",  message.c_str(), mCurFileName.c_str());
	Parser::parserWarning(warning_msg);
}

void LLSimpleXUIParser::parserError(const std::string& message)
{
	std::string error_msg = llformat("%s:\t%s",  message.c_str(), mCurFileName.c_str());
	Parser::parserError(error_msg);
}

bool LLSimpleXUIParser::readFlag(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	return self.mCurAttributeValueBegin == NO_VALUE_MARKER;
}

bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	if (!strcmp(self.mCurAttributeValueBegin, "true"))
	{
		*((bool*)val_ptr) = true;
		return true;
	}
	else if (!strcmp(self.mCurAttributeValueBegin, "false"))
	{
		*((bool*)val_ptr) = false;
		return true;
	}

	return false;
}

bool LLSimpleXUIParser::readStringValue(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	*((std::string*)val_ptr) = self.mCurAttributeValueBegin;
	return true;
}

bool LLSimpleXUIParser::readU8Value(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U8*)val_ptr)]).full;
}

bool LLSimpleXUIParser::readS8Value(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S8*)val_ptr)]).full;
}

bool LLSimpleXUIParser::readU16Value(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U16*)val_ptr)]).full;
}

bool LLSimpleXUIParser::readS16Value(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S16*)val_ptr)]).full;
}

bool LLSimpleXUIParser::readU32Value(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U32*)val_ptr)]).full;
}

bool LLSimpleXUIParser::readS32Value(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S32*)val_ptr)]).full;
}

bool LLSimpleXUIParser::readF32Value(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F32*)val_ptr)]).full;
}

bool LLSimpleXUIParser::readF64Value(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F64*)val_ptr)]).full;
}

bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	LLColor4 value;

	if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
	{
		*(LLColor4*)(val_ptr) = value;
		return true;
	}
	return false;
}

bool LLSimpleXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	LLColor4 value;
	LLUIColor* colorp = (LLUIColor*)val_ptr;

	if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
	{
		colorp->set(value);
		return true;
	}
	return false;
}

bool LLSimpleXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	LLUUID temp_id;
	// LLUUID::set is destructive, so use temporary value
	if (temp_id.set(std::string(self.mCurAttributeValueBegin)))
	{
		*(LLUUID*)(val_ptr) = temp_id;
		return true;
	}
	return false;
}

bool LLSimpleXUIParser::readSDValue(Parser& parser, void* val_ptr)
{
	LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
	*((LLSD*)val_ptr) = LLSD(self.mCurAttributeValueBegin);
	return true;
}

max_stars_repo_name: SaladDais/LLUDP-Encryption

max_issues_repo_name: bloomsirenix/Firestorm-manikineko

max_forks_repo_name: bloomsirenix/Firestorm-manikineko


text: #include <boost/fusion/container/generation/make_vector.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#include <boost/test/unit_test.hpp>
#include <test/data/nevmspv_valid.json.h>
#include <test/data/nevmspv_invalid.json.h>

#include <uint256.h>
#include <util/strencodings.h>
#include <nevm/nevm.h>
#include <nevm/common.h>
#include <nevm/rlp.h>
#include <script/interpreter.h>
#include <script/standard.h>
#include <policy/policy.h>
#include <services/asset.h>
#include <univalue.h>
#include <key_io.h>
#include <util/system.h>
#include <test/util/setup_common.h>
extern UniValue read_json(const std::string& jsondata);

BOOST_FIXTURE_TEST_SUITE(nevm_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(seniority_test)
{
    const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
    const auto consensusParams = chainParams->GetConsensus();
    const int oldSr1Height = 525600;
    const int oldSr2Height = oldSr1Height*2.5;
    const int newSr1Height = oldSr1Height/2.5;
    const int newSr2Height = newSr1Height*2.5;
    BOOST_CHECK_EQUAL(consensusParams.Seniority(consensusParams.nNEVMStartBlock, 0), consensusParams.nSeniorityLevel2);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(consensusParams.nNEVMStartBlock+1, 0), consensusParams.nSeniorityLevel2);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(consensusParams.nNEVMStartBlock, consensusParams.nNEVMStartBlock), 0);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(1000000, 1000000), 0);
    // apply old seniority numbers as if MN started at 0 height
    BOOST_CHECK_EQUAL(consensusParams.Seniority(oldSr2Height, 0), consensusParams.nSeniorityLevel2);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(oldSr1Height, 0), consensusParams.nSeniorityLevel1);
    // apply old seniority numbers as if MN started at 10000 height
    BOOST_CHECK_EQUAL(consensusParams.Seniority(oldSr2Height+10000, 10000), consensusParams.nSeniorityLevel2);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(oldSr1Height+10000, 10000), consensusParams.nSeniorityLevel1);
    // test transition of old seniority numbers
    BOOST_CHECK_EQUAL(consensusParams.Seniority(oldSr1Height + (oldSr2Height-oldSr1Height) - 1, 0), consensusParams.nSeniorityLevel1);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(oldSr1Height + (oldSr2Height-oldSr1Height), 0), consensusParams.nSeniorityLevel2);
    // test transition of new seniority number as if MN started at the NEVM start height
    BOOST_CHECK_EQUAL(consensusParams.Seniority(consensusParams.nNEVMStartBlock+newSr1Height - 1, consensusParams.nNEVMStartBlock), 0);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(consensusParams.nNEVMStartBlock+newSr1Height, consensusParams.nNEVMStartBlock), consensusParams.nSeniorityLevel1);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(consensusParams.nNEVMStartBlock+newSr1Height + (newSr2Height - newSr1Height) - 1, consensusParams.nNEVMStartBlock), consensusParams.nSeniorityLevel1);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(consensusParams.nNEVMStartBlock+newSr1Height + (newSr2Height - newSr1Height) , consensusParams.nNEVMStartBlock), consensusParams.nSeniorityLevel2);
    // test transition of new seniority number as if MN started before NEVM height
    const int nStartHeight = consensusParams.nNEVMStartBlock - 25000;
    const int nTargetHeight1 = (consensusParams.nNEVMStartBlock + newSr1Height) - (25000/2.5);
    const int nTargetHeight2 = (consensusParams.nNEVMStartBlock + newSr2Height) - (25000/2.5);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(nTargetHeight1 - 1, nStartHeight), 0);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(nTargetHeight1, nStartHeight), consensusParams.nSeniorityLevel1);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(nTargetHeight2 - 1, nStartHeight), consensusParams.nSeniorityLevel1);
    BOOST_CHECK_EQUAL(consensusParams.Seniority(nTargetHeight2, nStartHeight), consensusParams.nSeniorityLevel2);
}
BOOST_AUTO_TEST_CASE(halving_test)
{
    const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
    const auto consensusParams = chainParams->GetConsensus();
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(100000), 0);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(consensusParams.nSubsidyHalvingInterval), 0);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(consensusParams.nSubsidyHalvingInterval+1), 0);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals((consensusParams.nSubsidyHalvingInterval*2.5) - 1), 0);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(consensusParams.nSubsidyHalvingInterval*2.5), 1);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals((consensusParams.nSubsidyHalvingInterval*2.5) + 1), 1);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(consensusParams.nSubsidyHalvingInterval*2.5 + consensusParams.nSubsidyHalvingInterval*2.5), 2);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(consensusParams.nNEVMStartBlock), 2);
    double forkIntervals = consensusParams.nNEVMStartBlock/(consensusParams.nSubsidyHalvingInterval*2.5);
    int ceilingIntervalFork = ceil(forkIntervals);
    double diffForkInterval = ceilingIntervalFork - forkIntervals;
    int nextIntervalAfterFork = consensusParams.nNEVMStartBlock + diffForkInterval*consensusParams.nSubsidyHalvingInterval;
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(nextIntervalAfterFork - 1), 2);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(nextIntervalAfterFork), 3);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(nextIntervalAfterFork+1), 3);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(nextIntervalAfterFork + consensusParams.nSubsidyHalvingInterval - 1), 3);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(nextIntervalAfterFork + consensusParams.nSubsidyHalvingInterval), 4);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(nextIntervalAfterFork + (consensusParams.nSubsidyHalvingInterval*2) - 1), 4);
    BOOST_CHECK_EQUAL(consensusParams.SubsidyHalvingIntervals(nextIntervalAfterFork + (consensusParams.nSubsidyHalvingInterval*2)), 5);
}
BOOST_AUTO_TEST_CASE(nevm_parseabidata)
{
    tfm::format(std::cout,"Running nevm_parseabidata...\n");
    CAmount outputAmount;
    uint64_t nAsset = 0;
    const std::vector<unsigned char> &expectedMethodHash = ParseHex("54c988ff");
    const std::vector<unsigned char> &rlpBytes = ParseHex("54c988ff00000000000000000000000000000000000000000000000000000002540be400000000000000000000000000000000000000000000000000000000009be8894b0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002c62637274317130667265323430737939326d716b386b6b377073616561366b74366d3537323570377964636a0000000000000000000000000000000000000000");
    std::string expectedAddress = "bcrt1q0fre240sy92mqk8kk7psaea6kt6m5725p7ydcj";
    std::string address;
    BOOST_CHECK(parseNEVMMethodInputData(expectedMethodHash, 8, 8, rlpBytes, outputAmount, nAsset, address));
    BOOST_CHECK_EQUAL(outputAmount, 100*COIN);
    BOOST_CHECK_EQUAL(nAsset, (uint64_t)2615707979);
    BOOST_CHECK(address == expectedAddress);

}
BOOST_AUTO_TEST_CASE(nevmspv_valid)
{
    tfm::format(std::cout,"Running nevmspv_valid...\n");
    // Read tests from test/data/nevmspv_valid.json
    // Format is an array of arrays
    // Inner arrays are either [ "comment" ]
    // [[spv_root, spv_parent_node, spv_value, spv_path]]

    UniValue tests = read_json(std::string(json_tests::nevmspv_valid, json_tests::nevmspv_valid + sizeof(json_tests::nevmspv_valid)));

    for (unsigned int idx = 0; idx < tests.size(); idx++) {
        UniValue test = tests[idx];
        std::string strTest = test.write();
        if (test.size() != 4) {
				// ignore comments
				continue;
		} else {
        if ( !test[0].isStr() || !test[1].isStr() || !test[2].isStr() || !test[3].isStr()) {
            BOOST_ERROR("Bad test: " << strTest);
            continue;
        }

      	std::string spv_tx_root = test[0].get_str();
			  std::string spv_parent_nodes = test[1].get_str();
			  std::string spv_value = test[2].get_str();
			  std::string spv_path = test[3].get_str();

        const std::vector<unsigned char> &vchTxRoot = ParseHex(spv_tx_root);
        dev::RLP rlpTxRoot(&vchTxRoot);
        const std::vector<unsigned char> &vchTxParentNodes = ParseHex(spv_parent_nodes);
        dev::RLP rlpTxParentNodes(&vchTxParentNodes);
        const std::vector<unsigned char> &vchTxValue = ParseHex(spv_value);
        dev::RLP rlpTxValue(&vchTxValue);
        const std::vector<unsigned char> &vchTxPath = ParseHex(spv_path);
        BOOST_CHECK(VerifyProof(&vchTxPath, rlpTxValue, rlpTxParentNodes, rlpTxRoot));
        }
    }
}

BOOST_AUTO_TEST_CASE(nevmspv_invalid)
{
    tfm::format(std::cout,"Running nevmspv_invalid...\n");
    // Read tests from test/data/nevmspv_invalid.json
    // Format is an array of arrays
    // Inner arrays are either [ "comment" ]
    // [[spv_root, spv_parent_node, spv_value, spv_path]]

    UniValue tests = read_json(std::string(json_tests::nevmspv_invalid, json_tests::nevmspv_invalid + sizeof(json_tests::nevmspv_invalid)));

    for (unsigned int idx = 0; idx < tests.size(); idx++) {
        UniValue test = tests[idx];
        std::string strTest = test.write();
        if (test.size() != 4) {
				// ignore comments
				continue;
		    } else {
            if ( !test[0].isStr() || !test[1].isStr() || !test[2].isStr() || !test[3].isStr()) {
                BOOST_ERROR("Bad test: " << strTest);
                continue;
            }
			      std::string spv_tx_root = test[0].get_str();
			      std::string spv_parent_nodes = test[1].get_str();
			      std::string spv_value = test[2].get_str();
			      std::string spv_path = test[3].get_str();

            const std::vector<unsigned char> &vchTxRoot = ParseHex(spv_tx_root);
            dev::RLP rlpTxRoot(&vchTxRoot);
            const std::vector<unsigned char> &vchTxParentNodes = ParseHex(spv_parent_nodes);
            dev::RLP rlpTxParentNodes(&vchTxParentNodes);
            const std::vector<unsigned char> &vchTxValue = ParseHex(spv_value);
            dev::RLP rlpTxValue(&vchTxValue);
            const std::vector<unsigned char> &vchTxPath = ParseHex(spv_path);
            BOOST_CHECK(!VerifyProof(&vchTxPath, rlpTxValue, rlpTxParentNodes, rlpTxRoot));
        }
    }
}
BOOST_AUTO_TEST_SUITE_END()

ext: cpp

max_stars_repo_name: Frank-GER/syscoin

max_issues_repo_name: Frank-GER/syscoin

max_forks_repo_name: Frank-GER/syscoin


text:
#include <nori/object.h>
#include <Eigen/Geometry>
#include <Eigen/LU>
#include <boost/math/special_functions/fpclassify.hpp>

#if defined(PLATFORM_LINUX)
#include <malloc.h>
#endif

#if defined(PLATFORM_WINDOWS)
#include <windows.h>
#endif

#if defined(PLATFORM_MACOS)
#include <sys/sysctl.h>
#endif

#if !defined(L1_CACHE_LINE_SIZE)
#define L1_CACHE_LINE_SIZE 64
#endif

NORI_NAMESPACE_BEGIN

Color3f Color3f::toSRGB() const {
	Color3f result;

	for (int i=0; i<3; ++i) {
		float value = coeff(i);

		if (value <= 0.0031308f)
			result[i] = 12.92f * value;
		else
			result[i] = (1.0f + 0.055f)
				* std::pow(value, 1.0f/2.4f) -  0.055f;
	}

	return result;
}

Color3f Color3f::toLinearRGB() const {
	Color3f result;

	for (int i=0; i<3; ++i) {
		float value = coeff(i);

		if (value <= 0.04045f)
			result[i] = value * (1.0f / 12.92f);
		else
			result[i] = std::pow((value + 0.055f)
				* (1.0f / 1.055f), 2.4f);
	}

	return result;
}

bool Color3f::isValid() const {
	for (int i=0; i<3; ++i) {
		float value = coeff(i);
		int cl = boost::math::fpclassify(value);
		if (value < 0 || cl == FP_INFINITE || cl == FP_NAN)
			return false;
	}
	return true;
}

float Color3f::getLuminance() const {
	return coeff(0) * 0.212671f + coeff(1) * 0.715160f + coeff(2) * 0.072169f;
}

Transform::Transform(const Eigen::Matrix4f &trafo)
	: m_transform(trafo), m_inverse(trafo.inverse()) { }

QString Transform::toString() const {
	std::ostringstream oss;
	oss << m_transform.format(Eigen::IOFormat(4, 0, ", ", ";\n", "", "", "[", "]"));
	return QString(oss.str().c_str());
}
QString Transform::toLineString() const {
	std::ostringstream oss;
        for(int row = 0; row < 4; ++row){
            if(row > 0) oss << "; ";
            for(int col = 0; col < 4; ++col){
                if(col > 0) oss << ", ";
                oss << m_transform(row, col);
            }
        }
	return QString(oss.str().c_str());
}

Vector3f squareToUniformSphere(const Point2f &sample) {
	float z = 1.0f - 2.0f * sample.y();
	float r = std::sqrt(std::max((float) 0.0f, 1.0f - z*z));
	float sinPhi, cosPhi;
	sincosf(2.0f * M_PI * sample.x(), &sinPhi, &cosPhi);
	return Vector3f(r * cosPhi, r * sinPhi, z);
}

Vector3f squareToUniformHemisphere(const Point2f &sample) {
	float cosTheta = sample.x();
	float sinTheta = std::sqrt(std::max((float) 0, 1-cosTheta*cosTheta));

	float sinPhi, cosPhi;
	sincosf(2.0f * M_PI * sample.y(), &sinPhi, &cosPhi);

	return Vector3f(cosPhi * sinTheta, sinPhi * sinTheta, cosTheta);
}

Point2f squareToUniformDisk(const Point2f &sample) {
	float r = std::sqrt(sample.x());
	float sinPhi, cosPhi;
	sincosf(2.0f * M_PI * sample.y(), &sinPhi, &cosPhi);

	return Point2f(
		cosPhi * r,
		sinPhi * r
	);
}

Point2f squareToUniformDiskConcentric(const Point2f &sample) {
	float r1 = 2.0f*sample.x() - 1.0f;
	float r2 = 2.0f*sample.y() - 1.0f;

	Point2f coords;
	if (r1 == 0 && r2 == 0) {
		coords = Point2f(0, 0);
	} else if (r1 > -r2) { /* Regions 1/2 */
		if (r1 > r2)
			coords = Point2f(r1, (M_PI/4.0f) * r2/r1);
		else
			coords = Point2f(r2, (M_PI/4.0f) * (2.0f - r1/r2));
	} else { /* Regions 3/4 */
		if (r1<r2)
			coords = Point2f(-r1, (M_PI/4.0f) * (4.0f + r2/r1));
		else
			coords = Point2f(-r2, (M_PI/4.0f) * (6.0f - r1/r2));
	}

	Point2f result;
	sincosf(coords.y(), &result[1], &result[0]);
	return result*coords.x();
}

Point2f squareToUniformTriangle(const Point2f &sample) {
	float a = std::sqrt(1.0f - sample.x());
	return Point2f(1 - a, a * sample.y());
}

float intervalToTent(float sample) {
	float sign;

	if (sample < 0.5f) {
		sign = 1;
		sample *= 2;
	} else {
		sign = -1;
		sample = 2 * (sample - 0.5f);
	}

	return sign * (1 - std::sqrt(sample));
}

Point2f squareToTent(const Point2f &sample) {
	return Point2f(
		intervalToTent(sample.x()),
		intervalToTent(sample.y())
	);
}

Point2f squareToTriangle(const Point2f &sample) {
	float a = std::sqrt(1.0f - sample.x());
	return Point2f(1 - a, a * sample.y());
}

Vector3f sphericalDirection(float theta, float phi) {
	float sinTheta, cosTheta, sinPhi, cosPhi;

	sincosf(theta, &sinTheta, &cosTheta);
	sincosf(phi, &sinPhi, &cosPhi);

	return Vector3f(
		sinTheta * cosPhi,
		sinTheta * sinPhi,
		cosTheta
	);
}

Point2f sphericalCoordinates(const Vector3f &v) {
	Point2f result(
		std::acos(v.z()),
		std::atan2(v.y(), v.x())
	);
	if (result.y() < 0)
		result.y() += 2*M_PI;
	return result;
}

void coordinateSystem(const Vector3f &a, Vector3f &b, Vector3f &c) {
	if (std::abs(a.x()) > std::abs(a.y())) {
		float invLen = 1.0f / std::sqrt(a.x() * a.x() + a.z() * a.z());
		c = Vector3f(a.z() * invLen, 0.0f, -a.x() * invLen);
	} else {
		float invLen = 1.0f / std::sqrt(a.y() * a.y() + a.z() * a.z());
		c = Vector3f(0.0f, a.z() * invLen, -a.y() * invLen);
	}
	b = c.cross(a);
}

void *allocAligned(size_t size) {
#if defined(PLATFORM_WINDOWS)
	return _aligned_malloc(size, L1_CACHE_LINE_SIZE);
#elif defined(PLATFORM_MACOS)
	/* OSX malloc already returns 16-byte aligned data suitable
	   for AltiVec and SSE computations */
	return malloc(size);
#else
	return memalign(L1_CACHE_LINE_SIZE, size);
#endif
}

void freeAligned(void *ptr) {
#if defined(PLATFORM_WINDOWS)
	_aligned_free(ptr);
#else
	free(ptr);
#endif
}

int getCoreCount() {
#if defined(PLATFORM_WINDOWS)
	SYSTEM_INFO sys_info;
	GetSystemInfo(&sys_info);
	return sys_info.dwNumberOfProcessors;
#elif defined(PLATFORM_MACOS)
	int nprocs;
	size_t nprocsSize = sizeof(int);
	if (sysctlbyname("hw.activecpu", &nprocs, &nprocsSize, NULL, 0))
		throw NoriException("Could not detect the number of processors!");
	return (int) nprocs;
#else
	return sysconf(_SC_NPROCESSORS_CONF);
#endif
}

QString indent(const QString &string, int amount) {
	QString result = string;
	result.replace("\n", QString("\n") + QString(" ").repeated(amount));
	return result;
}

float fresnel(float cosThetaI, float extIOR, float intIOR) {
	float etaI = extIOR, etaT = intIOR;

	if (extIOR == intIOR)
		return 0.0f;

	/* Swap the indices of refraction if the interaction starts
	   at the inside of the object */
	if (cosThetaI < 0.0f) {
		std::swap(etaI, etaT);
		cosThetaI = -cosThetaI;
	}

	/* Using Snell's law, calculate the squared sine of the
	   angle between the normal and the transmitted ray */
	float eta = etaI / etaT,
		  sinThetaTSqr = eta*eta * (1-cosThetaI*cosThetaI);

	if (sinThetaTSqr > 1.0f)
		return 1.0f;  /* Total internal reflection! */

	float cosThetaT = std::sqrt(1.0f - sinThetaTSqr);

	float Rs = (etaI * cosThetaI - etaT * cosThetaT)
	         / (etaI * cosThetaI + etaT * cosThetaT);
	float Rp = (etaT * cosThetaI - etaI * cosThetaT)
	         / (etaT * cosThetaI + etaI * cosThetaT);

	return (Rs * Rs + Rp * Rp) / 2.0f;
}

NORI_NAMESPACE_END


text:
/*
 * Copyright (c) 2018 Tuukka Norri
 * This code is licensed under MIT license (see LICENSE for details).
 */

#include <algorithm>
#include <boost/range/combine.hpp>
#include <iomanip>
#include <iostream>
#include <libbio/assert.hh>
#include <libbio/dispatch.hh>
#include <libbio/file_handling.hh>
#include <libbio/mmap_handle.hh>
#include <range/v3/all.hpp>
#include <regex>

#include "cmdline.h"

namespace ios	= boost::iostreams;
namespace lb	= libbio;

namespace {

	typedef ios::stream <ios::array_source>	array_istream;
	typedef std::vector <lb::file_istream>	input_file_vector;
	typedef std::vector <array_istream>		array_istream_vector;
	typedef std::vector <lb::file_ostream>	output_file_vector;
	typedef std::vector <std::string>		file_name_vector;

	template <typename t_value>
	void open_file_for_writing(
		t_value name,
		lb::file_ostream &stream,
		lb::writing_open_mode const mode
	)
	{
		lb::open_file_for_writing(std::to_string(name), stream, mode);
	}

	template <>
	void open_file_for_writing(
		std::string const &name,
		lb::file_ostream &stream,
		lb::writing_open_mode const mode
	)
	{
		lb::open_file_for_writing(name, stream, mode);
	}

	void read_input_file_names(
		std::istream &istream,
		std::regex const &output_fname_re,
		file_name_vector &input_file_names,
		file_name_vector &output_file_names
	)
	{
		std::string fname;
		while (std::getline(istream, fname))
		{
			input_file_names.push_back(fname);

			std::smatch fname_match;
			std::regex_search(fname, fname_match, output_fname_re);
			auto out_fname(fname_match[1].str());
			output_file_names.emplace_back(std::move(out_fname));
		}
	}

	void open_input_files(
		file_name_vector const &input_file_names,
		input_file_vector &input_files
	)
	{
		for (auto const &tup : ranges::view::zip(input_file_names, input_files))
			lb::open_file_for_reading(std::get <0>(tup), std::get <1>(tup));
	}

	template <typename t_range>
	void open_output_files(
		t_range const &output_file_names,
		output_file_vector &output_files,
		bool const overwrite
	)
	{
		auto const mode(lb::make_writing_open_mode({
			lb::writing_open_mode::CREATE,
			(overwrite ? lb::writing_open_mode::OVERWRITE : lb::writing_open_mode::NONE)
		}));

		for (auto const &tup : ranges::view::zip(output_file_names, output_files))
			open_file_for_writing(std::get <0>(tup), std::get <1>(tup), mode);
	}

	template <typename t_istream>
	void output_from_streams(
		std::vector <t_istream> &input_streams,
		output_file_vector &output_streams
	)
	{
		lb::for_each(
			boost::combine(input_streams, output_streams),
			[](auto const &tup) {
				char c{};
				auto &input(tup.template get <0>());
				auto &output(tup.template get <1>());
				input >> std::noskipws >> c;
				output << c;
			}
		);
	}

	void output_from_reference(
		std::istream &reference,
		output_file_vector &output_files,
		std::size_t const aligned_pos
	)
	{
		char c{};
		reference.seekg(aligned_pos);
		reference >> std::noskipws >> c;
		lb::for_each(
			output_files,
			[c](auto &output) {
				output << c;
			}
		);
	}

	template <typename t_istream>
	void process(
		std::vector <t_istream> &input_streams,
		output_file_vector &output_streams,
		lb::file_istream &reference_stream,
		lb::file_istream &identity_column_stream
	)
	{
		// Read from the inputs and combine.
		std::cerr << "Handling the input…" << std::endl;
		std::size_t aligned_pos(0);
		char is_identity{};
		while (identity_column_stream >> std::noskipws >> is_identity)
		{
			switch (is_identity)
			{
				// Not identity.
				case '0':
					output_from_streams(input_streams, output_streams);
					break;

				// Identity.
				case '1':
					output_from_reference(reference_stream, output_streams, aligned_pos);
					break;

				// End of file.
				case '\n':
					goto exit_loop;

				// Unexpected character.
				default:
					throw std::runtime_error("Unexpected character");
					break;
			}

			++aligned_pos;

			if (0 == aligned_pos % 1000000)
			{
				auto const time(std::chrono::system_clock::now());
				auto const ct(std::chrono::system_clock::to_time_t(time));
				struct tm ctm;
				localtime_r(&ct, &ctm);
				std::cerr
				<< '['
				<< std::setw(2) << std::setfill('0') << ctm.tm_hour << ':'
				<< std::setw(2) << std::setfill('0') << ctm.tm_min << ':'
				<< std::setw(2) << std::setfill('0') << ctm.tm_sec
				<< "] At position " << aligned_pos << "…" << std::endl;
			}
		}

	exit_loop:
		lb::for_each(
			output_streams,
			[](auto &output) {
				output << std::flush;
			}
		);
	}

	void process_list_file_and_continue(
		lb::file_istream &reference_stream,
		lb::file_istream &identity_column_stream,
		char const *input_path,
		bool const read_from_cin,
		bool const should_overwrite
	)
	{
		file_name_vector input_file_names;
		file_name_vector output_file_names;
		std::regex output_fname_re(".*?([^/]+)$");

		if (read_from_cin)
			read_input_file_names(std::cin, output_fname_re, input_file_names, output_file_names);
		else
		{
			lb::file_istream stream;
			libbio::open_file_for_reading(input_path, stream);
			read_input_file_names(stream, output_fname_re, input_file_names, output_file_names);
		}

		// Instantiate streams.
		auto const file_count(input_file_names.size());
		input_file_vector input_files(file_count);
		output_file_vector output_files(file_count);
		open_input_files(input_file_names, input_files);
		open_output_files(output_file_names, output_files, should_overwrite);

		process(input_files, output_files, reference_stream, identity_column_stream);
	}

	void process_text_file_and_continue(
		lb::file_istream &reference_stream,
		lb::file_istream &identity_column_stream,
		char const *input_path,
		bool const read_from_cin,
		bool const should_overwrite
	)
	{
		if (read_from_cin)
			libbio_fail("Memory mapping needed for single-file input.");

		lb::mmap_handle <char> handle;
		handle.open(input_path);

		// Check the sequence size and that all sequences have the same length.
		auto sv(handle.to_string_view());
		auto const sequence_length(sv.find_first_of('\n'));
		std::size_t sequence_count(0);
		auto const limit(sv.size());
		for (std::size_t i(sequence_length); i < limit; i += (1 + sequence_length))
		{
			libbio_always_assert(sv[i] == '\n');
			++sequence_count;
		}

		array_istream_vector inputs(sequence_count);
		std::size_t j(0);
		auto const *data(handle.data());
		for (std::size_t i(sequence_length); i < limit; i+= (1 + sequence_length))
		{
			auto const start(i - sequence_length);
			inputs[j].open(data + start, sequence_length);
			++j;
		}

		output_file_vector output_files(sequence_count);
		open_output_files(ranges::view::iota(1, 1 + sequence_count), output_files, should_overwrite);

		process(inputs, output_files, reference_stream, identity_column_stream);
	}
}

int main(int argc, char **argv)
{
	gengetopt_args_info args_info;
	if (0 != cmdline_parser(argc, argv, &args_info))
		exit(EXIT_FAILURE);

	// Don't sync with stdio.
	std::ios_base::sync_with_stdio(false);

	char const *input_path(args_info.input_arg);
	char const *reference_path(args_info.reference_arg);
	char const *identity_column_path(args_info.identity_columns_arg);
	bool const should_overwrite(args_info.overwrite_flag);

	bool const read_from_cin('-' == args_info.input_arg[0] && '\0' == args_info.input_arg[1]);

	// Open the streams.
	std::cerr << "Opening the files…" << std::endl;
	lb::file_istream reference_stream;
	lb::file_istream identity_column_stream;
	lb::open_file_for_reading(reference_path, reference_stream);
	lb::open_file_for_reading(identity_column_path, identity_column_stream);
	reference_stream.exceptions(reference_stream.exceptions() | std::istream::badbit | std::istream::failbit);
	identity_column_stream.exceptions(identity_column_stream.exceptions() | std::istream::badbit | std::istream::failbit);

	switch (args_info.input_format_arg)
	{
		case input_format_arg_text:
			process_text_file_and_continue(reference_stream, identity_column_stream, args_info.input_arg, read_from_cin, should_overwrite);
			break;

		case input_format_arg_listMINUS_file:
			process_list_file_and_continue(reference_stream, identity_column_stream, args_info.input_arg, read_from_cin, should_overwrite);
			break;

		default:
			libbio_fail("Unexpected input file format");
	}

	cmdline_parser_free(&args_info);

	return EXIT_SUCCESS;
}

ext: cc

max_stars_repo_name: tsnorri/founder-sequences

max_issues_repo_name: tsnorri/founder-sequences

max_forks_repo_name: tsnorri/founder-sequences


text:
#include "GeoCoordinate.hpp"
#include "builders/BuilderContext.hpp"
#include "builders/buildings/BuildingBuilder.hpp"
#include "entities/Area.hpp"
#include "entities/Relation.hpp"

#include <boost/test/unit_test.hpp>

#include "test_utils/DependencyProvider.hpp"
#include "test_utils/ElementUtils.hpp"

using namespace utymap;
using namespace utymap::builders;
using namespace utymap::entities;
using namespace utymap::math;

namespace {
    const std::string stylesheet = "area,relation|z1[building=yes] { "
                                        "builders: building;"
                                        "building: true;"
                                        "facade-color: gradient(blue);"
                                        "facade-type: flat;"
                                        "roof-color: gradient(red);"
                                        "roof-type: flat;"
                                        "roof-height: 0m;"
                                        "height: 12m;"
                                        "min-height: 0m;"
                                    "}"
                                   "relation|z1[type=multipolygon] {"
                                        "multipolygon: true;"
                                    "};";
    struct Builders_Buildings_BuildingsBuilderFixture
    {
        DependencyProvider dependencyProvider;
    };
}

BOOST_FIXTURE_TEST_SUITE(Builders_Buildings_BuildingsBuilder, Builders_Buildings_BuildingsBuilderFixture)

BOOST_AUTO_TEST_CASE(GivenRectangleArea_WhenVisitArea_ThenMeshIsBuilt)
{
    QuadKey quadKey(1, 1, 0);
    bool isCalled = false;
    auto context = dependencyProvider.createBuilderContext(
            quadKey,
            stylesheet,
            [&](const Mesh& mesh) {
                isCalled = true;
                BOOST_CHECK_GT(mesh.vertices.size(), 0);
                BOOST_CHECK_GT(mesh.triangles.size(), 0);
                BOOST_CHECK_GT(mesh.colors.size(), 0);
            });
    Area building = ElementUtils::createElement<Area>(*dependencyProvider.getStringTable(), 0, { { "building", "yes" } },
        { { 10, 0 }, { 10, 10 }, { 0, 10 }, { 0, 0 } });
    BuildingBuilder builder(*context);

    builder.visitArea(building);

    BOOST_CHECK(isCalled);
}

BOOST_AUTO_TEST_CASE(GivenRelationWithHole_WhenVisitRelation_ThenMeshIsBuilt)
{
    QuadKey quadKey(1, 1, 0);
    bool isCalled = false;
    auto context = dependencyProvider.createBuilderContext(
        quadKey,
        stylesheet,
        [&](const Mesh& mesh) {
            isCalled = true;
            BOOST_CHECK_GT(mesh.vertices.size(), 0);
            BOOST_CHECK_GT(mesh.triangles.size(), 0);
            BOOST_CHECK_GT(mesh.colors.size(), 0);
    });
    Relation relation;
    relation.tags = {
            ElementUtils::createTag(*dependencyProvider.getStringTable(), "building", "yes"),
            ElementUtils::createTag(*dependencyProvider.getStringTable(), "type", "multipolygon"),
    };
    auto outer = std::make_shared<Area>(ElementUtils::createElement<Area>(*dependencyProvider.getStringTable(), 0, {},
        { { 10, 0 }, { 10, 10 }, { 0, 10 }, { 0, 0 } }));
    auto inner = std::make_shared<Area>(ElementUtils::createElement<Area>(*dependencyProvider.getStringTable(), 0, {},
        { { 2, 2 }, { 2, 8 }, { 8, 8 }, { 8, 2 } }));
    relation.elements.push_back(outer);
    relation.elements.push_back(inner);
    BuildingBuilder builder(*context);

    builder.visitRelation(relation);

    BOOST_CHECK(isCalled);
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: lonnibesancon/utymap

max_issues_repo_name: lonnibesancon/utymap

max_forks_repo_name: lonnibesancon/utymap


text:
#include <boost/test/unit_test.hpp>
#include <complex>
#include "../include/WindowingAnalysis.h"
#include "../../JeanBaptiste/include/tools/RealComplexConversion.h"
#include "../../JeanBaptiste/include/windowing/BartlettWindow.h"
#include "../../JeanBaptiste/include/windowing/BlackmanWindow.h"
#include "../../JeanBaptiste/include/windowing/BlackmanHarrisWindow.h"
#include "../../JeanBaptiste/include/windowing/CosineWindow.h"
#include "../../JeanBaptiste/include/windowing/FlatTopWindow.h"
#include "../../JeanBaptiste/include/windowing/HammingWindow.h"
#include "../../JeanBaptiste/include/windowing/VonHannWindow.h"
#include "../../JeanBaptiste/include/windowing/WelchWindow.h"
#include <string>

namespace ut = boost::unit_test;
namespace jb = jeanbaptiste;
namespace jt = jeanbaptiste::tools;
namespace jw = jeanbaptiste::windowing;

class WindowCalculationFixture
{
protected:
    std::vector<double> workingSet_;
    std::vector<double> expectedOut_;
    static const unsigned kSampleCnt_ = 128;
    Utilities::WindowingAnalysis<double> analysis_;
    jt::Real2Complex<std::complex<double>> real2ComplexConverter_;
    jt::Complex2Real<std::complex<double>> complex2RealConverter_;
    bool initialized_;

public:
    WindowCalculationFixture()
    {
        workingSet_.clear();
        expectedOut_.clear();
    }

    ~WindowCalculationFixture()
    {}
};

BOOST_FIXTURE_TEST_SUITE(WindowCalculationTestSuite, WindowCalculationFixture)

    BOOST_AUTO_TEST_CASE(bartlett)
    {
        BOOST_TEST((initialized_ = analysis_.initialize("../../test cases/WinBartlettTest.xml", "win.in", workingSet_, "win.out", expectedOut_)), "Loading test data failed.");
        if (!initialized_)
            return;

        BOOST_TEST_MESSAGE("Checking Bartlett window samples.");

        jw::BartlettWindow<std::integral_constant<int, kSampleCnt_>, std::complex<double>> bartlett;

        auto complexData = real2ComplexConverter_(workingSet_);
        bartlett(&complexData[0]);
        auto realData = complex2RealConverter_(complexData);

        analysis_.checkOutput(realData, expectedOut_);
    }

    BOOST_AUTO_TEST_CASE(blackman_harris)
    {
        BOOST_TEST((initialized_ = analysis_.initialize("../../test cases/WinBlackmanHarrisTest.xml", "win.in", workingSet_, "win.out", expectedOut_)), "Loading test data failed.");
        if (!initialized_)
            return;

        BOOST_TEST_MESSAGE("Checking Blackman Harris window samples.");

        jw::BlackmanHarrisWindow<std::integral_constant<int, kSampleCnt_>, std::complex<double>> blackmanHarris;

        auto complexData = real2ComplexConverter_(workingSet_);
        blackmanHarris(&complexData[0]);
        auto realData = complex2RealConverter_(complexData);

        analysis_.checkOutput(realData, expectedOut_);
    }

    BOOST_AUTO_TEST_CASE(blackman)
    {
        BOOST_TEST((initialized_ = analysis_.initialize("../../test cases/WinBlackmanTest.xml", "win.in", workingSet_, "win.out", expectedOut_)), "Loading test data failed.");
        if (!initialized_)
            return;

        BOOST_TEST_MESSAGE("Checking Blackman window samples.");

        jw::BlackmanWindow<std::integral_constant<int, kSampleCnt_>, std::complex<double>> blackman;

        auto complexData = real2ComplexConverter_(workingSet_);
        blackman(&complexData[0]);
        auto realData = complex2RealConverter_(complexData);

        analysis_.checkOutput(realData, expectedOut_);
    }

    BOOST_AUTO_TEST_CASE(cosine)
    {
        BOOST_TEST((initialized_ = analysis_.initialize("../../test cases/WinCosineTest.xml", "win.in", workingSet_, "win.out", expectedOut_)), "Loading test data failed.");
        if (!initialized_)
            return;

        BOOST_TEST_MESSAGE("Checking Cosine window samples.");

        jw::CosineWindow<std::integral_constant<int, kSampleCnt_>, std::complex<double>> cosineWin;

        auto complexData = real2ComplexConverter_(workingSet_);
        cosineWin(&complexData[0]);
        auto realData = complex2RealConverter_(complexData);

        analysis_.checkOutput(realData, expectedOut_);
    }

    BOOST_AUTO_TEST_CASE(flat_top)
    {
        BOOST_TEST((initialized_ = analysis_.initialize("../../test cases/WinFlatTopTest.xml", "win.in", workingSet_, "win.out", expectedOut_)), "Loading test data failed.");
        if (!initialized_)
            return;

        BOOST_TEST_MESSAGE("Checking Flat Top window samples.");

        jw::FlatTopWindow<std::integral_constant<int, kSampleCnt_>, std::complex<double>> flatTopWin;

        auto complexData = real2ComplexConverter_(workingSet_);
        flatTopWin(&complexData[0]);
        auto realData = complex2RealConverter_(complexData);

        analysis_.checkOutput(realData, expectedOut_);
    }

    BOOST_AUTO_TEST_CASE(hamming)
    {
        BOOST_TEST((initialized_ = analysis_.initialize("../../test cases/WinHammingTest.xml", "win.in", workingSet_, "win.out", expectedOut_)), "Loading test data failed.");
        if (!initialized_)
            return;

        BOOST_TEST_MESSAGE("Checking Hamming window samples.");

        jw::HammingWindow<std::integral_constant<int, kSampleCnt_>, std::complex<double>> hammingWin;

        auto complexData = real2ComplexConverter_(workingSet_);
        hammingWin(&complexData[0]);
        auto realData = complex2RealConverter_(complexData);

        analysis_.checkOutput(realData, expectedOut_);
    }

    BOOST_AUTO_TEST_CASE(von_hann)
    {
        BOOST_TEST((initialized_ = analysis_.initialize("../../test cases/WinvonHannTest.xml", "win.in", workingSet_, "win.out", expectedOut_)), "Loading test data failed.");
        if (!initialized_)
            return;

        BOOST_TEST_MESSAGE("Checking von Hann window samples.");

        jw::VonHannWindow<std::integral_constant<int, kSampleCnt_>, std::complex<double>> vonHannWin;

        auto complexData = real2ComplexConverter_(workingSet_);
        vonHannWin(&complexData[0]);
        auto realData = complex2RealConverter_(complexData);

        analysis_.checkOutput(realData, expectedOut_);
    }

    BOOST_AUTO_TEST_CASE(welch)
    {
        BOOST_TEST((initialized_ = analysis_.initialize("../../test cases/WinWelchTest.xml", "win.in", workingSet_, "win.out", expectedOut_)), "Loading test data failed.");
        if (!initialized_)
            return;

        BOOST_TEST_MESSAGE("Checking Welch window samples.");

        jw::WelchWindow<std::integral_constant<int, kSampleCnt_>, std::complex<double>> welchWin;

        auto complexData = real2ComplexConverter_(workingSet_);
        welchWin(&complexData[0]);
        auto realData = complex2RealConverter_(complexData);

        analysis_.checkOutput(realData, expectedOut_);
    }

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: JoergWarthemann/jeanbaptiste

max_issues_repo_name: JoergWarthemann/jeanbaptiste

max_forks_repo_name: JoergWarthemann/jeanbaptiste


text:
// Copyright 2016 Alex Silva Torres
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// 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.

#include "runner.h"

#include <cstdlib>

#include <string>
#include <memory>
#include <iostream>
#include <fstream>
#include <functional>
#include <readline/readline.h>
#include <readline/history.h>
#include <boost/filesystem.hpp>

#include "env-shell.h"
#include "objects/str-object.h"
#include "utils/dir.h"

namespace shpp {

static sigjmp_buf ctrlc_buf;

void HandleSignals(int signo) {
  if (signo == SIGINT) {
    std::cout << "\n";
    siglongjmp(ctrlc_buf, 1);
  }
}

Runner::Runner(): interpreter_(true) {
  using namespace internal;

  internal::EnvShell::instance()->InitShell();
}

void Runner::Exec(std::string name, std::vector<std::string>&& args) {
  try {
    internal::ScriptStream file(name);

    if (!file.IsOpen()) {
      throw std::invalid_argument((boost::format("can't open file: %1%")%name)
          .str());
    }

    interpreter_.Exec(file, std::move(args));
  } catch (RunTimeError& e) {
    std::cout << "File: '" << e.file()  << "'"
              << "\n  line: " << e.pos().line
              << "  >> " << e.line_error() << "\n"
              << "Error: " << e.what() << "\n\n";

    for (auto& msg: e.messages()) {
      std::cout << "File: '" << msg.file()  << "'"
                << "\n  line: " << msg.line()
                << "  >> " << msg.line_error() << "\n"
                << "Error: " << msg.msg() << "\n\n";
    }
  } catch (std::invalid_argument& e) {
    std::cout << "Error: " << e.what() << "\n\n";
  }
}

void Runner::ExecInterative() {
  namespace fs = boost::filesystem;
  using std::placeholders::_1;

  if (signal(SIGINT, HandleSignals) == SIG_ERR) {
    std::cerr << "failed to register interrupts with kernel\n";
    exit(-1);
  }

  internal::EnvShell::instance()->interective_exec(true);

  fs::path path_rc = fs::path(internal::GetHome() + "/.shpprc");

  if (fs::exists(path_rc)) {
    Exec(path_rc.string());
  }

  while (true) {
    try {
      interpreter_.ExecInterative([&](internal::Executor* exec, bool concat) {
        char *input;
        std::string str_source;
        std::string prompt;

        if (concat) {
          prompt = "| ";

          internal::ObjectPtr obj_func = interpreter_.LookupSymbol("PS2");

          if (obj_func) {
            std::vector<internal::ObjectPtr> params;
            internal::ObjectPtr obj = obj_func->Call(exec, std::move(params));

            if (obj->type() == internal::Object::ObjectType::STRING) {
              prompt = static_cast<internal::StringObject&>(*obj).value();
            }
          }
        } else {
          prompt = "> ";

          internal::ObjectPtr obj_func = interpreter_.LookupSymbol("PS1");

          if (obj_func) {
            std::vector<internal::ObjectPtr> params;
            internal::ObjectPtr obj = obj_func->Call(exec, std::move(params));

            if (obj->type() == internal::Object::ObjectType::STRING) {
              prompt = static_cast<internal::StringObject&>(*obj).value();
            }
          }
        }

        while (sigsetjmp(ctrlc_buf, 1) != 0 );

        input = readline(prompt.c_str());

        if (input == nullptr) {
          exit(0);
        }

        str_source = input;
        add_history(input);
        free(input);
        return str_source;
      });
    } catch (RunTimeError& e) {
      std::cout << "Error: " << e.pos().line << ": " << e.pos().col
                << ": " << e.what() << "\n\n";

      for (auto& msg: e.messages()) {
        std::cout << "Error: " << msg.line() << ": " << msg.pos()
                  << ": " << msg.msg() << "\n";
      }
    }
  }
}

}

max_stars_repo_name: aminya/shell-plus-plus

max_issues_repo_name: aminya/shell-plus-plus

max_forks_repo_name: aminya/shell-plus-plus


text:
/* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of NVIDIA CORPORATION 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 ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <fstream>

#include <boost/serialization/vector.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/bitset.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>

#include "util/accelergy_interface.hpp"
#include "util/banner.hpp"
#include "mapping/parser.hpp"
#include "compound-config/compound-config.hpp"

//--------------------------------------------//
//                Application                 //
//--------------------------------------------//

class Application
{
 protected:
  problem::Workload workload_;
  model::Engine::Specs arch_specs_;

  // The mapping has to be a dynamic object because we cannot
  // instantiate it before the problem shape has been parsed. UGH.
  Mapping* mapping_;

 private:

  // Serialization
  friend class boost::serialization::access;
  template <class Archive>
  void serialize(Archive& ar, const unsigned int version=0)
  {
    if(version == 0)
    {
      ar& BOOST_SERIALIZATION_NVP(workload_);
    }
  }

 public:

  Application(config::CompoundConfig* config)
  {
    auto rootNode = config->getRoot();

    // Evaluator application configuration.
    bool verbose = false;
    if (rootNode.exists("evaluator")) {
      auto evaluator = rootNode.lookup("evaluator");
      evaluator.lookupValue("verbose", verbose);
    }
    if (verbose) {
      for (auto& line: banner)
        std::cout << line << std::endl;
      std::cout << std::endl;
    }

    // Problem configuration.
    auto problem = rootNode.lookup("problem");
    problem::ParseWorkload(problem, workload_);
    if (verbose)
      std::cout << "Problem configuration complete." << std::endl;

    // Architecture configuration.
    config::CompoundConfigNode arch;
    if (rootNode.exists("arch")) {
      arch = rootNode.lookup("arch");
    } else if (rootNode.exists("architecture")) {
      arch = rootNode.lookup("architecture");
    }
    arch_specs_ = model::Engine::ParseSpecs(arch);

    if (rootNode.exists("ERT")) {
      auto ert = rootNode.lookup("ERT");
      if (verbose)
        std::cout << "Found Accelergy ERT (energy reference table), replacing internal energy model." << std::endl;
      arch_specs_.topology.ParseAccelergyERT(ert);
    } else {
#ifdef USE_ACCELERGY
      // Call accelergy ERT with all input files
      if (arch.exists("subtree") || arch.exists("local")) {
        accelergy::invokeAccelergy(config->inFiles);
        auto ertConfig = new config::CompoundConfig("ERT.yaml");
        auto ert = ertConfig->getRoot().lookup("ERT");
        if (verbose)
          std::cout << "Generate Accelergy ERT (energy reference table) to replace internal energy model." << std::endl;
        arch_specs_.topology.ParseAccelergyERT(ert);
      }
#endif
    }

    if (verbose)
      std::cout << "Architecture configuration complete." << std::endl;

    // Mapping configuration: expressed as a mapspace or mapping.
    auto mapping = rootNode.lookup("mapping");
    mapping_ = new Mapping(mapping::ParseAndConstruct(mapping, arch_specs_, workload_));
    if (verbose)
      std::cout << "Mapping construction complete." << std::endl;
  }

  // This class does not support being copied
  Application(const Application&) = delete;
  Application& operator=(const Application&) = delete;

  ~Application()
  {
    if (mapping_)
      delete mapping_;
  }

  // Run the evaluation.
  void Run()
  {
    // Output file names.
    const std::string out_prefix = "timeloop-model.";
    const std::string stats_file_name = out_prefix + "stats.txt";
    const std::string xml_file_name = out_prefix + "map+stats.xml";
    const std::string map_txt_file_name = out_prefix + "map.txt";

    model::Engine engine;
    engine.Spec(arch_specs_);

    auto& mapping = *mapping_;

    auto success = engine.Evaluate(mapping, workload_);
    if (!std::accumulate(success.begin(), success.end(), true, std::logical_and<>{}))
    {
      std::cout << "Illegal mapping, evaluation failed." << std::endl;
      return;
    }

    if (engine.IsEvaluated())
    {
      std::cout << "Utilization = " << std::setw(4) << std::fixed << std::setprecision(2) << engine.Utilization()
                << " | pJ/MACC = " << std::setw(8) << std::fixed << std::setprecision(3) << engine.Energy() /
          engine.GetTopology().GetArithmeticLevel()->MACCs() << std::endl;

      std::ofstream map_txt_file(map_txt_file_name);
      mapping.PrettyPrint(map_txt_file, arch_specs_.topology.StorageLevelNames(), engine.GetTopology().TileSizes());
      map_txt_file.close();

      std::ofstream stats_file(stats_file_name);
      stats_file << engine << std::endl;
      stats_file.close();
    }

    // Print the engine stats and mapping to an XML file
    std::ofstream ofs(xml_file_name);
    boost::archive::xml_oarchive ar(ofs);
    ar << BOOST_SERIALIZATION_NVP(engine);
    ar << BOOST_SERIALIZATION_NVP(mapping);
    const Application* a = this;
    ar << BOOST_SERIALIZATION_NVP(a);
  }
};

max_stars_repo_name: rbshi/timeloop

max_issues_repo_name: rbshi/timeloop

max_forks_repo_name: rbshi/timeloop