From 399d9468f494b3b4f5cc62c2e35aa604815af4d9 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 31 May 2012 11:50:25 +0200 Subject: [PATCH] Implement CDATA reader, fix bugs in Writer::insertBinFile --- src/App/PropertyFile.cpp | 52 +++++++++++++++++++++++++++------------- src/Base/Reader.cpp | 43 +++++++++++++++++++++++++++++---- src/Base/Reader.h | 15 ++++++++++-- src/Base/Writer.cpp | 24 +++++++------------ 4 files changed, 96 insertions(+), 38 deletions(-) diff --git a/src/App/PropertyFile.cpp b/src/App/PropertyFile.cpp index 13599c88a6..52278ea991 100644 --- a/src/App/PropertyFile.cpp +++ b/src/App/PropertyFile.cpp @@ -257,13 +257,18 @@ void PropertyFileIncluded::setPyObject(PyObject *value) void PropertyFileIncluded::Save (Base::Writer &writer) const { if (writer.isForceXML()) { - writer.Stream() << writer.ind() << "" << endl; - - // write the file in the XML stream - if (!_cValue.empty()) + if (!_cValue.empty()) { + Base::FileInfo file(_cValue.c_str()); + writer.Stream() << writer.ind() << "" << std::endl; + // write the file in the XML stream + writer.incInd(); writer.insertBinFile(_cValue.c_str()); - - writer.Stream() << writer.ind() <<"" << endl ; + writer.decInd(); + writer.Stream() << writer.ind() <<"" << endl; + } + else + writer.Stream() << writer.ind() << "" << std::endl; } else { // instead initiate an extra file @@ -280,17 +285,30 @@ void PropertyFileIncluded::Save (Base::Writer &writer) const void PropertyFileIncluded::Restore(Base::XMLReader &reader) { reader.readElement("FileIncluded"); - string file (reader.getAttribute("file") ); - - if (!file.empty()) { - // initate a file read - reader.addFile(file.c_str(),this); - - // is in the document transient path - aboutToSetValue(); - _cValue = getDocTransientPath() + "/" + file; - _BaseFileName = file; - hasSetValue(); + if (reader.hasAttribute("file")) { + string file (reader.getAttribute("file") ); + if (!file.empty()) { + // initate a file read + reader.addFile(file.c_str(),this); + // is in the document transient path + aboutToSetValue(); + _cValue = getDocTransientPath() + "/" + file; + _BaseFileName = file; + hasSetValue(); + } + } + // section is XML stream + else if (reader.hasAttribute("data")) { + string file (reader.getAttribute("data") ); + if (!file.empty()) { + // is in the document transient path + aboutToSetValue(); + _cValue = getDocTransientPath() + "/" + file; + reader.readBinFile(_cValue.c_str()); + reader.readEndElement("FileIncluded"); + _BaseFileName = file; + hasSetValue(); + } } } diff --git a/src/Base/Reader.cpp b/src/Base/Reader.cpp index db355f723f..6791b99f62 100644 --- a/src/Base/Reader.cpp +++ b/src/Base/Reader.cpp @@ -34,6 +34,7 @@ /// Here the FreeCAD includes sorted by Base,App,Gui...... #include "Reader.h" +#include "Base64.h" #include "Exception.h" #include "Persistence.h" #include "InputSource.h" @@ -79,6 +80,7 @@ Base::XMLReader::XMLReader(const char* FileName, std::istream& str) //parser->setFeature(XMLUni::fgXercesDynamic, true); parser->setContentHandler(this); + parser->setLexicalHandler(this); parser->setErrorHandler(this); try { @@ -127,7 +129,7 @@ long Base::XMLReader::getAttributeAsInteger(const char* AttrName) const if (pos != AttrMap.end()) return atol(pos->second.c_str()); else - // wrong name, use hasAttribute if not shure! + // wrong name, use hasAttribute if not sure! assert(0); return 0; @@ -140,7 +142,7 @@ unsigned long Base::XMLReader::getAttributeAsUnsigned(const char* AttrName) cons if (pos != AttrMap.end()) return strtoul(pos->second.c_str(),0,10); else - // wrong name, use hasAttribute if not shure! + // wrong name, use hasAttribute if not sure! assert(0); return 0; @@ -153,7 +155,7 @@ double Base::XMLReader::getAttributeAsFloat (const char* AttrName) const if (pos != AttrMap.end()) return atof(pos->second.c_str()); else - // wrong name, use hasAttribute if not shure! + // wrong name, use hasAttribute if not sure! assert(0); return 0.0; @@ -166,7 +168,7 @@ const char* Base::XMLReader::getAttribute (const char* AttrName) const if (pos != AttrMap.end()) return pos->second.c_str(); else - // wrong name, use hasAttribute if not shure! + // wrong name, use hasAttribute if not sure! assert(0); return ""; @@ -255,6 +257,22 @@ void Base::XMLReader::readCharacters(void) { } +void Base::XMLReader::readBinFile(const char* filename) +{ + Base::FileInfo fi(filename); + Base::ofstream to(fi, std::ios::out | std::ios::binary); + if (!to) + throw Base::Exception("XMLReader::readBinFile() Could not open file!"); + + bool ok; + do { + ok = read(); if (!ok) break; + } while (ReadType != EndCDATA); + + to << Base::base64_decode(Characters); + to.close(); +} + void Base::XMLReader::readFiles(zipios::ZipInputStream &zipstream) const { // It's possible that not all objects inside the document could be created, e.g. if a module @@ -370,15 +388,32 @@ void Base::XMLReader::endElement (const XMLCh* const /*uri*/, const XMLCh *cons ReadType = EndElement; } +void Base::XMLReader::startCDATA () +{ + ReadType = StartCDATA; +} +void Base::XMLReader::endCDATA () +{ + ReadType = EndCDATA; +} + +#if (XERCES_VERSION_MAJOR == 2) void Base::XMLReader::characters(const XMLCh* const chars, const unsigned int length) +#else +void Base::XMLReader::characters(const XMLCh* const chars, const XMLSize_t length) +#endif { Characters = StrX(chars).c_str(); ReadType = Chars; CharacterCount += length; } +#if (XERCES_VERSION_MAJOR == 2) void Base::XMLReader::ignorableWhitespace( const XMLCh* const /*chars*/, const unsigned int /*length*/) +#else +void Base::XMLReader::ignorableWhitespace( const XMLCh* const /*chars*/, const XMLSize_t /*length*/) +#endif { //fSpaceCount += length; } diff --git a/src/Base/Reader.h b/src/Base/Reader.h index 3ced7241b5..7e55575d42 100644 --- a/src/Base/Reader.h +++ b/src/Base/Reader.h @@ -131,6 +131,8 @@ public: void readEndElement(const char* ElementName=0); /// read until characters are found void readCharacters(void); + /// read binary file + void readBinFile(const char*); //@} /** @name Attribute handling */ @@ -171,8 +173,15 @@ protected: // ----------------------------------------------------------------------- virtual void startElement(const XMLCh* const uri, const XMLCh* const localname, const XMLCh* const qname, const XERCES_CPP_NAMESPACE_QUALIFIER Attributes& attrs); virtual void endElement (const XMLCh* const uri, const XMLCh *const localname, const XMLCh *const qname); - virtual void characters (const XMLCh* const chars, const unsigned int length); + virtual void startCDATA (); + virtual void endCDATA (); +#if (XERCES_VERSION_MAJOR == 2) + virtual void characters (const XMLCh* const chars, const unsigned int length); virtual void ignorableWhitespace(const XMLCh* const chars, const unsigned int length); +#else + virtual void characters (const XMLCh* const chars, const XMLSize_t length); + virtual void ignorableWhitespace(const XMLCh* const chars, const XMLSize_t length); +#endif virtual void resetDocument(); @@ -198,7 +207,9 @@ protected: Chars, StartElement, StartEndElement, - EndElement + EndElement, + StartCDATA, + EndCDATA } ReadType; diff --git a/src/Base/Writer.cpp b/src/Base/Writer.cpp index 01eecef6b5..621893a8a3 100644 --- a/src/Base/Writer.cpp +++ b/src/Base/Writer.cpp @@ -65,32 +65,26 @@ void Writer::insertAsciiFile(const char* FileName) if (!from) throw Base::Exception("Writer::insertAsciiFile() Could not open file!"); - Stream() << "" << endl; + Stream() << "]]>" << endl; } void Writer::insertBinFile(const char* FileName) { Base::FileInfo fi(FileName); - Base::ifstream from(fi, std::ios::in | std::ios::binary); + Base::ifstream from(fi, std::ios::in | std::ios::binary | std::ios::ate); if (!from) throw Base::Exception("Writer::insertAsciiFile() Could not open file!"); - Stream() << " bytes(fileSize); + from.read((char*)&bytes[0], fileSize); + Stream() << Base::base64_encode(&bytes[0], fileSize); Stream() << "]]>" << endl; }