summaryrefslogtreecommitdiff
path: root/shared/xml_base.cpp
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:12:17 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:12:17 +0200
commitb654dbfa5f3e4a4d02f72023f7c5895635aa6396 (patch)
tree8c1dfe7f638c0fc7afc1d08bc2fc0fd0f8646e5e /shared/xml_base.cpp
parent3.17 (diff)
downloadFreeFileSync-b654dbfa5f3e4a4d02f72023f7c5895635aa6396.tar.gz
FreeFileSync-b654dbfa5f3e4a4d02f72023f7c5895635aa6396.tar.bz2
FreeFileSync-b654dbfa5f3e4a4d02f72023f7c5895635aa6396.zip
3.18
Diffstat (limited to 'shared/xml_base.cpp')
-rw-r--r--shared/xml_base.cpp316
1 files changed, 42 insertions, 274 deletions
diff --git a/shared/xml_base.cpp b/shared/xml_base.cpp
index efed738a..3b786fe8 100644
--- a/shared/xml_base.cpp
+++ b/shared/xml_base.cpp
@@ -5,328 +5,96 @@
// **************************************************************************
//
#include "xml_base.h"
-#include "file_io.h"
-#include "i18n.h"
-#include "string_conv.h"
-#include "system_constants.h"
-#include "file_handling.h"
+#include <file_handling.h>
+#include <string_conv.h>
+#include <file_io.h>
+#include <i18n.h>
+#include <system_constants.h>
using namespace zen;
-using namespace xmlAccess;
-namespace
+void xmlAccess::loadXmlDocument(const wxString& filename, XmlDoc& doc) //throw FfsXmlError()
{
-//convert (0xD, 0xA) and (0xD) to 0xA: just like in TiXmlDocument::LoadFile(); not sure if actually needed
-void normalize(std::vector<char>& stream)
-{
- std::vector<char> tmp;
- for (std::vector<char>::const_iterator i = stream.begin(); i != stream.end(); ++i)
- switch (*i)
- {
- case '\xD':
- tmp.push_back('\xA');
- if (i + 1 != stream.end() && *(i + 1) == '\xA')
- ++i;
- break;
- default:
- tmp.push_back(*i);
- }
-
- stream.swap(tmp);
-}
-
-
-void parseRawXmlDocument(const wxString& filename, TiXmlDocument& document) //throw XmlError()
-{
- const zen::UInt64 fs = zen::getFilesize(wxToZ(filename));
-
+ std::string stream;
try
{
+ const zen::UInt64 fs = zen::getFilesize(wxToZ(filename)); //throw (FileError)
{
//quick test whether input is an XML: avoid loading large binary files up front!
- std::string xmlBegin = "<?xml version=";
+ //doesn't correctly handle BOM! (but no issue yet...)
+ const std::string xmlBegin = "<?xml version=";
std::vector<char> buffer(xmlBegin.size());
FileInput inputFile(wxToZ(filename)); //throw (FileError);
const size_t bytesRead = inputFile.read(&buffer[0], buffer.size()); //throw (FileError)
if (bytesRead < xmlBegin.size() || !std::equal(buffer.begin(), buffer.end(), xmlBegin.begin()))
- throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\""));
+ throw FfsXmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\""));
}
- std::vector<char> buffer(to<size_t>(fs) + 1); //inc. null-termination (already set!)
+ stream.resize(to<size_t>(fs));
FileInput inputFile(wxToZ(filename)); //throw (FileError);
- const size_t bytesRead = inputFile.read(&buffer[0], to<size_t>(fs)); //throw (FileError)
+ const size_t bytesRead = inputFile.read(&stream[0], stream.size()); //throw (FileError)
if (bytesRead < to<size_t>(fs))
{
wxString errorMessage = wxString(_("Error reading file:")) + wxT("\n\"") + filename + wxT("\"");
- throw XmlError(errorMessage + wxT("\n\n"));
+ throw FfsXmlError(errorMessage + wxT("\n\n"));
}
-
- //convert (0xD, 0xA) and (0xD) to (0xA): just like in TiXmlDocument::LoadFile(); not sure if actually needed
- normalize(buffer);
-
- document.Parse(&buffer[0], 0, TIXML_ENCODING_UTF8); //respect null-termination!
}
catch (const FileError& error) //more detailed error messages than with wxWidgets
{
- throw XmlError(error.msg());
+ throw FfsXmlError(error.msg());
}
-}
-}
-
-
-void xmlAccess::loadXmlDocument(const wxString& filename, TiXmlDocument& document) //throw XmlError()
-{
- TiXmlBase::SetCondenseWhiteSpace(false); //do not condense whitespace characters
- ::parseRawXmlDocument(filename, document); //throw XmlError()
-
- TiXmlElement* root = document.RootElement();
- if (!root)
- throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\""));
-}
-
-
-namespace
-{
-bool saveNecessary(const Zstring& filename, const std::string& dataToWrite) //throw()
-{
try
{
- if (zen::getFilesize(filename) != static_cast<unsigned long>(dataToWrite.size())) //throw (FileError);
- return true;
-
- std::vector<char> inputBuffer(dataToWrite.size() + 1); //+ 1 in order to test for end of file!
-
- FileInput inputFile(filename); //throw (FileError);
-
- const size_t bytesRead = inputFile.read(&inputBuffer[0], inputBuffer.size()); //throw (FileError)
- if (bytesRead != dataToWrite.size()) //implicit test for eof!
- return true;
-
- return ::memcmp(&inputBuffer[0], dataToWrite.c_str(), dataToWrite.size()) != 0;
- }
- catch (const FileError&)
- {
- return true;
+ zen::parse(stream, doc); //throw XmlParsingError
}
-}
-}
-
-
-void xmlAccess::saveXmlDocument(const wxString& filename, const TiXmlDocument& document) //throw (XmlError)
-{
- TiXmlBase::SetCondenseWhiteSpace(false); //do not condense whitespace characters
-
- //convert XML into continuous byte sequence
- TiXmlPrinter printer;
- printer.SetLineBreak(wxString(common::LINE_BREAK).ToUTF8());
- document.Accept(&printer);
- const std::string buffer = printer.Str();
-
- if (saveNecessary(wxToZ(filename), buffer)) //only write file if different data will be written
+ catch (const XmlParsingError&)
{
- try
- {
- FileOutput outputFile(wxToZ(filename), FileOutput::ACC_OVERWRITE); //throw (FileError)
- outputFile.write(buffer.c_str(), buffer.length()); //
- }
- catch (const FileError& error) //more detailed error messages than with wxWidgets
- {
- throw XmlError(error.msg());
- }
+ throw FfsXmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\""));
}
}
-//################################################################################################################
-bool xmlAccess::readXmlElement(const std::string& name, const TiXmlElement* parent, std::string& output)
+const wxString xmlAccess::getErrorMessageFormatted(const XmlIn& in)
{
- if (parent)
- {
- const TiXmlElement* child = parent->FirstChildElement(name);
- if (child)
- {
- const char* text = child->GetText();
- if (text) //may be NULL!!
- output = text;
- else //NULL means empty string
- output.clear();
- return true;
- }
- }
-
- return false;
-}
-
+ wxString errorMessage = wxString(_("Could not read values for the following XML nodes:")) + wxT("\n");
-bool xmlAccess::readXmlElement(const std::string& name, const TiXmlElement* parent, wxString& output)
-{
- std::string tempString;
- if (!readXmlElement(name, parent, tempString))
- return false;
+ std::vector<wxString> failedNodes = in.getErrorsAs<wxString>();
+ std::for_each(failedNodes.begin(), failedNodes.end(),
+ [&](const wxString& str) { errorMessage += str + wxT('\n'); });
- output = wxString::FromUTF8(tempString.c_str());
- return true;
+ return errorMessage;
}
-bool xmlAccess::readXmlElement(const std::string& name, const TiXmlElement* parent, bool& output)
+void xmlAccess::saveXmlDocument(const zen::XmlDoc& doc, const wxString& filename) //throw (FfsXmlError)
{
- std::string dummy;
- if (readXmlElement(name, parent, dummy))
- {
- output = dummy == "true";
- return true;
- }
- else
- return false;
-}
+ std::string stream = serialize(doc); //throw ()
-
-bool xmlAccess::readXmlElement(const std::string& name, const TiXmlElement* parent, std::vector<wxString>& output)
-{
- if (parent)
+ bool saveNecessary = true;
+ try
{
- //load elements
- const TiXmlElement* xmlList = parent->FirstChildElement(name);
- if (xmlList)
- {
- output.clear();
- for (const TiXmlElement* item = xmlList->FirstChildElement("Item"); item != NULL; item = item->NextSiblingElement())
+ if (zen::getFilesize(wxToZ(filename)) == stream.size()) //throw FileError
+ try
{
- const char* text = item->GetText();
- if (text) //may be NULL!!
- output.push_back(wxString::FromUTF8(text));
- else
- output.push_back(wxEmptyString);
+ if (zen::loadStream(filename) == stream) //throw XmlFileError
+ saveNecessary = false;
}
- return true;
- }
+ catch(const zen::XmlFileError&) {}
}
+ catch (FileError&) {}
- return false;
-}
-
-
-bool xmlAccess::readXmlAttribute(const std::string& name, const TiXmlElement* node, std::string& output)
-{
- if (node)
- {
- const std::string* attrib = node->Attribute(name);
- if (attrib) //may be NULL!
+ if (saveNecessary)
+ try
{
- output = *attrib;
- return true;
+ FileOutput outputFile(wxToZ(filename), FileOutput::ACC_OVERWRITE); //throw (FileError)
+ outputFile.write(stream.c_str(), stream.length()); //
+ }
+ catch (const FileError& error) //more detailed error messages than with wxWidgets
+ {
+ throw FfsXmlError(error.msg());
}
- }
- return false;
-}
-
-
-bool xmlAccess::readXmlAttribute(const std::string& name, const TiXmlElement* node, wxString& output)
-{
- std::string tempString;
- if (!readXmlAttribute(name, node, tempString))
- return false;
-
- output = wxString::FromUTF8(tempString.c_str());
- return true;
-}
-
-
-bool xmlAccess::readXmlAttribute(const std::string& name, const TiXmlElement* node, bool& output)
-{
- std::string dummy;
- if (readXmlAttribute(name, node, dummy))
- {
- output = dummy == "true";
- return true;
- }
- else
- return false;
-}
-
-
-//################################################################################################################
-
-
-void xmlAccess::addXmlElement(const std::string& name, const std::string& value, TiXmlElement* parent)
-{
- if (parent)
- {
- TiXmlElement* subElement = new TiXmlElement(name);
- parent->LinkEndChild(subElement);
- subElement->LinkEndChild(new TiXmlText(value));
- }
-}
-
-
-void xmlAccess::addXmlElement(const std::string& name, const wxString& value, TiXmlElement* parent)
-{
- addXmlElement(name, std::string(value.ToUTF8()), parent);
-}
-
-
-void xmlAccess::addXmlElement(const std::string& name, const bool value, TiXmlElement* parent)
-{
- if (value)
- addXmlElement(name, std::string("true"), parent);
- else
- addXmlElement(name, std::string("false"), parent);
-}
-
-
-void xmlAccess::addXmlElement(const std::string& name, const std::vector<wxString>& value, TiXmlElement* parent)
-{
- if (parent)
- {
- TiXmlElement* xmlList= new TiXmlElement(name);
- parent->LinkEndChild(xmlList);
-
- for (std::vector<wxString>::const_iterator i = value.begin(); i != value.end(); ++i)
- addXmlElement("Item", std::string(i->ToUTF8()), xmlList);
- }
-}
-
-
-void xmlAccess::addXmlAttribute(const std::string& name, const std::string& value, TiXmlElement* node)
-{
- if (node)
- node->SetAttribute(name, value);
-}
-
-
-void xmlAccess::addXmlAttribute(const std::string& name, const wxString& value, TiXmlElement* node)
-{
- addXmlAttribute(name, std::string(value.ToUTF8()), node);
-}
-
-
-void xmlAccess::addXmlAttribute(const std::string& name, const bool value, TiXmlElement* node)
-{
- if (value)
- addXmlAttribute(name, std::string("true"), node);
- else
- addXmlAttribute(name, std::string("false"), node);
-}
-
-
-using xmlAccess::XmlErrorLogger;
-
-void XmlErrorLogger::logError(const std::string& nodeName)
-{
- failedNodes.push_back(wxString::FromUTF8(nodeName.c_str()));
-}
-
-
-const wxString XmlErrorLogger::getErrorMessageFormatted() const
-{
- wxString errorMessage = wxString(_("Could not read values for the following XML nodes:")) + wxT("\n");
- for (std::vector<wxString>::const_iterator i = failedNodes.begin(); i != failedNodes.end(); ++i)
- errorMessage += wxString(wxT("<")) + *i + wxT(">") + ((i - failedNodes.begin() + 1) % 3 == 0 ? wxT("\n") : wxT(" "));
- return errorMessage;
}
-
bgstack15