A port of the irrlicht XML parser library.

Files at this revision

API Documentation at this revision

Comitter:
hlipka
Date:
Wed Nov 17 20:19:41 2010 +0000
Commit message:
initial version

Changed in this revision

CXMLReaderImpl.h Show annotated file Show diff for this revision Revisions of this file
fast_atof.h Show annotated file Show diff for this revision Revisions of this file
heapsort.h Show annotated file Show diff for this revision Revisions of this file
irrArray.h Show annotated file Show diff for this revision Revisions of this file
irrString.h Show annotated file Show diff for this revision Revisions of this file
irrTypes.h Show annotated file Show diff for this revision Revisions of this file
irrXML.cpp Show annotated file Show diff for this revision Revisions of this file
irrXML.h Show annotated file Show diff for this revision Revisions of this file
stringReader.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CXMLReaderImpl.h	Wed Nov 17 20:19:41 2010 +0000
@@ -0,0 +1,797 @@
+// Copyright (C) 2002-2005 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine" and the "irrXML" project.
+// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
+
+#ifndef __ICXML_READER_IMPL_H_INCLUDED__
+#define __ICXML_READER_IMPL_H_INCLUDED__
+
+#include "irrXML.h"
+#include "irrString.h"
+#include "irrArray.h"
+#include "fast_atof.h"
+
+#ifdef _DEBUG
+#define IRR_DEBUGPRINT(x) printf((x));
+#else // _DEBUG 
+#define IRR_DEBUGPRINT(x)
+#endif // _DEBUG
+
+
+namespace irr
+{
+namespace io
+{
+
+
+//! implementation of the IrrXMLReader
+template<class char_type, class superclass>
+class CXMLReaderImpl : public IIrrXMLReader<char_type, superclass>
+{
+public:
+
+	//! Constructor
+	CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true)
+		: TextData(0), P(0), TextSize(0), TextBegin(0), CurrentNodeType(EXN_NONE),
+		SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII)
+	{
+		if (!callback)
+			return;
+
+		storeTargetFormat();
+
+		// read whole xml file
+
+		readFile(callback);
+		
+		// clean up
+
+		if (deleteCallBack)
+			delete callback;
+
+		// create list with special characters
+
+		createSpecialCharacterList();
+
+		// set pointer to text begin
+		P = TextBegin;
+	}
+    	
+
+	//! Destructor
+	virtual ~CXMLReaderImpl()
+	{
+		delete [] TextData;
+	}
+
+
+	//! Reads forward to the next xml node. 
+	//! \return Returns false, if there was no further node. 
+	virtual bool read()
+	{
+		// if not end reached, parse the node
+		if (P && (unsigned int)(P - TextBegin) < TextSize - 1 && *P != 0)
+		{
+			parseCurrentNode();
+			return true;
+		}
+
+		_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
+		return false;
+	}
+
+
+	//! Returns the type of the current XML node.
+	virtual EXML_NODE getNodeType() const
+	{
+		return CurrentNodeType;
+	}
+
+
+	//! Returns attribute count of the current XML node.
+	virtual int getAttributeCount() const
+	{
+		return Attributes.size();
+	}
+
+
+	//! Returns name of an attribute.
+	virtual const char_type* getAttributeName(int idx) const
+	{
+		if (idx < 0 || idx >= (int)Attributes.size())
+			return 0;
+
+		return Attributes[idx].Name.c_str();
+	}
+
+
+	//! Returns the value of an attribute. 
+	virtual const char_type* getAttributeValue(int idx) const
+	{
+		if (idx < 0 || idx >= (int)Attributes.size())
+			return 0;
+
+		return Attributes[idx].Value.c_str();
+	}
+
+
+	//! Returns the value of an attribute. 
+	virtual const char_type* getAttributeValue(const char_type* name) const
+	{
+		const SAttribute* attr = getAttributeByName(name);
+		if (!attr)
+			return 0;
+
+		return attr->Value.c_str();
+	}
+
+
+	//! Returns the value of an attribute
+	virtual const char_type* getAttributeValueSafe(const char_type* name) const
+	{
+		const SAttribute* attr = getAttributeByName(name);
+		if (!attr)
+			return EmptyString.c_str();
+
+		return attr->Value.c_str();
+	}
+
+
+
+	//! Returns the value of an attribute as integer. 
+	virtual int getAttributeValueAsInt(const char_type* name) const
+	{
+		return (int)getAttributeValueAsFloat(name);
+	}
+
+
+	//! Returns the value of an attribute as integer. 
+    virtual int getAttributeValueAsInt(int idx) const
+	{
+		return (int)getAttributeValueAsFloat(idx);
+	}
+
+
+	//! Returns the value of an attribute as float. 
+	virtual float getAttributeValueAsFloat(const char_type* name) const
+	{
+		const SAttribute* attr = getAttributeByName(name);
+		if (!attr)
+			return 0;
+
+		core::stringc c = attr->Value.c_str();
+		return core::fast_atof(c.c_str());
+	}
+
+
+	//! Returns the value of an attribute as float. 
+	virtual float getAttributeValueAsFloat(int idx) const
+	{
+		const char_type* attrvalue = getAttributeValue(idx);
+		if (!attrvalue)
+			return 0;
+
+		core::stringc c = attrvalue;
+		return core::fast_atof(c.c_str());
+	}
+
+
+	//! Returns the name of the current node.
+	virtual const char_type* getNodeName() const
+	{
+		return NodeName.c_str();
+	}
+
+
+	//! Returns data of the current node.
+	virtual const char_type* getNodeData() const
+	{
+		return NodeName.c_str();
+	}
+
+
+	//! Returns if an element is an empty element, like <foo />
+	virtual bool isEmptyElement() const
+	{
+		return IsEmptyElement;
+	}
+
+	//! Returns format of the source xml file.
+	virtual ETEXT_FORMAT getSourceFormat() const
+	{
+		return SourceFormat;
+	}
+
+	//! Returns format of the strings returned by the parser.
+	virtual ETEXT_FORMAT getParserFormat() const
+	{
+		return TargetFormat;
+	}
+
+private:
+
+	// Reads the current xml node
+	void parseCurrentNode()
+	{
+		char_type* start = P;
+
+		// more forward until '<' found
+		while(*P != L'<' && *P)
+			++P;
+
+		if (!*P)
+			return;
+
+		if (P - start > 0)
+		{
+			// we found some text, store it
+			if (setText(start, P))
+				return;
+		}
+
+		++P;
+
+		// based on current token, parse and report next element
+		switch(*P)
+		{
+		case L'/':
+			parseClosingXMLElement(); 
+			break;
+		case L'?':
+			ignoreDefinition();	
+			break;
+		case L'!':
+			if (!parseCDATA())
+				parseComment();	
+			break;
+		default:
+			parseOpeningXMLElement();
+			break;
+		}
+	}
+
+
+	//! sets the state that text was found. Returns true if set should be set
+	bool setText(char_type* start, char_type* end)
+	{
+		// check if text is more than 2 characters, and if not, check if there is 
+		// only white space, so that this text won't be reported
+		if (end - start < 3)
+		{
+			char_type* p = start;
+			for(; p != end; ++p)
+				if (!isWhiteSpace(*p))
+					break;
+
+			if (p == end)
+				return false;
+		}
+
+		// set current text to the parsed text, and replace xml special characters
+		core::string<char_type> s(start, (int)(end - start));
+		NodeName = replaceSpecialCharacters(s);
+
+		// current XML node type is text
+		CurrentNodeType = EXN_TEXT;
+
+		return true;
+	}
+
+
+
+	//! ignores an xml definition like <?xml something />
+	void ignoreDefinition()
+	{
+		CurrentNodeType = EXN_UNKNOWN;
+
+		// move until end marked with '>' reached
+		while(*P != L'>')
+			++P;
+
+		++P;
+	}
+
+
+	//! parses a comment
+	void parseComment()
+	{
+		CurrentNodeType = EXN_COMMENT;
+		P += 1;
+
+		char_type *pCommentBegin = P;
+
+		int count = 1;
+
+		// move until end of comment reached
+		while(count)
+		{
+			if (*P == L'>')
+				--count;
+			else
+			if (*P == L'<')
+				++count;
+
+			++P;
+		}
+
+		P -= 3;
+		NodeName = core::string<char_type>(pCommentBegin+2, (int)(P - pCommentBegin-2));
+		P += 3;
+	}
+
+
+	//! parses an opening xml element and reads attributes
+	void parseOpeningXMLElement()
+	{
+		CurrentNodeType = EXN_ELEMENT;
+		IsEmptyElement = false;
+		Attributes.clear();
+
+		// find name
+		const char_type* startName = P;
+
+		// find end of element
+		while(*P != L'>' && !isWhiteSpace(*P))
+			++P;
+
+		const char_type* endName = P;
+
+		// find Attributes
+		while(*P != L'>')
+		{
+			if (isWhiteSpace(*P))
+				++P;
+			else
+			{
+				if (*P != L'/')
+				{
+					// we've got an attribute
+
+					// read the attribute names
+					const char_type* attributeNameBegin = P;
+
+					while(!isWhiteSpace(*P) && *P != L'=')
+						++P;
+
+					const char_type* attributeNameEnd = P;
+					++P;
+
+					// read the attribute value
+					// check for quotes and single quotes, thx to murphy
+					while( (*P != L'\"') && (*P != L'\'') && *P) 
+						++P;
+
+					if (!*P) // malformatted xml file
+						return;
+
+					const char_type attributeQuoteChar = *P;
+
+					++P;
+					const char_type* attributeValueBegin = P;
+					
+					while(*P != attributeQuoteChar && *P)
+						++P;
+
+					if (!*P) // malformatted xml file
+						return;
+
+					const char_type* attributeValueEnd = P;
+					++P;
+
+					SAttribute attr;
+					attr.Name = core::string<char_type>(attributeNameBegin, 
+						(int)(attributeNameEnd - attributeNameBegin));
+
+					core::string<char_type> s(attributeValueBegin, 
+						(int)(attributeValueEnd - attributeValueBegin));
+
+					attr.Value = replaceSpecialCharacters(s);
+					Attributes.push_back(attr);
+				}
+				else
+				{
+					// tag is closed directly
+					++P;
+					IsEmptyElement = true;
+					break;
+				}
+			}
+		}
+
+		// check if this tag is closing directly
+		if (endName > startName && *(endName-1) == L'/')
+		{
+			// directly closing tag
+			IsEmptyElement = true;
+			endName--;
+		}
+		
+		NodeName = core::string<char_type>(startName, (int)(endName - startName));
+
+		++P;
+	}
+
+
+	//! parses an closing xml tag
+	void parseClosingXMLElement()
+	{
+		CurrentNodeType = EXN_ELEMENT_END;
+		IsEmptyElement = false;
+		Attributes.clear();
+
+		++P;
+		const char_type* pBeginClose = P;
+
+		while(*P != L'>')
+			++P;
+
+		NodeName = core::string<char_type>(pBeginClose, (int)(P - pBeginClose));
+		++P;
+	}
+
+	//! parses a possible CDATA section, returns false if begin was not a CDATA section
+	bool parseCDATA()
+	{
+		if (*(P+1) != L'[')
+			return false;
+
+		CurrentNodeType = EXN_CDATA;
+
+		// skip '<![CDATA['
+		int count=0;
+		while( *P && count<8 )
+		{
+			++P;
+			++count;
+		}
+
+		if (!*P)
+			return true;
+
+		char_type *cDataBegin = P;
+		char_type *cDataEnd = 0;
+
+		// find end of CDATA
+		while(*P && !cDataEnd)
+		{
+			if (*P == L'>' && 
+			   (*(P-1) == L']') &&
+			   (*(P-2) == L']'))
+			{
+				cDataEnd = P - 2;
+			}
+
+			++P;
+		}
+
+		if ( cDataEnd )
+			NodeName = core::string<char_type>(cDataBegin, (int)(cDataEnd - cDataBegin));
+		else
+			NodeName = "";
+
+		return true;
+	}
+
+
+	// structure for storing attribute-name pairs
+	struct SAttribute
+	{
+		core::string<char_type> Name;
+		core::string<char_type> Value;
+	};
+
+	// finds a current attribute by name, returns 0 if not found
+	const SAttribute* getAttributeByName(const char_type* name) const
+	{
+		if (!name)
+			return 0;
+
+		core::string<char_type> n = name;
+
+		for (int i=0; i<(int)Attributes.size(); ++i)
+			if (Attributes[i].Name == n)
+				return &Attributes[i];
+
+		return 0;
+	}
+
+	// replaces xml special characters in a string and creates a new one
+	core::string<char_type> replaceSpecialCharacters(
+		core::string<char_type>& origstr)
+	{
+		int pos = origstr.findFirst(L'&');
+		int oldPos = 0;
+
+		if (pos == -1)
+			return origstr;
+
+		core::string<char_type> newstr;
+
+		while(pos != -1 && pos < origstr.size()-2)
+		{
+			// check if it is one of the special characters
+
+			int specialChar = -1;
+			for (int i=0; i<(int)SpecialCharacters.size(); ++i)
+			{
+				const char_type* p = &origstr.c_str()[pos]+1;
+
+				if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1))
+				{
+					specialChar = i;
+					break;
+				}
+			}
+
+			if (specialChar != -1)
+			{
+				newstr.append(origstr.subString(oldPos, pos - oldPos));
+				newstr.append(SpecialCharacters[specialChar][0]);
+				pos += SpecialCharacters[specialChar].size();
+			}
+			else
+			{
+				newstr.append(origstr.subString(oldPos, pos - oldPos + 1));
+				pos += 1;
+			}
+
+			// find next &
+			oldPos = pos;
+			pos = origstr.findNext(L'&', pos);		
+		}
+
+		if (oldPos < origstr.size()-1)
+			newstr.append(origstr.subString(oldPos, origstr.size()-oldPos));
+
+		return newstr;
+	}
+
+
+
+	//! reads the xml file and converts it into the wanted character format.
+	bool readFile(IFileReadCallBack* callback)
+	{
+		int size = callback->getSize();		
+		size += 4; // We need two terminating 0's at the end.
+		           // For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4.
+
+		char* data8 = new char[size];
+
+		if (!callback->read(data8, size-4))
+		{
+			delete [] data8;
+			return false;
+		}
+
+		// add zeros at end
+
+		data8[size-1] = 0;
+		data8[size-2] = 0;
+		data8[size-3] = 0;
+		data8[size-4] = 0;
+
+		char16* data16 = reinterpret_cast<char16*>(data8);
+		char32* data32 = reinterpret_cast<char32*>(data8);	
+
+		// now we need to convert the data to the desired target format
+		// based on the byte order mark.
+
+		const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF;
+		const int UTF16_BE = 0xFFFE;
+		const int UTF16_LE = 0xFEFF;
+		const int UTF32_BE = 0xFFFE0000;
+		const int UTF32_LE = 0x0000FEFF;
+
+		// check source for all utf versions and convert to target data format
+		
+		if (size >= 4 && data32[0] == (char32)UTF32_BE)
+		{
+			// UTF-32, big endian
+			SourceFormat = ETF_UTF32_BE;
+			convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header
+		}
+		else
+		if (size >= 4 && data32[0] == (char32)UTF32_LE)
+		{
+			// UTF-32, little endian
+			SourceFormat = ETF_UTF32_LE;
+			convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header
+		}
+		else
+		if (size >= 2 && data16[0] == UTF16_BE)
+		{
+			// UTF-16, big endian
+			SourceFormat = ETF_UTF16_BE;
+			convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header
+		}
+		else
+		if (size >= 2 && data16[0] == UTF16_LE)
+		{
+			// UTF-16, little endian
+			SourceFormat = ETF_UTF16_LE;
+			convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header
+		}
+		else
+		if (size >= 3 && data8[0] == UTF8[0] && data8[1] == UTF8[1] && data8[2] == UTF8[2])
+		{
+			// UTF-8
+			SourceFormat = ETF_UTF8;
+			convertTextData(data8+3, data8, size); // data8+3 because we need to skip the header
+		}
+		else
+		{
+			// ASCII
+			SourceFormat = ETF_ASCII;
+			convertTextData(data8, data8, size);
+		}
+
+		return true;
+	}
+
+
+	//! converts the text file into the desired format.
+	//! \param source: begin of the text (without byte order mark)
+	//! \param pointerToStore: pointer to text data block which can be
+	//! stored or deleted based on the nesessary conversion.
+	//! \param sizeWithoutHeader: Text size in characters without header
+	template<class src_char_type>
+	void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader)
+	{
+		// convert little to big endian if necessary
+		if (sizeof(src_char_type) > 1 && 
+			isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat))
+			convertToLittleEndian(source);
+
+		// check if conversion is necessary:
+		if (sizeof(src_char_type) == sizeof(char_type))
+		{
+			// no need to convert
+			TextBegin = (char_type*)source;
+			TextData = (char_type*)pointerToStore;
+			TextSize = sizeWithoutHeader;
+		}
+		else
+		{
+			// convert source into target data format. 
+			// TODO: implement a real conversion. This one just 
+			// copies bytes. This is a problem when there are 
+			// unicode symbols using more than one character.
+
+			TextData = new char_type[sizeWithoutHeader];
+
+			for (int i=0; i<sizeWithoutHeader; ++i)
+				TextData[i] = (char_type)source[i];
+
+			TextBegin = TextData;
+			TextSize = sizeWithoutHeader;
+
+			// delete original data because no longer needed
+			delete [] pointerToStore;
+		}
+	}
+
+	//! converts whole text buffer to little endian
+	template<class src_char_type>
+	void convertToLittleEndian(src_char_type* t)
+	{
+		if (sizeof(src_char_type) == 4) 
+		{
+			// 32 bit
+
+			while(*t)
+			{
+				*t = ((*t & 0xff000000) >> 24) |
+				     ((*t & 0x00ff0000) >> 8)  |
+				     ((*t & 0x0000ff00) << 8)  |
+				     ((*t & 0x000000ff) << 24);
+				++t;
+			}
+		}
+		else
+		{
+			// 16 bit 
+
+			while(*t)
+			{
+				*t = (*t >> 8) | (*t << 8);
+				++t;
+			}
+		}
+	}
+
+	//! returns if a format is little endian
+	inline bool isLittleEndian(ETEXT_FORMAT f)
+	{
+		return f == ETF_ASCII ||
+		       f == ETF_UTF8 ||
+		       f == ETF_UTF16_LE ||
+		       f == ETF_UTF32_LE;
+	}
+
+
+	//! returns true if a character is whitespace
+	inline bool isWhiteSpace(char_type c)
+	{
+		return (c==' ' || c=='\t' || c=='\n' || c=='\r');
+	}
+
+
+	//! generates a list with xml special characters
+	void createSpecialCharacterList()
+	{
+		// list of strings containing special symbols, 
+		// the first character is the special character,
+		// the following is the symbol string without trailing &.
+
+		SpecialCharacters.push_back("&amp;");
+		SpecialCharacters.push_back("<lt;");
+		SpecialCharacters.push_back(">gt;");
+		SpecialCharacters.push_back("\"quot;");
+		SpecialCharacters.push_back("'apos;");
+		
+	}
+
+
+	//! compares the first n characters of the strings
+	bool equalsn(const char_type* str1, const char_type* str2, int len)
+	{
+		int i;
+		for(i=0; str1[i] && str2[i] && i < len; ++i)
+			if (str1[i] != str2[i])
+				return false;
+
+		// if one (or both) of the strings was smaller then they
+		// are only equal if they have the same lenght
+		return (i == len) || (str1[i] == 0 && str2[i] == 0);
+	}
+
+
+	//! stores the target text format
+	void storeTargetFormat()
+	{
+		// get target format. We could have done this using template specialization,
+		// but VisualStudio 6 don't like it and we want to support it.
+
+		switch(sizeof(char_type))
+		{
+		case 1: 
+			TargetFormat = ETF_UTF8;
+			break;
+		case 2: 
+			TargetFormat = ETF_UTF16_LE;
+			break;
+		case 4: 
+			TargetFormat = ETF_UTF32_LE;
+			break;
+		default:
+			TargetFormat = ETF_ASCII; // should never happen.
+		}
+	}
+
+
+	// instance variables:
+
+	char_type* TextData;         // data block of the text file
+	char_type* P;                // current point in text to parse
+	char_type* TextBegin;        // start of text to parse
+	unsigned int TextSize;       // size of text to parse in characters, not bytes
+
+	EXML_NODE CurrentNodeType;   // type of the currently parsed node
+	ETEXT_FORMAT SourceFormat;   // source format of the xml file
+	ETEXT_FORMAT TargetFormat;   // output format of this parser
+
+	core::string<char_type> NodeName;    // name of the node currently in
+	core::string<char_type> EmptyString; // empty string to be returned by getSafe() methods
+
+	bool IsEmptyElement;       // is the currently parsed node empty?
+
+	core::array< core::string<char_type> > SpecialCharacters; // see createSpecialCharacterList()
+
+	core::array<SAttribute> Attributes; // attributes of current element
+	
+}; // end CXMLReaderImpl
+
+
+} // end namespace
+} // end namespace
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fast_atof.h	Wed Nov 17 20:19:41 2010 +0000
@@ -0,0 +1,138 @@
+// Copyright (C) 2002-2005 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine" and the "irrXML" project.
+// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
+
+#ifndef __FAST_A_TO_F_H_INCLUDED__
+#define __FAST_A_TO_F_H_INCLUDED__
+
+#include <stdlib.h>
+#include <math.h>
+
+namespace irr
+{
+namespace core
+{
+
+const float fast_atof_table[] =	{
+										0.f,
+										0.1f,
+										0.01f,
+										0.001f,
+										0.0001f,
+										0.00001f,
+										0.000001f,
+										0.0000001f,
+										0.00000001f,
+										0.000000001f,
+										0.0000000001f,
+										0.00000000001f,
+										0.000000000001f,
+										0.0000000000001f,
+										0.00000000000001f,
+										0.000000000000001f
+									};
+
+//! Provides a fast function for converting a string into a float,
+//! about 6 times faster than atof in win32.
+// If you find any bugs, please send them to me, niko (at) irrlicht3d.org.
+inline char* fast_atof_move(char* c, float& out)
+{
+	bool inv = false;
+	char *t;
+	float f;
+
+	if (*c=='-')
+	{
+		c++;
+		inv = true;
+	}
+
+	f = (float)strtol(c, &t, 10);
+
+	c = t;
+
+	if (*c == '.')
+	{
+		c++;
+
+		float pl = (float)strtol(c, &t, 10);
+		pl *= fast_atof_table[t-c];
+
+		f += pl;
+
+		c = t;
+
+		if (*c == 'e')
+		{
+			++c;
+			float exp = (float)strtol(c, &t, 10);
+			f *= (float)pow(10.0f, exp);
+			c = t;
+		}
+	}
+
+	if (inv)
+		f *= -1.0f;
+	
+	out = f;
+	return c;
+}
+
+//! Provides a fast function for converting a string into a float,
+//! about 6 times faster than atof in win32.
+// If you find any bugs, please send them to me, niko (at) irrlicht3d.org.
+inline const char* fast_atof_move_const(const char* c, float& out)
+{
+	bool inv = false;
+	char *t;
+	float f;
+
+	if (*c=='-')
+	{
+		c++;
+		inv = true;
+	}
+
+	f = (float)strtol(c, &t, 10);
+
+	c = t;
+
+	if (*c == '.')
+	{
+		c++;
+
+		float pl = (float)strtol(c, &t, 10);
+		pl *= fast_atof_table[t-c];
+
+		f += pl;
+
+		c = t;
+
+		if (*c == 'e') 
+		{ 
+			++c; 
+			f32 exp = (f32)strtol(c, &t, 10); 
+			f *= (f32)powf(10.0f, exp); 
+			c = t; 
+		}
+	}
+
+	if (inv)
+		f *= -1.0f;
+	
+	out = f;
+	return c;
+}
+
+
+inline float fast_atof(const char* c)
+{
+	float ret;
+	fast_atof_move_const(c, ret);
+	return ret;
+}
+
+} // end namespace core
+}// end namespace irr
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/heapsort.h	Wed Nov 17 20:19:41 2010 +0000
@@ -0,0 +1,72 @@
+// Copyright (C) 2002-2005 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#ifndef __IRR_HEAPSORT_H_INCLUDED__
+#define __IRR_HEAPSORT_H_INCLUDED__
+
+#include "irrTypes.h"
+
+namespace irr
+{
+namespace core
+{
+
+//! Sinks an element into the heap.
+template<class T>
+inline void heapsink(T*array, s32 element, s32 max)
+{
+	while ((element<<1) < max)	// there is a left child
+	{
+		s32 j = (element<<1);
+	
+		if (j+1 < max && array[j] < array[j+1])
+			j = j+1;							// take right child
+
+		if (array[element] < array[j])
+		{
+			T t = array[j];						// swap elements
+			array[j] = array[element];
+			array[element] = t;
+			element = j;
+		}
+		else
+			return;
+	}
+}
+
+
+//! Sorts an array with size 'size' using heapsort.
+template<class T>
+inline void heapsort(T* array_, s32 size)
+{
+	// for heapsink we pretent this is not c++, where
+	// arrays start with index 0. So we decrease the array pointer,
+	// the maximum always +2 and the element always +1
+
+	T* virtualArray = array_ - 1;
+	s32 virtualSize = size + 2;
+	s32 i;
+
+	// build heap
+
+	for (i=((size-1)/2); i>=0; --i)	
+		heapsink(virtualArray, i+1, virtualSize-1);
+
+	// sort array
+
+	for (i=size-1; i>=0; --i)	
+	{
+		T t = array_[0];
+		array_[0] = array_[i];
+		array_[i] = t;
+		heapsink(virtualArray, 1, i + 1);
+	}
+}
+
+} // end namespace core
+} // end namespace irr
+
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/irrArray.h	Wed Nov 17 20:19:41 2010 +0000
@@ -0,0 +1,443 @@
+// Copyright (C) 2002-2005 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine" and the "irrXML" project.
+// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
+
+#ifndef __IRR_ARRAY_H_INCLUDED__
+#define __IRR_ARRAY_H_INCLUDED__
+
+#include "irrTypes.h"
+#include "heapsort.h"
+
+namespace irr
+{
+namespace core
+{
+
+//!	Self reallocating template array (like stl vector) with additional features.
+/** Some features are: Heap sorting, binary search methods, easier debugging.
+*/
+template <class T>
+class array
+{
+
+public:
+
+	array()
+		: data(0), used(0), allocated(0),
+			free_when_destroyed(true), is_sorted(true)
+	{
+	}
+
+	//! Constructs a array and allocates an initial chunk of memory.
+	//! \param start_count: Amount of elements to allocate.
+	array(u32 start_count)
+		: data(0), used(0), allocated(0),
+			free_when_destroyed(true),	is_sorted(true)
+	{
+		reallocate(start_count);
+	}
+
+
+	//! Copy constructor
+	array(const array<T>& other)
+		: data(0)
+	{
+		*this = other;
+	}
+
+
+
+	//! Destructor. Frees allocated memory, if set_free_when_destroyed
+	//! was not set to false by the user before.
+	~array()
+	{
+		if (free_when_destroyed)
+			delete [] data;
+	}
+
+
+
+	//! Reallocates the array, make it bigger or smaller.
+	//! \param new_size: New size of array.
+	void reallocate(u32 new_size)
+	{
+		T* old_data = data;
+
+		data = new T[new_size];
+		allocated = new_size;
+		
+		s32 end = used < new_size ? used : new_size;
+		for (s32 i=0; i<end; ++i)
+			data[i] = old_data[i];
+
+		if (allocated < used)
+			used = allocated;
+		
+		delete [] old_data;
+	}
+
+	//! Adds an element at back of array. If the array is to small to 
+	//! add this new element, the array is made bigger.
+	//! \param element: Element to add at the back of the array.
+	void push_back(const T& element)
+	{
+		if (used + 1 > allocated)
+		{
+			// reallocate(used * 2 +1);
+			// this doesn't work if the element is in the same array. So
+			// we'll copy the element first to be sure we'll get no data
+			// corruption
+
+			T e;
+			e = element;           // copy element
+			reallocate(used * 2 +1); // increase data block
+			data[used++] = e;        // push_back
+			is_sorted = false; 
+			return;
+		}
+
+		data[used++] = element;
+		is_sorted = false;
+	}
+
+
+	//! Adds an element at the front of the array. If the array is to small to 
+	//! add this new element, the array is made bigger. Please note that this
+	//! is slow, because the whole array needs to be copied for this.
+	//! \param element: Element to add at the back of the array.
+	void push_front(const T& element)
+	{
+		if (used + 1 > allocated)
+			reallocate(used * 2 +1);
+
+		for (int i=(int)used; i>0; --i)
+			data[i] = data[i-1];
+
+		data[0] = element;
+		is_sorted = false;
+		++used;
+	}
+
+	
+	//! Insert item into array at specified position. Please use this
+	//! only if you know what you are doing (possible performance loss). 
+	//! The preferred method of adding elements should be push_back().
+	//! \param element: Element to be inserted
+	//! \param index: Where position to insert the new element.
+	void insert(const T& element, u32 index=0) 
+	{
+		_IRR_DEBUG_BREAK_IF(index>used) // access violation
+
+		if (used + 1 > allocated)
+			reallocate(used * 2 +1);
+
+		for (u32 i=used++; i>index; i--) 
+			data[i] = data[i-1];
+
+		data[index] = element;
+		is_sorted = false;
+	}
+
+
+
+
+	//! Clears the array and deletes all allocated memory.
+	void clear()
+	{
+		delete [] data;
+		data = 0;
+		used = 0;
+		allocated = 0;
+		is_sorted = true;
+	}
+
+
+
+	//! Sets pointer to new array, using this as new workspace.
+	//! \param newPointer: Pointer to new array of elements.
+	//! \param size: Size of the new array.
+	void set_pointer(T* newPointer, u32 size)
+	{
+		delete [] data;
+		data = newPointer;
+		allocated = size;
+		used = size;
+		is_sorted = false;
+	}
+
+
+
+	//! Sets if the array should delete the memory it used.
+	//! \param f: If true, the array frees the allocated memory in its
+	//! destructor, otherwise not. The default is true.
+	void set_free_when_destroyed(bool f)
+	{
+		free_when_destroyed = f;
+	}
+
+
+
+	//! Sets the size of the array.
+	//! \param usedNow: Amount of elements now used.
+	void set_used(u32 usedNow)
+	{
+		if (allocated < usedNow)
+			reallocate(usedNow);
+
+		used = usedNow;
+	}
+
+
+
+	//! Assignement operator
+	void operator=(const array<T>& other)
+	{
+		if (data)
+			delete [] data;
+
+		//if (allocated < other.allocated)
+		if (other.allocated == 0)
+			data = 0;
+		else
+			data = new T[other.allocated];
+
+		used = other.used;
+		free_when_destroyed = other.free_when_destroyed;
+		is_sorted = other.is_sorted;
+		allocated = other.allocated;
+
+		for (u32 i=0; i<other.used; ++i)
+			data[i] = other.data[i];
+	}
+
+
+	//! Direct access operator
+	T& operator [](u32 index)
+	{
+		_IRR_DEBUG_BREAK_IF(index>=used) // access violation
+
+		return data[index];
+	}
+
+
+
+	//! Direct access operator
+	const T& operator [](u32 index) const
+	{
+		_IRR_DEBUG_BREAK_IF(index>=used) // access violation
+
+		return data[index];
+	}
+
+    //! Gets last frame
+	const T& getLast() const
+	{
+		_IRR_DEBUG_BREAK_IF(!used) // access violation
+
+		return data[used-1];
+	}
+
+    //! Gets last frame
+	T& getLast()
+	{
+		_IRR_DEBUG_BREAK_IF(!used) // access violation
+
+		return data[used-1];
+	}
+    
+
+	//! Returns a pointer to the array.
+	//! \return Pointer to the array.
+	T* pointer()
+	{
+		return data;
+	}
+
+
+
+	//! Returns a const pointer to the array.
+	//! \return Pointer to the array.
+	const T* const_pointer() const
+	{
+		return data;
+	}
+
+
+
+	//! Returns size of used array.
+	//! \return Size of elements in the array.
+	u32 size() const
+	{
+		return used;
+	}
+
+
+
+	//! Returns amount memory allocated.
+	//! \return Returns amount of memory allocated. The amount of bytes
+	//! allocated would  be allocated_size() * sizeof(ElementsUsed);
+	u32 allocated_size() const
+	{
+		return allocated;
+	}
+
+
+
+	//! Returns true if array is empty
+	//! \return True if the array is empty, false if not.
+	bool empty() const
+	{
+		return used == 0;
+	}
+
+
+
+	//! Sorts the array using heapsort. There is no additional memory waste and
+	//! the algorithm performs (O) n log n in worst case.
+	void sort()
+	{
+		if (is_sorted || used<2)
+			return;
+
+		heapsort(data, used);
+		is_sorted = true;
+	}
+
+
+
+	//! Performs a binary search for an element, returns -1 if not found.
+	//! The array will be sorted before the binary search if it is not
+	//! already sorted.
+	//! \param element: Element to search for.
+	//! \return Returns position of the searched element if it was found,
+	//! otherwise -1 is returned.
+	s32 binary_search(const T& element)
+	{
+		return binary_search(element, 0, used-1);
+	}
+
+
+
+	//! Performs a binary search for an element, returns -1 if not found.
+	//! The array will be sorted before the binary search if it is not
+	//! already sorted.
+	//! \param element: Element to search for.
+	//! \param left: First left index
+	//! \param right: Last right index.
+	//! \return Returns position of the searched element if it was found,
+	//! otherwise -1 is returned.
+	s32 binary_search(const T& element, s32 left, s32 right)
+	{
+		if (!used)
+			return -1;
+
+		sort();
+
+		s32 m;
+
+		do
+		{
+			m = (left+right)>>1;
+
+			if (element < data[m])
+				right = m - 1;
+			else
+				left = m + 1;
+
+		} while((element < data[m] || data[m] < element) && left<=right);
+
+		// this last line equals to:
+		// " while((element != array[m]) && left<=right);"
+		// but we only want to use the '<' operator.
+		// the same in next line, it is "(element == array[m])"
+
+		if (!(element < data[m]) && !(data[m] < element))
+			return m;
+
+		return -1;
+	}
+
+
+	//! Finds an element in linear time, which is very slow. Use
+	//! binary_search for faster finding. Only works if =operator is implemented.
+	//! \param element: Element to search for.
+	//! \return Returns position of the searched element if it was found,
+	//! otherwise -1 is returned.
+	s32 linear_search(T& element)
+	{
+		for (u32 i=0; i<used; ++i)
+			if (!(element < data[i]) && !(data[i] < element))
+				return (s32)i;
+
+		return -1;
+	}
+
+
+	//! Finds an element in linear time, which is very slow. Use
+	//! binary_search for faster finding. Only works if =operator is implemented.
+	//! \param element: Element to search for.
+	//! \return Returns position of the searched element if it was found,
+	//! otherwise -1 is returned.
+	s32 linear_reverse_search(T& element)
+	{
+		for (s32 i=used-1; i>=0; --i)
+			if (data[i] == element)
+				return (s32)i;
+
+		return -1;
+	}
+
+
+
+	//! Erases an element from the array. May be slow, because all elements 
+	//! following after the erased element have to be copied.
+	//! \param index: Index of element to be erased.
+	void erase(u32 index)
+	{
+		_IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation
+
+		for (u32 i=index+1; i<used; ++i)
+			data[i-1] = data[i];
+
+		--used;
+	}
+
+
+	//! Erases some elements from the array. may be slow, because all elements 
+	//! following after the erased element have to be copied.
+	//! \param index: Index of the first element to be erased.
+	//! \param count: Amount of elements to be erased.
+	void erase(u32 index, s32 count)
+	{
+		_IRR_DEBUG_BREAK_IF(index>=used || index<0 || count<1 || index+count>used) // access violation
+
+		for (u32 i=index+count; i<used; ++i)
+			data[i-count] = data[i];
+
+		used-= count;
+	}
+
+
+	//! Sets if the array is sorted
+	void set_sorted(bool _is_sorted)
+	{
+		is_sorted = _is_sorted;
+	}
+
+			
+	private:
+
+		T* data;
+		u32 allocated;
+		u32 used;
+		bool free_when_destroyed;
+		bool is_sorted;
+};
+
+
+} // end namespace core
+} // end namespace irr
+
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/irrString.h	Wed Nov 17 20:19:41 2010 +0000
@@ -0,0 +1,663 @@
+// Copyright (C) 2002-2005 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine" and the "irrXML" project.
+// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
+
+#ifndef __IRR_STRING_H_INCLUDED__
+#define __IRR_STRING_H_INCLUDED__
+
+#include "irrTypes.h"
+
+namespace irr
+{
+namespace core
+{
+
+//!	Very simple string class with some useful features.
+/**	string<c8> and string<wchar_t> work both with unicode AND ascii,
+so you can assign unicode to string<c8> and ascii to string<wchar_t> 
+(and the other way round) if your ever would want to. 
+Note that the conversation between both is not done using an encoding.
+
+Known bugs:
+Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the
+methods make_upper, make_lower and equals_ignore_case.
+*/
+template <class T>
+class string
+{
+public:
+
+	//! Default constructor
+	string()
+	: allocated(1), used(1), array(0)
+	{
+		array = new T[1];
+		array[0] = 0x0;
+	}
+
+
+
+	//! Constructor
+	string(const string<T>& other)
+	: allocated(0), used(0), array(0)
+	{
+		*this = other;
+	}
+
+
+	//! Constructs a string from an int
+	string(int number)
+	: allocated(0), used(0), array(0)
+	{
+		// store if negative and make positive
+
+		bool negative = false;
+		if (number < 0)
+		{
+			number *= -1;
+			negative = true;
+		}
+
+		// temporary buffer for 16 numbers
+
+		c8 tmpbuf[16];
+		tmpbuf[15] = 0;
+		s32 idx = 15;	
+
+		// special case '0'
+
+		if (!number) 
+		{
+			tmpbuf[14] = '0';
+			*this = &tmpbuf[14];
+			return;
+		}
+
+		// add numbers
+
+		while(number && idx)
+		{
+			idx--;	
+			tmpbuf[idx] = (c8)('0' + (number % 10));
+			number = number / 10;					
+		}
+
+		// add sign
+
+		if (negative)
+		{
+			idx--;
+			tmpbuf[idx] = '-';			
+		}
+
+		*this = &tmpbuf[idx];
+	}
+
+
+
+	//! Constructor for copying a string from a pointer with a given lenght
+	template <class B>
+	string(const B* c, s32 lenght)
+	: allocated(0), used(0), array(0)
+	{
+		if (!c)
+			return;
+
+        allocated = used = lenght+1;
+		array = new T[used];
+
+		for (s32 l = 0; l<lenght; ++l)
+			array[l] = (T)c[l];
+
+		array[lenght] = 0;
+	}
+
+
+
+	//! Constructor for unicode and ascii strings
+	template <class B>
+	string(const B* c)
+	: allocated(0), used(0), array(0)
+	{
+		*this = c;
+	}
+
+
+
+	//! destructor
+	~string()
+	{
+		delete [] array;
+	}
+
+
+
+	//! Assignment operator
+	string<T>& operator=(const string<T>& other) 
+	{
+		if (this == &other)
+			return *this;
+
+		delete [] array;
+		allocated = used = other.size()+1;
+		array = new T[used];
+
+		const T* p = other.c_str();
+		for (s32 i=0; i<used; ++i, ++p)
+			array[i] = *p;
+
+		return *this;
+	}
+
+
+
+	//! Assignment operator for strings, ascii and unicode
+	template <class B>
+	string<T>& operator=(const B* c) 
+	{
+		if (!c)
+		{
+			if (!array)
+			{
+				array = new T[1];
+				allocated = 1;
+				used = 1;
+			}
+			array[0] = 0x0;
+			return *this;
+		}
+
+		if ((void*)c == (void*)array)
+			return *this;
+
+		s32 len = 0;
+		const B* p = c;
+		while(*p)
+		{
+			++len;
+			++p;
+		}
+
+		// we'll take the old string for a while, because the new string could be
+		// a part of the current string.
+		T* oldArray = array;
+
+        allocated = used = len+1;
+		array = new T[used];
+
+		for (s32 l = 0; l<len+1; ++l)
+			array[l] = (T)c[l];
+
+		delete [] oldArray;
+		return *this;
+	}
+
+	//! Add operator for other strings
+	string<T> operator+(const string<T>& other) 
+	{ 
+		string<T> str(*this); 
+		str.append(other); 
+
+		return str; 
+	} 
+
+	//! Add operator for strings, ascii and unicode 
+	template <class B> 
+	string<T> operator+(const B* c) 
+	{ 
+		string<T> str(*this); 
+		str.append(c); 
+
+		return str; 
+	}
+
+
+
+	//! Direct access operator
+	T& operator [](const s32 index)  const
+	{
+		_IRR_DEBUG_BREAK_IF(index>=used) // bad index
+
+		return array[index];
+	}
+
+
+	//! Comparison operator
+	bool operator ==(const T* str) const
+	{
+		int i;
+		for(i=0; array[i] && str[i]; ++i)
+			if (array[i] != str[i])
+				return false;
+
+		return !array[i] && !str[i];
+	}
+
+
+
+	//! Comparison operator
+	bool operator ==(const string<T>& other) const
+	{
+		for(s32 i=0; array[i] && other.array[i]; ++i)
+			if (array[i] != other.array[i])
+				return false;
+
+		return used == other.used;
+	}
+
+
+
+	//! Is smaller operator
+	bool operator <(const string<T>& other) const
+	{
+		for(s32 i=0; array[i] && other.array[i]; ++i)
+			if (array[i] != other.array[i])
+				return (array[i] < other.array[i]);
+
+		return used < other.used;
+	}
+
+
+
+	//! Equals not operator
+	bool operator !=(const string<T>& other) const
+	{
+		return !(*this == other);
+	}
+
+
+    
+	//! Returns length of string
+	/** \return Returns length of the string in characters. */
+	s32 size() const
+	{
+		return used-1;
+	}
+
+
+
+	//! Returns character string
+	/** \return Returns pointer to C-style zero terminated string. */
+	const T* c_str() const
+	{
+		return array;
+	}
+
+
+
+	//! Makes the string lower case.
+	void make_lower()
+	{
+		const T A = (T)'A';
+		const T Z = (T)'Z';
+		const T diff = (T)'a' - A;
+
+		for (s32 i=0; i<used; ++i)
+		{
+			if (array[i]>=A && array[i]<=Z)
+				array[i] += diff;
+		}
+	}
+
+
+
+	//! Makes the string upper case.
+	void make_upper()
+	{
+		const T a = (T)'a';
+		const T z = (T)'z';
+		const T diff = (T)'A' - a;
+
+		for (s32 i=0; i<used; ++i)
+		{
+			if (array[i]>=a && array[i]<=z)
+				array[i] += diff;
+		}
+	}
+
+
+
+	//! Compares the string ignoring case.
+	/** \param other: Other string to compare.
+	\return Returns true if the string are equal ignoring case. */
+	bool equals_ignore_case(const string<T>& other) const
+	{
+		for(s32 i=0; array[i] && other[i]; ++i)
+			if (toLower(array[i]) != toLower(other[i]))
+				return false;
+
+		return used == other.used;
+	}
+
+
+	//! compares the first n characters of the strings
+	bool equalsn(const string<T>& other, int len)
+	{
+		int i;
+		for(i=0; array[i] && other[i] && i < len; ++i)
+			if (array[i] != other[i])
+				return false;
+
+		// if one (or both) of the strings was smaller then they
+		// are only equal if they have the same lenght
+		return (i == len) || (used == other.used);
+	}
+
+
+	//! compares the first n characters of the strings
+	bool equalsn(const T* str, int len)
+	{
+		int i;	
+		for(i=0; array[i] && str[i] && i < len; ++i)
+			if (array[i] != str[i])
+				return false;
+
+		// if one (or both) of the strings was smaller then they
+		// are only equal if they have the same lenght
+		return (i == len) || (array[i] == 0 && str[i] == 0);
+	}
+
+
+	//! Appends a character to this string
+	/** \param character: Character to append. */
+	void append(T character)
+	{
+		if (used + 1 > allocated)
+			reallocate((s32)used + 1);
+
+		used += 1;
+
+		array[used-2] = character;
+		array[used-1] = 0;
+	}
+
+	//! Appends a string to this string
+	/** \param other: String to append. */
+	void append(const string<T>& other)
+	{
+		--used;
+
+		s32 len = other.size();
+		
+		if (used + len + 1 > allocated)
+			reallocate((s32)used + (s32)len + 1);
+
+		for (s32 l=0; l<len+1; ++l)
+			array[l+used] = other[l];
+
+		used = used + len + 1;
+	}
+
+
+	//! Appends a string of the length l to this string.
+	/** \param other: other String to append to this string.
+	 \param length: How much characters of the other string to add to this one. */
+	void append(const string<T>& other, s32 length)
+	{
+		s32 len = other.size();
+
+		if (len < length)
+		{
+			append(other);
+			return;
+		}
+
+		len = length;
+		--used;
+		
+		if (used + len > allocated)
+			reallocate((s32)used + (s32)len);
+
+		for (s32 l=0; l<len; ++l)
+			array[l+used] = other[l];
+
+		used = used + len;
+	}
+
+
+	//! Reserves some memory.
+	/** \param count: Amount of characters to reserve. */
+	void reserve(s32 count)
+	{
+		if (count < allocated)
+			return;
+
+		reallocate(count);
+	}
+
+
+	//! finds first occurrence of character in string
+	/** \param c: Character to search for.
+	\return Returns position where the character has been found,
+	or -1 if not found. */
+	s32 findFirst(T c) const
+	{
+		for (s32 i=0; i<used; ++i)
+			if (array[i] == c)
+				return i;
+
+		return -1;
+	}
+
+	//! finds first occurrence of a character of a list in string
+	/** \param c: List of strings to find. For example if the method
+	should find the first occurance of 'a' or 'b', this parameter should be "ab".
+	\param count: Amount of characters in the list. Ususally, 
+	this should be strlen(ofParameter1)
+	\return Returns position where one of the character has been found,
+	or -1 if not found. */
+	s32 findFirstChar(T* c, int count) const
+	{
+		for (s32 i=0; i<used; ++i)
+			for (int j=0; j<count; ++j)
+				if (array[i] == c[j])
+					return i;
+
+		return -1;
+	}
+
+
+	//! Finds first position of a character not in a given list.
+	/** \param c: List of characters not to find. For example if the method
+	 should find the first occurance of a character not 'a' or 'b', this parameter should be "ab".
+	\param count: Amount of characters in the list. Ususally, 
+	this should be strlen(ofParameter1)
+	\return Returns position where the character has been found,
+	or -1 if not found. */
+	template <class B> 
+	s32 findFirstCharNotInList(B* c, int count) const
+	{
+		for (int i=0; i<used; ++i)
+		{
+            int j;
+			for (j=0; j<count; ++j)
+				if (array[i] == c[j])
+					break;
+
+			if (j==count)
+				return i;
+		}
+
+		return -1;
+	}
+
+	//! Finds last position of a character not in a given list.
+	/** \param c: List of characters not to find. For example if the method
+	 should find the first occurance of a character not 'a' or 'b', this parameter should be "ab".
+	\param count: Amount of characters in the list. Ususally, 
+	this should be strlen(ofParameter1)
+	\return Returns position where the character has been found,
+	or -1 if not found. */
+	template <class B> 
+	s32 findLastCharNotInList(B* c, int count) const
+	{
+		for (int i=used-2; i>=0; --i)
+		{
+            int j;
+			for (j=0; j<count; ++j)
+				if (array[i] == c[j])
+					break;
+
+			if (j==count)
+				return i;
+		}
+
+		return -1;
+	}
+
+	//! finds next occurrence of character in string
+	/** \param c: Character to search for.
+	\param startPos: Position in string to start searching. 
+	\return Returns position where the character has been found,
+	or -1 if not found. */
+	s32 findNext(T c, s32 startPos) const
+	{
+		for (s32 i=startPos; i<used; ++i)
+			if (array[i] == c)
+				return i;
+
+		return -1;
+	}
+
+
+	//! finds last occurrence of character in string
+	//! \param c: Character to search for.
+	//! \return Returns position where the character has been found,
+	//! or -1 if not found.
+	s32 findLast(T c) const
+	{
+		for (s32 i=used-1; i>=0; --i)
+			if (array[i] == c)
+				return i;
+
+		return -1;
+	}
+
+
+	//! Returns a substring
+	//! \param begin: Start of substring.
+	//! \param length: Length of substring.
+	string<T> subString(s32 begin, s32 length)
+	{
+		if (length <= 0)
+			return string<T>("");
+
+		string<T> o;
+		o.reserve(length+1);
+
+		for (s32 i=0; i<length; ++i)
+			o.array[i] = array[i+begin];
+
+		o.array[length] = 0;
+		o.used = o.allocated;
+
+		return o;
+	}
+
+
+	void operator += (T c)
+	{
+		append(c);
+	}
+
+	void operator += (const string<T>& other)
+	{
+		append(other);
+	}
+
+	void operator += (int i)
+	{
+		append(string<T>(i));
+	}
+
+	//! replaces all characters of a special type with another one
+	void replace(T toReplace, T replaceWith)
+	{
+		for (s32 i=0; i<used; ++i)
+			if (array[i] == toReplace)
+				array[i] = replaceWith;
+	}
+
+	//! trims the string.
+	/** Removes whitespace from begin and end of the string. */
+	void trim()
+	{
+		const char whitespace[] = " \t\n";
+		const int whitespacecount = 3;
+
+		// find start and end of real string without whitespace
+		int begin = findFirstCharNotInList(whitespace, whitespacecount);
+		if (begin == -1)
+			return;
+
+		int end = findLastCharNotInList(whitespace, whitespacecount);
+		if (end == -1)
+			return;
+
+		*this = subString(begin, (end +1) - begin);
+	}
+
+
+	//! Erases a character from the string. May be slow, because all elements 
+	//! following after the erased element have to be copied.
+	//! \param index: Index of element to be erased.
+	void erase(int index)
+	{
+		_IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation
+
+		for (int i=index+1; i<used; ++i)
+			array[i-1] = array[i];
+
+		--used;
+	}
+
+    	
+
+private:
+
+	//! Returns a character converted to lower case
+	T toLower(const T& t) const
+	{
+		if (t>=(T)'A' && t<=(T)'Z')
+			return t + ((T)'a' - (T)'A');
+		else
+			return t;
+	}
+
+	//! Reallocate the array, make it bigger or smaler
+	void reallocate(s32 new_size)
+	{
+		T* old_array = array;
+
+		array = new T[new_size];
+		allocated = new_size;
+		
+		s32 amount = used < new_size ? used : new_size;
+		for (s32 i=0; i<amount; ++i)
+			array[i] = old_array[i];
+
+		if (allocated < used)
+			used = allocated;
+		
+		delete [] old_array;
+	}
+
+
+	//--- member variables
+
+	T* array;
+	s32 allocated;
+	s32 used;
+};
+
+
+//! Typedef for character strings
+typedef string<irr::c8> stringc;
+
+//! Typedef for wide character strings
+typedef string<wchar_t> stringw;
+
+} // end namespace core
+} // end namespace irr
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/irrTypes.h	Wed Nov 17 20:19:41 2010 +0000
@@ -0,0 +1,100 @@
+// Copyright (C) 2002-2005 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#ifndef __IRR_TYPES_H_INCLUDED__
+#define __IRR_TYPES_H_INCLUDED__
+
+namespace irr
+{
+
+//! 8 bit unsigned variable.
+/** This is a typedef for unsigned char, it ensures portability of the engine. */
+typedef unsigned char		u8; 
+
+//! 8 bit signed variable.
+/** This is a typedef for signed char, it ensures portability of the engine. */
+typedef signed char			s8; 
+
+//! 8 bit character variable.
+/** This is a typedef for char, it ensures portability of the engine. */
+typedef char				c8; 
+
+
+
+//! 16 bit unsigned variable.
+/** This is a typedef for unsigned short, it ensures portability of the engine. */
+typedef unsigned short		u16;
+
+//! 16 bit signed variable.
+/** This is a typedef for signed short, it ensures portability of the engine. */
+typedef signed short		s16; 
+
+
+
+//! 32 bit unsigned variable.
+/** This is a typedef for unsigned int, it ensures portability of the engine. */
+typedef unsigned int		u32;
+
+//! 32 bit signed variable.
+/** This is a typedef for signed int, it ensures portability of the engine. */
+typedef signed int			s32; 
+
+
+
+// 64 bit signed variable.
+// This is a typedef for __int64, it ensures portability of the engine. 
+// This type is currently not used by the engine and not supported by compilers
+// other than Microsoft Compilers, so it is outcommented.
+//typedef __int64				s64; 
+
+
+
+//! 32 bit floating point variable.
+/** This is a typedef for float, it ensures portability of the engine. */
+typedef float				f32; 
+
+//! 64 bit floating point variable.
+/** This is a typedef for double, it ensures portability of the engine. */
+typedef double				f64; 
+
+
+} // end namespace
+
+
+// define the wchar_t type if not already built in.
+#ifdef _MSC_VER 
+#ifndef _WCHAR_T_DEFINED
+//! A 16 bit wide character type.
+/**
+	Defines the wchar_t-type.
+	In VS6, its not possible to tell
+	the standard compiler to treat wchar_t as a built-in type, and 
+	sometimes we just don't want to include the huge stdlib.h or wchar.h,
+	so we'll use this.
+*/
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif // wchar is not defined
+#endif // microsoft compiler
+
+//! define a break macro for debugging only in Win32 mode.
+#if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG)
+#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) if (_CONDITION_) {_asm int 3}
+#else 
+#define _IRR_DEBUG_BREAK_IF( _CONDITION_ )
+#endif
+
+//! Defines a small statement to work around a microsoft compiler bug.
+/** The microsft compiler 7.0 - 7.1 has a bug:
+When you call unmanaged code that returns a bool type value of false from managed code, 
+the return value may appear as true. See 
+http://support.microsoft.com/default.aspx?kbid=823071 for details. 
+Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/
+#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400)
+#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX __asm mov eax,100
+#else
+#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX
+#endif // _IRR_MANAGED_MARSHALLING_BUGFIX
+
+#endif // __IRR_TYPES_H_INCLUDED__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/irrXML.cpp	Wed Nov 17 20:19:41 2010 +0000
@@ -0,0 +1,147 @@
+// Copyright (C) 2002-2005 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine" and the "irrXML" project.
+// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
+
+#include "irrXML.h"
+#include "irrString.h"
+#include "irrArray.h"
+#include "fast_atof.h"
+#include "CXMLReaderImpl.h"
+
+namespace irr
+{
+namespace io
+{
+
+//! Implementation of the file read callback for ordinary files
+class CFileReadCallBack : public IFileReadCallBack
+{
+public:
+
+	//! construct from filename
+	CFileReadCallBack(const char* filename)
+		: File(0), Size(0), Close(true)
+	{
+		// open file
+		File = fopen(filename, "rb");
+
+		if (File)
+			getFileSize();
+	}
+
+	//! construct from FILE pointer
+	CFileReadCallBack(FILE* file)
+		: File(file), Size(0), Close(false)
+	{
+		if (File)
+			getFileSize();
+	}
+
+	//! destructor
+	virtual ~CFileReadCallBack()
+	{
+		if (Close && File)
+			fclose(File);
+	}
+
+	//! Reads an amount of bytes from the file.
+	virtual int read(void* buffer, int sizeToRead)
+	{
+		if (!File)
+			return 0;
+
+		return (int)fread(buffer, 1, sizeToRead, File);
+	}
+
+	//! Returns size of file in bytes
+	virtual int getSize()
+	{
+		return Size;
+	}
+
+private:
+
+	//! retrieves the file size of the open file
+	void getFileSize()
+	{
+		fseek(File, 0, SEEK_END);
+		Size = ftell(File);
+		fseek(File, 0, SEEK_SET);
+	}
+
+	FILE* File;
+	int Size;
+	bool Close;
+
+}; // end class CFileReadCallBack
+
+
+
+// FACTORY FUNCTIONS:
+
+
+//! Creates an instance of an UFT-8 or ASCII character xml parser. 
+IrrXMLReader* createIrrXMLReader(const char* filename)
+{
+	return new CXMLReaderImpl<char, IXMLBase>(new CFileReadCallBack(filename)); 
+}
+
+
+//! Creates an instance of an UFT-8 or ASCII character xml parser. 
+IrrXMLReader* createIrrXMLReader(FILE* file)
+{
+	return new CXMLReaderImpl<char, IXMLBase>(new CFileReadCallBack(file)); 
+}
+
+
+//! Creates an instance of an UFT-8 or ASCII character xml parser. 
+IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback)
+{
+	return new CXMLReaderImpl<char, IXMLBase>(callback, false); 
+}
+
+
+//! Creates an instance of an UTF-16 xml parser. 
+IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename)
+{
+	return new CXMLReaderImpl<char16, IXMLBase>(new CFileReadCallBack(filename)); 
+}
+
+
+//! Creates an instance of an UTF-16 xml parser. 
+IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file)
+{
+	return new CXMLReaderImpl<char16, IXMLBase>(new CFileReadCallBack(file)); 
+}
+
+
+//! Creates an instance of an UTF-16 xml parser. 
+IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback)
+{
+	return new CXMLReaderImpl<char16, IXMLBase>(callback, false); 
+}
+
+
+//! Creates an instance of an UTF-32 xml parser. 
+IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename)
+{
+	return new CXMLReaderImpl<char32, IXMLBase>(new CFileReadCallBack(filename)); 
+}
+
+
+//! Creates an instance of an UTF-32 xml parser. 
+IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file)
+{
+	return new CXMLReaderImpl<char32, IXMLBase>(new CFileReadCallBack(file)); 
+}
+
+
+//! Creates an instance of an UTF-32 xml parser. 
+IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback)
+{
+	return new CXMLReaderImpl<char32, IXMLBase>(callback, false); 
+}
+
+
+} // end namespace io
+} // end namespace irr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/irrXML.h	Wed Nov 17 20:19:41 2010 +0000
@@ -0,0 +1,539 @@
+// Copyright (C) 2002-2005 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine" and the "irrXML" project.
+// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
+
+#ifndef __IRR_XML_H_INCLUDED__
+#define __IRR_XML_H_INCLUDED__
+
+#include <stdio.h>
+
+/** \mainpage irrXML 1.2 API documentation
+ <div align="center"><img src="logobig.png" ></div>
+
+ \section intro Introduction
+
+  Welcome to the irrXML API documentation.
+  Here you'll find any information you'll need to develop applications with
+  irrXML. If you look for a tutorial on how to start, take a look at the \ref irrxmlexample,
+  at the homepage of irrXML at <A HREF="http://xml.irrlicht3d.org" >xml.irrlicht3d.org</A> 
+  or into the SDK in the directory \example.
+ 
+  irrXML is intended to be a high speed and easy-to-use XML Parser for C++, and
+  this documentation is an important part of it. If you have any questions or
+  suggestions, just send a email to the author of the engine, Nikolaus Gebhardt
+  (niko (at) irrlicht3d.org). For more informations about this parser, see \ref history.
+
+  \section features Features
+
+  irrXML provides forward-only, read-only 
+     access to a stream of non validated XML data. It was fully implemented by
+	 Nikolaus Gebhardt. Its current features are:
+
+	 - It it fast as lighting and has very low memory usage. It was 
+	   developed with the intention of being used in 3D games, as it already has been.
+	 - irrXML is very small: It only consists of 60 KB of code and can be added easily
+	   to your existing project.
+	 - Of course, it is platform independent and works with lots of compilers.
+	 - It is able to parse ASCII, UTF-8, UTF-16 and UTF-32 text files, both in 
+	   little and big endian format. 
+	 - Independent of the input file format, the parser can return all strings in ASCII, UTF-8,
+	   UTF-16 and UTF-32 format. 
+	 - With its optional file access abstraction it has the advantage that it can read not
+	   only from files but from any type of data (memory, network, ...). For example when 
+	   used with the Irrlicht Engine, it directly reads from compressed .zip files. 
+	 - Just like the Irrlicht Engine for which it was originally created, it is extremely easy 
+	   to use.
+	 - It has no external dependencies, it does not even need the STL. 
+
+	 Although irrXML has some strenghts, it currently also has the following limitations:
+
+	 - The input xml file is not validated and assumed to be correct. 
+
+    \section irrxmlexample Example
+
+    The following code demonstrates the basic usage of irrXML. A simple xml
+	file like this is parsed:
+    \code
+	<?xml version="1.0"?>
+	<config>
+		<!-- This is a config file for the mesh viewer -->
+		<model file="dwarf.dea" />
+		<messageText caption="Irrlicht Engine Mesh Viewer">
+		Welcome to the Mesh Viewer of the &quot;Irrlicht Engine&quot;.
+		</messageText>
+	</config>
+	\endcode
+
+	The code for parsing this file would look like this:
+	\code
+	#include <irrXML.h>
+	using namespace irr; // irrXML is located in the namespace irr::io
+	using namespace io;
+
+	#include <string> // we use STL strings to store data in this example
+
+	void main()
+	{
+		// create the reader using one of the factory functions
+
+		IrrXMLReader* xml = createIrrXMLReader("config.xml");
+
+		// strings for storing the data we want to get out of the file
+		std::string modelFile;
+		std::string messageText;
+		std::string caption;
+
+		// parse the file until end reached
+
+		while(xml && xml->read())
+		{
+			switch(xml->getNodeType())
+			{
+			case EXN_TEXT:
+				// in this xml file, the only text which occurs is the messageText
+				messageText = xml->getNodeData();
+				break;
+			case EXN_ELEMENT:
+				{
+					if (!strcmp("model", xml->getNodeName()))
+						modelFile = xml->getAttributeValue("file");
+					else
+					if (!strcmp("messageText", xml->getNodeName()))
+						caption = xml->getAttributeValue("caption");
+				}
+				break;
+			}
+		}
+
+		// delete the xml parser after usage
+		delete xml;
+	}
+	\endcode
+
+	\section howto How to use
+
+	Simply add the source files in the /src directory of irrXML to your project. Done.
+
+	\section license License
+
+	The irrXML license is based on the zlib license. Basicly, this means you can do with
+	irrXML whatever you want:
+
+	Copyright (C) 2002-2005 Nikolaus Gebhardt
+
+	This software is provided 'as-is', without any express or implied
+	warranty.  In no event will the authors be held liable for any damages
+	arising from the use of this software.
+
+	Permission is granted to anyone to use this software for any purpose,
+	including commercial applications, and to alter it and redistribute it
+	freely, subject to the following restrictions:
+
+	1. The origin of this software must not be misrepresented; you must not
+		claim that you wrote the original software. If you use this software
+		in a product, an acknowledgment in the product documentation would be
+		appreciated but is not required.
+
+	2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+	3. This notice may not be removed or altered from any source distribution.
+
+	\section history History
+
+	As lots of references in this documentation and the source show, this xml 
+	parser has originally been a part of the 
+	<A HREF="http://irrlicht.sourceforge.net" >Irrlicht Engine</A>. But because
+	the parser has become very useful with the latest release, people asked for a 
+	separate version of it, to be able to use it in non Irrlicht projects. With
+	irrXML 1.0, this has now been done.
+*/
+
+namespace irr
+{
+namespace io
+{
+	//! Enumeration of all supported source text file formats 
+	enum ETEXT_FORMAT
+	{
+		//! ASCII, file without byte order mark, or not a text file
+		ETF_ASCII,
+
+		//! UTF-8 format
+		ETF_UTF8,
+
+		//! UTF-16 format, big endian
+		ETF_UTF16_BE,
+
+		//! UTF-16 format, little endian
+		ETF_UTF16_LE,
+
+		//! UTF-32 format, big endian
+		ETF_UTF32_BE,
+
+		//! UTF-32 format, little endian
+		ETF_UTF32_LE,
+	};
+
+
+	//! Enumeration for all xml nodes which are parsed by IrrXMLReader
+	enum EXML_NODE
+	{
+		//! No xml node. This is usually the node if you did not read anything yet.
+		EXN_NONE,
+
+		//! A xml element, like <foo>
+		EXN_ELEMENT,
+
+		//! End of an xml element, like </foo>
+		EXN_ELEMENT_END,
+
+		//! Text within a xml element: <foo> this is the text. </foo>
+		EXN_TEXT,
+
+		//! An xml comment like &lt;!-- I am a comment --&gt; or a DTD definition.
+		EXN_COMMENT,
+
+		//! An xml cdata section like &lt;![CDATA[ this is some CDATA ]]&gt;
+		EXN_CDATA,
+
+		//! Unknown element.
+		EXN_UNKNOWN
+	};
+
+	//! Callback class for file read abstraction. 
+	/** With this, it is possible to make the xml parser read in other things 
+	than just files. The Irrlicht engine is using this for example to 
+	read xml from compressed .zip files. To make the parser read in 
+	any other data, derive a class from this interface, implement the 
+	two methods to read your data and give a pointer to an instance of
+	your implementation when calling createIrrXMLReader(), 
+	createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */
+	class IFileReadCallBack
+	{
+	public:
+
+		//! virtual destructor
+		virtual ~IFileReadCallBack() {};
+
+		//! Reads an amount of bytes from the file.
+		/** \param buffer: Pointer to buffer where to read bytes will be written to.
+		\param sizeToRead: Amount of bytes to read from the file.
+		\return Returns how much bytes were read. */
+		virtual int read(void* buffer, int sizeToRead) = 0;
+
+		//! Returns size of file in bytes
+		virtual int getSize() = 0;
+	};
+
+	//! Empty class to be used as parent class for IrrXMLReader.
+	/** If you need another class as base class for the xml reader, you can do this by creating
+	the reader using for example new CXMLReaderImpl<char, YourBaseClass>(yourcallback);
+	The Irrlicht Engine for example needs IUnknown as base class for every object to
+	let it automaticly reference countend, hence it replaces IXMLBase with IUnknown.
+	See irrXML.cpp on how this can be done in detail. */
+	class IXMLBase
+	{
+	};	
+
+	//! Interface providing easy read access to a XML file.
+	/** You can create an instance of this reader using one of the factory functions
+	createIrrXMLReader(), createIrrXMLReaderUTF16() and createIrrXMLReaderUTF32().
+	If using the parser from the Irrlicht Engine, please use IFileSystem::createXMLReader() 
+	instead.
+	For a detailed intro how to use the parser, see \ref irrxmlexample and \ref features.
+
+	The typical usage of this parser looks like this:
+	\code
+	#include <irrXML.h>
+	using namespace irr; // irrXML is located in the namespace irr::io
+	using namespace io;
+
+	void main()
+	{
+		// create the reader using one of the factory functions
+		IrrXMLReader* xml = createIrrXMLReader("config.xml");
+
+		if (xml == 0)
+			return; // file could not be opened
+
+		// parse the file until end reached
+		while(xml->read())
+		{
+			// based on xml->getNodeType(), do something.
+		}
+
+		// delete the xml parser after usage
+		delete xml;
+	}
+	\endcode
+	See \ref irrxmlexample for a more detailed example.
+	*/
+	template<class char_type, class super_class>
+	class IIrrXMLReader : public super_class
+	{
+	public:
+
+		//! Destructor
+		virtual ~IIrrXMLReader() {};
+
+		//! Reads forward to the next xml node. 
+		/** \return Returns false, if there was no further node.  */
+		virtual bool read() = 0;
+
+		//! Returns the type of the current XML node.
+		virtual EXML_NODE getNodeType() const = 0;
+
+        //! Returns attribute count of the current XML node. 
+		/** This is usually
+		non null if the current node is EXN_ELEMENT, and the element has attributes.
+		\return Returns amount of attributes of this xml node. */
+		virtual int getAttributeCount() const = 0;
+
+		//! Returns name of an attribute. 
+		/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
+		\return Name of the attribute, 0 if an attribute with this index does not exist. */
+		virtual const char_type* getAttributeName(int idx) const = 0;
+
+		//! Returns the value of an attribute. 
+		/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
+		\return Value of the attribute, 0 if an attribute with this index does not exist. */
+		virtual const char_type* getAttributeValue(int idx) const = 0;
+
+		//! Returns the value of an attribute. 
+		/** \param name: Name of the attribute.
+		\return Value of the attribute, 0 if an attribute with this name does not exist. */
+		virtual const char_type* getAttributeValue(const char_type* name) const = 0;
+
+		//! Returns the value of an attribute in a safe way.
+		/** Like getAttributeValue(), but does not 
+		return 0 if the attribute does not exist. An empty string ("") is returned then.
+		\param name: Name of the attribute.
+		\return Value of the attribute, and "" if an attribute with this name does not exist */
+		virtual const char_type* getAttributeValueSafe(const char_type* name) const = 0;
+
+		//! Returns the value of an attribute as integer. 
+		/** \param name Name of the attribute.
+		\return Value of the attribute as integer, and 0 if an attribute with this name does not exist or
+		the value could not be interpreted as integer. */
+		virtual int getAttributeValueAsInt(const char_type* name) const = 0;
+
+		//! Returns the value of an attribute as integer. 
+		/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
+		\return Value of the attribute as integer, and 0 if an attribute with this index does not exist or
+		the value could not be interpreted as integer. */
+		virtual int getAttributeValueAsInt(int idx) const = 0;
+
+		//! Returns the value of an attribute as float. 
+		/** \param name: Name of the attribute.
+		\return Value of the attribute as float, and 0 if an attribute with this name does not exist or
+		the value could not be interpreted as float. */
+		virtual float getAttributeValueAsFloat(const char_type* name) const = 0;
+
+		//! Returns the value of an attribute as float. 
+		/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
+		\return Value of the attribute as float, and 0 if an attribute with this index does not exist or
+		the value could not be interpreted as float. */
+		virtual float getAttributeValueAsFloat(int idx) const = 0;
+
+		//! Returns the name of the current node. 
+		/** Only non null, if the node type is EXN_ELEMENT.
+		\return Name of the current node or 0 if the node has no name. */
+		virtual const char_type* getNodeName() const = 0;
+
+		//! Returns data of the current node. 
+		/** Only non null if the node has some
+		data and it is of type EXN_TEXT or EXN_UNKNOWN. */
+		virtual const char_type* getNodeData() const = 0;
+
+		//! Returns if an element is an empty element, like <foo />
+		virtual bool isEmptyElement() const = 0;
+
+		//! Returns format of the source xml file. 
+		/** It is not necessary to use
+		this method because the parser will convert the input file format
+		to the format wanted by the user when creating the parser. This
+		method is useful to get/display additional informations. */
+		virtual ETEXT_FORMAT getSourceFormat() const = 0;
+
+		//! Returns format of the strings returned by the parser. 
+		/** This will be UTF8 for example when you created a parser with
+		IrrXMLReaderUTF8() and UTF32 when it has been created using 
+		IrrXMLReaderUTF32. It should not be necessary to call this
+		method and only exists for informational purposes. */
+		virtual ETEXT_FORMAT getParserFormat() const = 0;
+	};
+
+
+	//! defines the utf-16 type.
+	/** Not using wchar_t for this because 
+	wchar_t has 16 bit on windows and 32 bit on other operating systems. */
+	typedef unsigned short char16;
+
+	//! defines the utf-32 type. 
+	/** Not using wchar_t for this because 
+	wchar_t has 16 bit on windows and 32 bit on other operating systems. */
+	typedef unsigned long char32;
+
+	//! A UTF-8 or ASCII character xml parser.
+	/** This means that all character data will be returned in 8 bit ASCII or UTF-8 by this parser. 
+	The file to read can be in any format, it will be converted to UTF-8 if it is not
+	in this format.
+	Create an instance of this with createIrrXMLReader(); 
+	See IIrrXMLReader for description on how to use it. */
+	typedef IIrrXMLReader<char, IXMLBase> IrrXMLReader;
+
+	//! A UTF-16 xml parser. 
+	/** This means that all character data will be returned in UTF-16 by this parser. 
+	The file to read can be in any format, it will be converted to UTF-16 if it is not
+	in this format.
+	Create an instance of this with createIrrXMLReaderUTF16(); 
+	See IIrrXMLReader for description on how to use it.  */
+	typedef IIrrXMLReader<char16, IXMLBase> IrrXMLReaderUTF16;
+
+	//! A UTF-32 xml parser. 
+	/** This means that all character data will be returned in UTF-32 by this parser. 
+	The file to read can be in any format, it will be converted to UTF-32 if it is not
+	in this format.
+	Create an instance of this with createIrrXMLReaderUTF32(); 
+	See IIrrXMLReader for description on how to use it. */
+	typedef IIrrXMLReader<char32, IXMLBase> IrrXMLReaderUTF32;
+
+
+	//! Creates an instance of an UFT-8 or ASCII character xml parser.
+	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. 
+	The file to read can be in any format, it will be converted to UTF-8 if it is not in this format.
+	If you are using the Irrlicht Engine, it is better not to use this function but
+	IFileSystem::createXMLReaderUTF8() instead.
+	\param filename: Name of file to be opened.
+	\return Returns a pointer to the created xml parser. This pointer should be 
+	deleted using 'delete' after no longer needed. Returns 0 if an error occured
+	and the file could not be opened. */
+	IrrXMLReader* createIrrXMLReader(const char* filename);
+
+	//! Creates an instance of an UFT-8 or ASCII character xml parser.
+	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can 
+	be in any format, it will be converted to UTF-8 if it is not in this format.
+	If you are using the Irrlicht Engine, it is better not to use this function but
+	IFileSystem::createXMLReaderUTF8() instead.
+	\param file: Pointer to opened file, must have been opened in binary mode, e.g.
+	using fopen("foo.bar", "wb"); The file will not be closed after it has been read.
+	\return Returns a pointer to the created xml parser. This pointer should be 
+	deleted using 'delete' after no longer needed. Returns 0 if an error occured
+	and the file could not be opened. */
+	IrrXMLReader* createIrrXMLReader(FILE* file);
+
+	//! Creates an instance of an UFT-8 or ASCII character xml parser. 
+	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can 
+	 be in any format, it will be converted to UTF-8 if it is not in this format.
+	 If you are using the Irrlicht Engine, it is better not to use this function but
+	 IFileSystem::createXMLReaderUTF8() instead.
+	 \param callback: Callback for file read abstraction. Implement your own
+	 callback to make the xml parser read in other things than just files. See
+	 IFileReadCallBack for more information about this.
+	 \return Returns a pointer to the created xml parser. This pointer should be 
+	 deleted using 'delete' after no longer needed. Returns 0 if an error occured
+	 and the file could not be opened. */
+	IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback);
+
+	//! Creates an instance of an UFT-16 xml parser. 
+	/** This means that
+	all character data will be returned in UTF-16. The file to read can 
+	be in any format, it will be converted to UTF-16 if it is not in this format.
+	If you are using the Irrlicht Engine, it is better not to use this function but
+	IFileSystem::createXMLReader() instead.
+	\param filename: Name of file to be opened.
+	\return Returns a pointer to the created xml parser. This pointer should be 
+	deleted using 'delete' after no longer needed. Returns 0 if an error occured
+	and the file could not be opened. */
+	IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename);
+
+	//! Creates an instance of an UFT-16 xml parser. 
+	/** This means that all character data will be returned in UTF-16. The file to read can 
+	be in any format, it will be converted to UTF-16 if it is not in this format.
+	If you are using the Irrlicht Engine, it is better not to use this function but
+	IFileSystem::createXMLReader() instead.
+	\param file: Pointer to opened file, must have been opened in binary mode, e.g.
+	using fopen("foo.bar", "wb"); The file will not be closed after it has been read.
+	\return Returns a pointer to the created xml parser. This pointer should be 
+	deleted using 'delete' after no longer needed. Returns 0 if an error occured
+	and the file could not be opened. */
+	IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file);
+
+	//! Creates an instance of an UFT-16 xml parser. 
+	/** This means that all character data will be returned in UTF-16. The file to read can 
+	be in any format, it will be converted to UTF-16 if it is not in this format.
+	If you are using the Irrlicht Engine, it is better not to use this function but
+	IFileSystem::createXMLReader() instead.
+	\param callback: Callback for file read abstraction. Implement your own
+	callback to make the xml parser read in other things than just files. See
+	IFileReadCallBack for more information about this.
+	\return Returns a pointer to the created xml parser. This pointer should be 
+	deleted using 'delete' after no longer needed. Returns 0 if an error occured
+	and the file could not be opened. */
+	IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback);
+
+
+	//! Creates an instance of an UFT-32 xml parser. 
+	/** This means that all character data will be returned in UTF-32. The file to read can 
+	be in any format, it will be converted to UTF-32 if it is not in this format.
+	If you are using the Irrlicht Engine, it is better not to use this function but
+	IFileSystem::createXMLReader() instead.
+	\param filename: Name of file to be opened.
+	\return Returns a pointer to the created xml parser. This pointer should be 
+	deleted using 'delete' after no longer needed. Returns 0 if an error occured
+	and the file could not be opened. */
+	IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename);
+
+	//! Creates an instance of an UFT-32 xml parser. 
+	/** This means that all character data will be returned in UTF-32. The file to read can 
+	be in any format, it will be converted to UTF-32 if it is not in this format.
+	if you are using the Irrlicht Engine, it is better not to use this function but
+	IFileSystem::createXMLReader() instead.
+	\param file: Pointer to opened file, must have been opened in binary mode, e.g.
+	using fopen("foo.bar", "wb"); The file will not be closed after it has been read.
+	\return Returns a pointer to the created xml parser. This pointer should be 
+	deleted using 'delete' after no longer needed. Returns 0 if an error occured
+	and the file could not be opened. */
+	IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file);
+
+	//! Creates an instance of an UFT-32 xml parser. 
+	/** This means that
+	all character data will be returned in UTF-32. The file to read can 
+	be in any format, it will be converted to UTF-32 if it is not in this format.
+	If you are using the Irrlicht Engine, it is better not to use this function but
+	IFileSystem::createXMLReader() instead.
+	\param callback: Callback for file read abstraction. Implement your own
+	callback to make the xml parser read in other things than just files. See
+	IFileReadCallBack for more information about this.
+	\return Returns a pointer to the created xml parser. This pointer should be 
+	deleted using 'delete' after no longer needed. Returns 0 if an error occured
+	and the file could not be opened. */
+	IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback);
+	
+
+	/*! \file irrxml.h
+    \brief Header file of the irrXML, the Irrlicht XML parser.
+    
+    This file includes everything needed for using irrXML, 
+    the XML parser of the Irrlicht Engine. To use irrXML,
+	you only need to include this file in your project:
+
+	\code
+	#include <irrXML.h>
+	\endcode
+
+	It is also common to use the two namespaces in which irrXML is included, 
+	directly after #including irrXML.h:
+
+	\code
+	#include <irrXML.h>
+	using namespace irr;
+	using namespace io;
+	\endcode
+	*/
+
+} // end namespace io
+} // end namespace irr
+
+#endif // __IRR_XML_H_INCLUDED__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stringReader.h	Wed Nov 17 20:19:41 2010 +0000
@@ -0,0 +1,49 @@
+#ifndef STRINGREADER_H
+#define STRINGREADER_H
+
+#include <stdlib.h>
+#include <string.h>
+
+class CStringReadCallBack : public IFileReadCallBack
+{
+public:
+
+	//! construct from filename
+	CStringReadCallBack(char* data)
+		: Size(0), Close(true), _offset(0)
+	{
+    	_data=data;
+    	Size=strlen(_data);
+	}
+
+	//! destructor
+	virtual ~CStringReadCallBack()
+	{
+	}
+
+	//! Reads an amount of bytes from the file.
+	virtual int read(void* buffer, int sizeToRead)
+	{
+	    int len=sizeToRead;
+	    if (Size-_offset>len)
+	        len=Size-_offset;
+        memcpy(buffer,_data+_offset,len);
+		return len;
+	}
+
+	//! Returns size of file in bytes
+	virtual int getSize()
+	{
+		return Size;
+	}
+
+private:
+
+	int Size;
+	int _offset;
+	bool Close;
+	char* _data;
+
+}; // end class CFileReadCallBack
+
+#endif