summaryrefslogtreecommitdiff
path: root/shared/xmlBase.cpp
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:05:53 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:05:53 +0200
commit618dfb51d93898632830f1b87443d3f748780871 (patch)
treebac520a2e261154f8d35b0cb8aa345f5ab373811 /shared/xmlBase.cpp
parent3.4 (diff)
downloadFreeFileSync-618dfb51d93898632830f1b87443d3f748780871.tar.gz
FreeFileSync-618dfb51d93898632830f1b87443d3f748780871.tar.bz2
FreeFileSync-618dfb51d93898632830f1b87443d3f748780871.zip
3.5
Diffstat (limited to 'shared/xmlBase.cpp')
-rw-r--r--shared/xmlBase.cpp113
1 files changed, 81 insertions, 32 deletions
diff --git a/shared/xmlBase.cpp b/shared/xmlBase.cpp
index 759f24d2..1a41f02f 100644
--- a/shared/xmlBase.cpp
+++ b/shared/xmlBase.cpp
@@ -6,8 +6,15 @@
//
#include "xmlBase.h"
#include "globalFunctions.h"
-#include <wx/ffile.h>
#include <wx/intl.h>
+#include <wx/ffile.h>
+#include "fileIO.h"
+#include "stringConv.h"
+#include "systemConstants.h"
+#include <boost/scoped_array.hpp>
+#include <wx/log.h>
+
+using namespace FreeFileSync;
std::string getTypeName(xmlAccess::XmlType type)
@@ -30,8 +37,12 @@ std::string getTypeName(xmlAccess::XmlType type)
}
-xmlAccess::XmlType xmlAccess::getXmlType(const wxString& filename)
+xmlAccess::XmlType xmlAccess::getXmlType(const wxString& filename) //throw()
{
+#ifndef __WXDEBUG__
+ wxLogNull noWxLogs; //hide wxWidgets log messages in release build
+#endif
+
if (!wxFileExists(filename))
return XML_OTHER;
@@ -77,34 +88,70 @@ xmlAccess::XmlType xmlAccess::getXmlType(const wxString& filename)
return XML_OTHER;
}
+namespace
+{
+//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 0xD:
+ tmp.push_back(0xA);
+ if (i + 1 != stream.end() && *(i + 1) == 0xA)
+ ++i;
+ break;
+ default:
+ tmp.push_back(*i);
+ }
-bool xmlAccess::loadXmlDocument(const wxString& fileName, const xmlAccess::XmlType type, TiXmlDocument& document)
+ stream.swap(tmp);
+}
+}
+
+
+void xmlAccess::loadXmlDocument(const wxString& filename, const xmlAccess::XmlType type, TiXmlDocument& document) //throw FileError()
{
- if (!wxFileExists(fileName)) //avoid wxWidgets error message when wxFFile receives not existing file
- return false;
+ std::vector<char> inputStream;
- //workaround to get a FILE* from a unicode filename
- wxFFile dummyFile(fileName, wxT("rb")); //binary mode needed for TiXml to work correctly in this case
- if (dummyFile.IsOpened())
+ try
{
- FILE* inputFile = dummyFile.fp();
+ const size_t BUFFER_SIZE = 512 * 1024;
+ static boost::scoped_array<unsigned char> buffer(new unsigned char[BUFFER_SIZE]);
+
+ FileInput inputFile(wxToZ(filename)); //throw FileError();
+ do
+ {
+ const size_t bytesRead = inputFile.read(buffer.get(), BUFFER_SIZE); //throw FileError()
+ inputStream.insert(inputStream.end(), buffer.get(), buffer.get() + bytesRead);
+ }
+ while (!inputFile.eof());
+ }
+ catch (const FileError& error) //more detailed error messages than with wxWidgets
+ {
+ throw XmlError(error.show());
+ }
+
+ if (!inputStream.empty())
+ {
+ //convert (0xD, 0xA) and (0xD) to (0xA): just like in TiXmlDocument::LoadFile(); not sure if actually needed
+ ::normalize(inputStream);
TiXmlBase::SetCondenseWhiteSpace(false); //do not condense whitespace characters
+ document.Parse(&inputStream[0], 0, TIXML_DEFAULT_ENCODING);
+
+ TiXmlElement* root = document.RootElement();
- if (document.LoadFile(inputFile)) //load XML; fails if inputFile is no proper XML
+ if (root && (root->ValueStr() == std::string("FreeFileSync"))) //check for FFS configuration xml
{
- TiXmlElement* root = document.RootElement();
-
- if (root && (root->ValueStr() == std::string("FreeFileSync"))) //check for FFS configuration xml
- {
- const char* cfgType = root->Attribute("XmlType");
- if (cfgType)
- return std::string(cfgType) == getTypeName(type);
- }
+ const char* cfgType = root->Attribute("XmlType");
+ if (cfgType && std::string(cfgType) == getTypeName(type))
+ return; //finally... success!
}
}
- return false;
+ throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\""));
}
@@ -123,22 +170,24 @@ void xmlAccess::getDefaultXmlDocument(const XmlType type, TiXmlDocument& documen
}
-bool xmlAccess::saveXmlDocument(const wxString& fileName, const TiXmlDocument& document)
+void xmlAccess::saveXmlDocument(const wxString& filename, const TiXmlDocument& document) //throw (XmlError)
{
- //workaround to get a FILE* from a unicode filename
- wxFFile dummyFile(fileName, wxT("w")); //no need for "binary" mode here
- if (!dummyFile.IsOpened())
- return false;
-
- FILE* outputFile = dummyFile.fp();
+ //convert XML into continuous byte sequence
+ TiXmlPrinter printer;
+ printer.SetLineBreak(wxString(globalFunctions::LINE_BREAK).ToUTF8());
+ document.Accept(&printer);
+ const std::string buffer = printer.Str();
- if (!document.SaveFile(outputFile)) //save XML
- return false;
-
- return dummyFile.Flush(); //flush data to disk! (think of multiple batch jobs writing/reading)
+ try
+ {
+ FileOutput outputFile(wxToZ(filename)); //throw FileError()
+ outputFile.write(buffer.c_str(), buffer.length()); //
+ }
+ catch (const FileError& error) //more detailed error messages than with wxWidgets
+ {
+ throw XmlError(error.show());
+ }
}
-
-
//################################################################################################################
bgstack15