📄 xml_writer.cpp
字号:
/* $Id: xml_writer.cpp,v 1.12 2004/01/09 22:15:25 grumbel Exp $
**
** ClanLib Game SDK
** Copyright (C) 2003 The ClanLib Team
** For a total list of contributers see the file CREDITS.
**
** 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; either
** version 2.1 of the License, or (at your option) any later version.
**
** 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Core/precomp.h"
#include "API/Core/XML/xml_writer.h"
#include "API/Core/XML/xml_token_save.h"
#include "API/Core/System/clanstring.h"
#include "xml_writer_generic.h"
//static std::string insert_escapes(std::string str);
static std::string insert_escapes_fast(std::string str);
/////////////////////////////////////////////////////////////////////////////
// CL_XMLWriter construction:
CL_XMLWriter::CL_XMLWriter() : impl(0)
{
}
CL_XMLWriter::CL_XMLWriter(const CL_XMLWriter ©) : impl(copy.impl)
{
if (impl) impl->add_ref();
}
CL_XMLWriter::CL_XMLWriter(CL_OutputSource *output, bool delete_output) : impl(new CL_XMLWriter_Generic)
{
impl->output = output;
impl->delete_output = delete_output;
impl->add_ref();
}
CL_XMLWriter::~CL_XMLWriter()
{
if (impl) impl->release_ref();
}
/////////////////////////////////////////////////////////////////////////////
// CL_XMLWriter attributes:
bool CL_XMLWriter::get_insert_whitespace() const
{
return impl->insert_whitespace;
}
void CL_XMLWriter::set_insert_whitespace(bool enable)
{
impl->insert_whitespace = enable;
}
/////////////////////////////////////////////////////////////////////////////
// CL_XMLWriter operations:
CL_XMLWriter &CL_XMLWriter::operator =(const CL_XMLWriter ©)
{
if (impl) impl->release_ref();
impl = copy.impl;
if (impl) impl->add_ref();
return *this;
}
void CL_XMLWriter::write(const CL_XMLTokenSave &token)
{
if (!impl) return;
std::string str;
switch (token.get_type())
{
case CL_XMLToken::NULL_TOKEN:
return; // should this throw exception instead?
case CL_XMLToken::ELEMENT_TOKEN:
if (token.get_variant() == CL_XMLToken::END)
{
str = CL_String::format("</%1>", insert_escapes_fast(token.get_name()));
}
else
{
str = CL_String::format("<%1", insert_escapes_fast(token.get_name()));
int size = token.get_attributes_number();
for (int i=0; i<size; i++)
{
std::pair<std::string, std::string> attribute(token.get_attribute(i));
str.append(CL_String::format(" %1=\"%2\"", insert_escapes_fast(attribute.first), insert_escapes_fast(attribute.second)));
}
if (token.get_variant() == CL_XMLToken::SINGLE)
str.append("/>");
else
str.append(">");
}
break;
case CL_XMLToken::TEXT_TOKEN:
str = insert_escapes_fast(token.get_value());
break;
case CL_XMLToken::CDATA_SECTION_TOKEN:
str = CL_String::format("<!CDATA[%1]]>", token.get_value());
break;
case CL_XMLToken::COMMENT_TOKEN:
str = CL_String::format("<!--%1-->", token.get_value());
break;
case CL_XMLToken::ENTITY_REFERENCE_TOKEN:
case CL_XMLToken::ENTITY_TOKEN:
case CL_XMLToken::PROCESSING_INSTRUCTION_TOKEN:
case CL_XMLToken::DOCUMENT_TYPE_TOKEN:
case CL_XMLToken::NOTATION_TOKEN:
return; // not implemented yet.
}
if (token.get_variant() == CL_XMLToken::END)
{
impl->indent--;
}
if (impl->insert_whitespace)
{
std::string indent_tabs(impl->indent, '\t');
impl->output->write(indent_tabs.data(), indent_tabs.size());
}
impl->output->write(str.data(), str.size());
if (impl->insert_whitespace)
{
#ifdef WIN32
impl->output->write("\r\n", 2);
#else
impl->output->write("\n", 2);
#endif
}
if (token.get_variant() == CL_XMLToken::BEGIN)
{
impl->indent++;
}
}
/////////////////////////////////////////////////////////////////////////////
// CL_XMLWriter implementation:
#if 0
static std::string insert_escapes(std::string str)
{
std::string::size_type pos;
pos = 0;
while (pos != std::string::npos)
{
pos = str.find("&", pos);
if (pos == std::string::npos) break;
str.replace( pos, 1, "&" );
pos++;
}
pos = 0;
while (pos != std::string::npos)
{
pos = str.find("\"", pos);
if (pos == std::string::npos) break;
str.replace( pos, 1, """ );
pos++;
}
pos = 0;
while (pos != std::string::npos)
{
pos = str.find("\'", pos);
if (pos == std::string::npos) break;
str.replace( pos, 1, "'" );
pos++;
}
pos = 0;
while (pos != std::string::npos)
{
pos = str.find("<", pos);
if (pos == std::string::npos) break;
str.replace( pos, 1, "<" );
pos++;
}
pos = 0;
while (pos != std::string::npos)
{
pos = str.find(">", pos);
if (pos == std::string::npos) break;
str.replace( pos, 1, ">" );
pos++;
}
return str;
}
#endif
static std::string insert_escapes_fast(std::string str)
{
static std::string const amp("&");
static std::string const quot(""");
static std::string const apos("'");
static std::string const lt("<");
static std::string const gt(">");
std::string::size_type pos = 0;
while (pos < str.size())
{
switch(str[pos])
{
case '&':
str.replace(pos, 1, amp);
pos += amp.size();
break;
case '\'':
str.replace(pos, 1, apos);
pos += apos.size();
break;
case '\"':
str.replace(pos, 1, quot);
pos += quot.size();
break;
case '<':
str.replace(pos, 1, lt);
pos += lt.size();
break;
case '>':
str.replace(pos, 1, gt);
pos += gt.size();
break;
default:
++pos;
break;
}
}
return str;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -