Files
create/src/Base/Persistence.h
2025-10-14 10:00:04 -05:00

175 lines
7.6 KiB
C++

// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef APP_PERSISTENCE_H
#define APP_PERSISTENCE_H
#include "BaseClass.h"
namespace Base
{
class Reader;
class Writer;
class XMLReader;
/// Persistence class and root of the type system
class BaseExport Persistence: public BaseClass
{
TYPESYSTEM_HEADER();
public:
/**
* @brief Get the size of objects.
*
* It is not meant to have the exact size, it is more or less a fast
* estimation to tell whether it is two bytes or a GB.
*/
virtual unsigned int getMemSize() const = 0;
/** This method is used to save properties to an XML document.
* A good example you'll find in PropertyStandard.cpp, e.g. the vector:
* \code
* void PropertyVector::Save (Writer &writer) const
* {
* writer << writer.ind() << "<PropertyVector valueX=\"" << _cVec.x <<
* "\" valueY=\"" << _cVec.y <<
* "\" valueZ=\"" << _cVec.z <<"\"/>" << endl;
* }
* \endcode
* The writer.ind() expression writes the indentation, just for pretty printing of the XML.
* As you see, the writing of the XML document is not done with a DOM implementation because
* of performance reasons. Therefore the programmer has to take care that a valid XML document
* is written. This means closing tags and writing UTF-8.
* @see Base::Writer
*/
virtual void Save(Writer& /*writer*/) const = 0;
/** This method is used to restore properties from an XML document.
* It uses the XMLReader class, which bases on SAX, to read the in Save()
* written information. Again the Vector as an example:
* \code
* void PropertyVector::Restore(Base::XMLReader &reader)
* {
* // read my Element
* reader.readElement("PropertyVector");
* // get the value of my Attribute
* _cVec.x = reader.getAttribute<double>("valueX");
* _cVec.y = reader.getAttribute<double>("valueY");
* _cVec.z = reader.getAttribute<double>("valueZ");
* }
* \endcode
*/
virtual void Restore(XMLReader& /*reader*/) = 0;
/** This method is used to save large amounts of data to a binary file.
* Sometimes it makes no sense to write property data as XML. In case the
* amount of data is too big or the data type has a more effective way to
* save itself. In this cases it is possible to write the data in a separate file
* inside the document archive. In case you want do so you have to re-implement
* SaveDocFile(). First, you have to inform the framework in Save() that you want do so.
* Here an example from the Mesh module which can save a (pontetionaly big) triangle mesh:
* \code
* void PropertyMeshKernel::Save (Base::Writer &writer) const
* {
* if (writer.isForceXML())
* {
* writer << writer.ind() << "<Mesh>" << std::endl;
* MeshCore::MeshDocXML saver(*_pcMesh);
* saver.Save(writer);
* }else{
* writer << writer.ind() << "<Mesh file=\"" << writer.addFile("MeshKernel.bms", this) <<
* "\"/>" << std::endl;
* }
* \endcode
* The writer.isForceXML() is an indication to force you to write XML. Regardless of size and
* effectiveness. The second part informs the Base::writer through
* writer.addFile("MeshKernel.bms", this) that this object wants to write a file with the given
* name. The method addFile() returns a unique name that then is written in the XML stream. This
* allows your RestoreDocFile() method to identify and read the file again. Later your
* SaveDocFile() method is called as many times as you issued the addFile() call: \code void
* PropertyMeshKernel::SaveDocFile (Base::Writer &writer) const
* {
* _pcMesh->Write( writer );
* }
* \endcode
* In this method you can simply stream your content to the file (Base::Writer inheriting from
* ostream).
*/
virtual void SaveDocFile(Writer& /*writer*/) const;
/** This method is used to restore large amounts of data from a file
* In this method you simply stream in your SaveDocFile() saved data.
* Again you have to apply for the call of this method in the Restore() call:
* \code
* void PropertyMeshKernel::Restore(Base::XMLReader &reader)
* {
* reader.readElement("Mesh");
* std::string file (reader.getAttribute<const char*>("file") );
*
* if(file == "")
* {
* // read XML
* MeshCore::MeshDocXML restorer(*_pcMesh);
* restorer.Restore(reader);
* }else{
* // initiate a file read
* reader.addFile(file.c_str(),this);
* }
* }
* \endcode
* After you issued the reader.addFile() your RestoreDocFile() is called:
* \code
* void PropertyMeshKernel::RestoreDocFile(Base::Reader &reader)
* {
* _pcMesh->Read( reader );
* }
* \endcode
* @see Base::Reader,Base::XMLReader
*/
virtual void RestoreDocFile(Reader& /*reader*/);
/// Encodes an attribute upon saving.
static std::string encodeAttribute(const std::string&);
/// Replaces all characters with '_' that are not allowed in XML
static std::string validateXMLString(const std::string& str);
// dump the binary persistence data into into the stream
void dumpToStream(std::ostream& stream, int compression);
// restore the binary persistence data from a stream. Must have the format used by dumpToStream
void restoreFromStream(std::istream& stream);
private:
/** This method is used at the end of restoreFromStream()
* after all data files have been read in.
* A subclass can set up some internals. The default
* implementation does nothing.
*/
virtual void restoreFinished()
{}
};
} // namespace Base
#endif // APP_PERSISTENCE_H