GLES drivers adapted, but only did make compile-tests. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6038 dfc29bdd-3216-0410-991c-e03cc46cb475
		
			
				
	
	
		
			473 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			473 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (C) 2002-2012 Nikolaus Gebhardt
 | |
| // This file is part of the "Irrlicht Engine".
 | |
| // For conditions of distribution and use, see copyright notice in irrlicht.h
 | |
| 
 | |
| #include "CXMLWriter.h"
 | |
| 
 | |
| #ifdef _IRR_COMPILE_WITH_XML_
 | |
| 
 | |
| #include <wchar.h>
 | |
| #include "irrString.h"
 | |
| #include "IrrCompileConfig.h"
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| namespace io
 | |
| {
 | |
| 
 | |
| //! creates an IXMLReader
 | |
| IXMLWriter* createIXMLWriter(IWriteFile* file)
 | |
| {
 | |
| 	return new CXMLWriter(file);
 | |
| }
 | |
| 
 | |
| //! creates an IXMLReader
 | |
| IXMLWriterUTF8* createIXMLWriterUTF8(IWriteFile* file)
 | |
| {
 | |
| 	return new CXMLWriterUTF8(file);
 | |
| }
 | |
| 
 | |
| //! Constructor
 | |
| CXMLWriter::CXMLWriter(IWriteFile* file)
 | |
| : CXMLWriterCommon(file) 
 | |
| {
 | |
| 	#ifdef _DEBUG
 | |
| 	setDebugName("CXMLWriter");
 | |
| 	#endif
 | |
| }
 | |
| 
 | |
| 
 | |
| //! Writes a xml 1.0 header like <?xml version="1.0"?>
 | |
| void CXMLWriter::writeXMLHeader()
 | |
| {
 | |
| 	if (!File)
 | |
| 		return;
 | |
| 
 | |
| 	if (sizeof(wchar_t)==2)
 | |
| 	{
 | |
| 		const u16 h = 0xFEFF;
 | |
| 		File->write(&h, 2);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		const u32 h = 0x0000FEFF;
 | |
| 		File->write(&h, sizeof(wchar_t));
 | |
| 	}
 | |
| 
 | |
| 	const wchar_t* const p = L"<?xml version=\"1.0\"?>";
 | |
| 	File->write(p, wcslen(p)*sizeof(wchar_t));
 | |
| 
 | |
| 	writeLineBreak();
 | |
| 	TextWrittenLast = false;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| //! Writes an xml element with maximal 5 attributes
 | |
| void CXMLWriter::writeElement(const wchar_t* name, bool empty,
 | |
| 	const wchar_t* attr1Name, const wchar_t* attr1Value,
 | |
| 	const wchar_t* attr2Name, const wchar_t* attr2Value,
 | |
| 	const wchar_t* attr3Name, const wchar_t* attr3Value,
 | |
| 	const wchar_t* attr4Name, const wchar_t* attr4Value,
 | |
| 	const wchar_t* attr5Name, const wchar_t* attr5Value)
 | |
| {
 | |
| 	if (!File || !name)
 | |
| 		return;
 | |
| 
 | |
| 	if (Tabs > 0)
 | |
| 	{
 | |
| 		for (int i=0; i<Tabs; ++i)
 | |
| 			File->write(L"\t", sizeof(wchar_t));
 | |
| 	}
 | |
| 
 | |
| 	// write name
 | |
| 
 | |
| 	File->write(L"<", sizeof(wchar_t));
 | |
| 	File->write(name, wcslen(name)*sizeof(wchar_t));
 | |
| 
 | |
| 	// write attributes
 | |
| 
 | |
| 	writeAttribute(attr1Name, attr1Value);
 | |
| 	writeAttribute(attr2Name, attr2Value);
 | |
| 	writeAttribute(attr3Name, attr3Value);
 | |
| 	writeAttribute(attr4Name, attr4Value);
 | |
| 	writeAttribute(attr5Name, attr5Value);
 | |
| 
 | |
| 	// write closing tag
 | |
| 	if (empty)
 | |
| 		File->write(L" />", 3*sizeof(wchar_t));
 | |
| 	else
 | |
| 	{
 | |
| 		File->write(L">", sizeof(wchar_t));
 | |
| 		++Tabs;
 | |
| 	}
 | |
| 
 | |
| 	TextWrittenLast = false;
 | |
| }
 | |
| 
 | |
| //! Writes an xml element with any number of attributes
 | |
| void CXMLWriter::writeElement(const wchar_t* name, bool empty,
 | |
| 				  core::array<core::stringw> &names,
 | |
| 				  core::array<core::stringw> &values)
 | |
| {
 | |
| 	if (!File || !name)
 | |
| 		return;
 | |
| 
 | |
| 	if (Tabs > 0)
 | |
| 	{
 | |
| 		for (int i=0; i<Tabs; ++i)
 | |
| 			File->write(L"\t", sizeof(wchar_t));
 | |
| 	}
 | |
| 
 | |
| 	// write name
 | |
| 
 | |
| 	File->write(L"<", sizeof(wchar_t));
 | |
| 	File->write(name, wcslen(name)*sizeof(wchar_t));
 | |
| 
 | |
| 	// write attributes
 | |
| 	u32 i=0;
 | |
| 	for (; i < names.size() && i < values.size(); ++i)
 | |
| 		writeAttribute(names[i].c_str(), values[i].c_str());
 | |
| 
 | |
| 	// write closing tag
 | |
| 	if (empty)
 | |
| 		File->write(L" />", 3*sizeof(wchar_t));
 | |
| 	else
 | |
| 	{
 | |
| 		File->write(L">", sizeof(wchar_t));
 | |
| 		++Tabs;
 | |
| 	}
 | |
| 
 | |
| 	TextWrittenLast = false;
 | |
| }
 | |
| 
 | |
| 
 | |
| void CXMLWriter::writeAttribute(const wchar_t* name, const wchar_t* value)
 | |
| {
 | |
| 	if (!name || !value)
 | |
| 		return;
 | |
| 
 | |
| 	File->write(L" ", sizeof(wchar_t));
 | |
| 	File->write(name, wcslen(name)*sizeof(wchar_t));
 | |
| 	File->write(L"=\"", 2*sizeof(wchar_t));
 | |
| 	writeText(value);
 | |
| 	File->write(L"\"", sizeof(wchar_t));
 | |
| }
 | |
| 
 | |
| 
 | |
| //! Writes a comment into the xml file
 | |
| void CXMLWriter::writeComment(const wchar_t* comment)
 | |
| {
 | |
| 	if (!File || !comment)
 | |
| 		return;
 | |
| 
 | |
| 	File->write(L"<!--", 4*sizeof(wchar_t));
 | |
| 	writeText(comment);
 | |
| 	File->write(L"-->", 3*sizeof(wchar_t));
 | |
| }
 | |
| 
 | |
| 
 | |
| //! Writes the closing tag for an element. Like </foo>
 | |
| void CXMLWriter::writeClosingTag(const wchar_t* name)
 | |
| {
 | |
| 	if (!File || !name)
 | |
| 		return;
 | |
| 
 | |
| 	--Tabs;
 | |
| 
 | |
| 	if (Tabs > 0 && !TextWrittenLast)
 | |
| 	{
 | |
| 		for (int i=0; i<Tabs; ++i)
 | |
| 			File->write(L"\t", sizeof(wchar_t));
 | |
| 	}
 | |
| 
 | |
| 	File->write(L"</", 2*sizeof(wchar_t));
 | |
| 	File->write(name, wcslen(name)*sizeof(wchar_t));
 | |
| 	File->write(L">", sizeof(wchar_t));
 | |
| 	TextWrittenLast = false;
 | |
| }
 | |
| 
 | |
| //! Writes a text into the file. All occurrences of special characters like
 | |
| //! & (&), < (<), > (>), and " (") are automatically replaced.
 | |
| void CXMLWriter::writeText(const wchar_t* text)
 | |
| {
 | |
| 	if (!File || !text)
 | |
| 		return;
 | |
| 
 | |
| 	static const CXMLWriter::XMLSpecialCharacters XMLWSChar[] =
 | |
| 	{
 | |
| 		{ L'&', L"&" },
 | |
| 		{ L'<', L"<" },
 | |
| 		{ L'>', L">" },
 | |
| 		{ L'"', L""" },
 | |
| 		{ L'\0', 0 }
 | |
| 	};
 | |
| 
 | |
| 	// TODO: we have to get rid of that reserve call as well as it slows down xml-writing seriously.
 | |
| 	// Making a member-variable would work, but a lot of memory would stay around after writing.
 | |
| 	// So the correct solution is probably using fixed block here and always write when that is full.
 | |
| 	core::stringw s;
 | |
| 	s.reserve(wcslen(text)+1);
 | |
| 	const wchar_t* p = text;
 | |
| 
 | |
| 	while(*p)
 | |
| 	{
 | |
| 		// check if it is matching
 | |
| 		bool found = false;
 | |
| 		for (s32 i=0; XMLWSChar[i].Character != '\0'; ++i)
 | |
| 			if (*p == XMLWSChar[i].Character)
 | |
| 			{
 | |
| 				s.append(XMLWSChar[i].Symbol);
 | |
| 				found = true;
 | |
| 				break;
 | |
| 			}
 | |
| 
 | |
| 		if (!found)
 | |
| 			s.append(*p);
 | |
| 		++p;
 | |
| 	}
 | |
| 
 | |
| 	// write new string
 | |
| 	File->write(s.c_str(), s.size()*sizeof(wchar_t));
 | |
| 	TextWrittenLast = true;
 | |
| }
 | |
| 
 | |
| 
 | |
| //! Writes a line break
 | |
| void CXMLWriter::writeLineBreak()
 | |
| {
 | |
| 	if (!File)
 | |
| 		return;
 | |
| 
 | |
| #if defined(_IRR_OSX_PLATFORM_)
 | |
| 	File->write(L"\r", sizeof(wchar_t));
 | |
| #elif defined(_IRR_WINDOWS_API_)
 | |
| 	File->write(L"\r\n", 2*sizeof(wchar_t));
 | |
| #else
 | |
| 	File->write(L"\n", sizeof(wchar_t));
 | |
| #endif
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| //! Constructor
 | |
| CXMLWriterUTF8::CXMLWriterUTF8(IWriteFile* file)
 | |
| : CXMLWriterCommon(file) 
 | |
| {
 | |
| 	#ifdef _DEBUG
 | |
| 	setDebugName("CXMLWriter");
 | |
| 	#endif
 | |
| }
 | |
| 
 | |
| 
 | |
| //! Writes a xml 1.0 header like <?xml version="1.0"?>
 | |
| void CXMLWriterUTF8::writeXMLHeader()
 | |
| {
 | |
| 	if (!File)
 | |
| 		return;
 | |
| 
 | |
| 	// No BOM as it's not necessarily utf8
 | |
| 
 | |
| 	const c8* const p = "<?xml version=\"1.0\"?>";
 | |
| 	File->write(p, strlen(p) * sizeof(c8));
 | |
| 
 | |
| 	writeLineBreak();
 | |
| 	TextWrittenLast = false;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| //! Writes an xml element with maximal 5 attributes
 | |
| void CXMLWriterUTF8::writeElement(const c8* name, bool empty,
 | |
| 	const c8* attr1Name, const c8* attr1Value,
 | |
| 	const c8* attr2Name, const c8* attr2Value,
 | |
| 	const c8* attr3Name, const c8* attr3Value,
 | |
| 	const c8* attr4Name, const c8* attr4Value,
 | |
| 	const c8* attr5Name, const c8* attr5Value)
 | |
| {
 | |
| 	if (!File || !name)
 | |
| 		return;
 | |
| 
 | |
| 	if (Tabs > 0)
 | |
| 	{
 | |
| 		for (int i=0; i<Tabs; ++i)
 | |
| 			File->write("\t", sizeof(c8));
 | |
| 	}
 | |
| 
 | |
| 	// write name
 | |
| 
 | |
| 	File->write("<", sizeof(c8));
 | |
| 	File->write(name, strlen(name)*sizeof(c8));
 | |
| 
 | |
| 	// write attributes
 | |
| 
 | |
| 	writeAttribute(attr1Name, attr1Value);
 | |
| 	writeAttribute(attr2Name, attr2Value);
 | |
| 	writeAttribute(attr3Name, attr3Value);
 | |
| 	writeAttribute(attr4Name, attr4Value);
 | |
| 	writeAttribute(attr5Name, attr5Value);
 | |
| 
 | |
| 	// write closing tag
 | |
| 	if (empty)
 | |
| 		File->write(" />", 3*sizeof(c8));
 | |
| 	else
 | |
| 	{
 | |
| 		File->write(">", sizeof(c8));
 | |
| 		++Tabs;
 | |
| 	}
 | |
| 
 | |
| 	TextWrittenLast = false;
 | |
| }
 | |
| 
 | |
| //! Writes an xml element with any number of attributes
 | |
| void CXMLWriterUTF8::writeElement(const c8* name, bool empty,
 | |
| 				  core::array<core::stringc> &names,
 | |
| 				  core::array<core::stringc> &values)
 | |
| {
 | |
| 	if (!File || !name)
 | |
| 		return;
 | |
| 
 | |
| 	if (Tabs > 0)
 | |
| 	{
 | |
| 		for (int i=0; i<Tabs; ++i)
 | |
| 			File->write("\t", sizeof(c8));
 | |
| 	}
 | |
| 
 | |
| 	// write name
 | |
| 
 | |
| 	File->write("<", sizeof(c8));
 | |
| 	File->write(name, strlen(name)*sizeof(c8));
 | |
| 
 | |
| 	// write attributes
 | |
| 	u32 i=0;
 | |
| 	for (; i < names.size() && i < values.size(); ++i)
 | |
| 		writeAttribute(names[i].c_str(), values[i].c_str());
 | |
| 
 | |
| 	// write closing tag
 | |
| 	if (empty)
 | |
| 		File->write(" />", 3*sizeof(c8));
 | |
| 	else
 | |
| 	{
 | |
| 		File->write(">", sizeof(c8));
 | |
| 		++Tabs;
 | |
| 	}
 | |
| 
 | |
| 	TextWrittenLast = false;
 | |
| }
 | |
| 
 | |
| 
 | |
| void CXMLWriterUTF8::writeAttribute(const c8* name, const c8* value)
 | |
| {
 | |
| 	if (!name || !value)
 | |
| 		return;
 | |
| 
 | |
| 	File->write(" ", sizeof(c8));
 | |
| 	File->write(name, strlen(name)*sizeof(c8));
 | |
| 	File->write("=\"", 2*sizeof(c8));
 | |
| 	writeText(value);
 | |
| 	File->write("\"", sizeof(c8));
 | |
| }
 | |
| 
 | |
| 
 | |
| //! Writes a comment into the xml file
 | |
| void CXMLWriterUTF8::writeComment(const c8* comment)
 | |
| {
 | |
| 	if (!File || !comment)
 | |
| 		return;
 | |
| 
 | |
| 	File->write("<!--", 4*sizeof(c8));
 | |
| 	writeText(comment);
 | |
| 	File->write("-->", 3*sizeof(c8));
 | |
| }
 | |
| 
 | |
| 
 | |
| //! Writes the closing tag for an element. Like </foo>
 | |
| void CXMLWriterUTF8::writeClosingTag(const c8* name)
 | |
| {
 | |
| 	if (!File || !name)
 | |
| 		return;
 | |
| 
 | |
| 	--Tabs;
 | |
| 
 | |
| 	if (Tabs > 0 && !TextWrittenLast)
 | |
| 	{
 | |
| 		for (int i=0; i<Tabs; ++i)
 | |
| 			File->write("\t", sizeof(c8));
 | |
| 	}
 | |
| 
 | |
| 	File->write("</", 2*sizeof(c8));
 | |
| 	File->write(name, strlen(name)*sizeof(c8));
 | |
| 	File->write(">", sizeof(c8));
 | |
| 	TextWrittenLast = false;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| //! Writes a text into the file. All occurrences of special characters like
 | |
| //! & (&), < (<), > (>), and " (") are automatically replaced.
 | |
| void CXMLWriterUTF8::writeText(const c8* text)
 | |
| {
 | |
| 	if (!File || !text)
 | |
| 		return;
 | |
| 
 | |
| 	static const CXMLWriterUTF8::XMLSpecialCharacters XMLWSChar[] =
 | |
| 	{
 | |
| 		{ '&', "&" },
 | |
| 		{ '<', "<" },
 | |
| 		{ '>', ">" },
 | |
| 		{ '"', """ },
 | |
| 		{ '\0', 0 }
 | |
| 	};
 | |
| 
 | |
| 	// TODO: we have to get rid of that reserve call as well as it slows down xml-writing seriously.
 | |
| 	// Making a member-variable would work, but a lot of memory would stay around after writing.
 | |
| 	// So the correct solution is probably using fixed block here and always write when that is full.
 | |
| 	core::stringc s;
 | |
| 	s.reserve(strlen(text)+1);
 | |
| 	const c8* p = text;
 | |
| 
 | |
| 	while(*p)
 | |
| 	{
 | |
| 		// check if it is matching
 | |
| 		bool found = false;
 | |
| 		for (s32 i=0; XMLWSChar[i].Character != '\0'; ++i)
 | |
| 			if (*p == XMLWSChar[i].Character)
 | |
| 			{
 | |
| 				s.append(XMLWSChar[i].Symbol);
 | |
| 				found = true;
 | |
| 				break;
 | |
| 			}
 | |
| 
 | |
| 		if (!found)
 | |
| 			s.append(*p);
 | |
| 		++p;
 | |
| 	}
 | |
| 
 | |
| 	// write new string
 | |
| 	File->write(s.c_str(), s.size()*sizeof(c8));
 | |
| 	TextWrittenLast = true;
 | |
| }
 | |
| 
 | |
| 
 | |
| //! Writes a line break
 | |
| void CXMLWriterUTF8::writeLineBreak()
 | |
| {
 | |
| 	if (!File)
 | |
| 		return;
 | |
| 
 | |
| #if defined(_IRR_OSX_PLATFORM_)
 | |
| 	File->write("\r", sizeof(c8));
 | |
| #elif defined(_IRR_WINDOWS_API_)
 | |
| 	File->write("\r\n", 2*sizeof(c8));
 | |
| #else
 | |
| 	File->write("\n", sizeof(c8));
 | |
| #endif
 | |
| 
 | |
| }
 | |
| 
 | |
| } // end namespace irr
 | |
| } // end namespace io
 | |
| 
 | |
| #endif // _IRR_COMPILE_WITH_XML_
 |