Source: ../../../tse3/src/tse3/Serializable.h
|
|
|
|
/*
* @(#)Serializable.h 3.00 7 Jun 1999
*
* Copyright (c) 2000 Pete Goodliffe (pete@cthree.org)
*
* This file is part of TSE3 - the Trax Sequencer Engine version 3.00.
*
* This library is modifiable/redistributable under the terms of the GNU
* General Public License.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING. If not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef TSE3_SERIALIZABLE_H
#define TSE3_SERIALIZABLE_H
#include
#include
#include
namespace TSE3
{
class Song;
class Progress;
/**
* Data structure used by the @ref Serializable class during loading.
* It contains information that has been gained about the file, mostly
* from the "Header" chunk. Most @ref Serializable classes will not need
* to write to this struct, but will almost certainly need to read it
* (at least to convert local file PPQN resolution to TSE3 system PPQN).
*/
struct SerializableLoadInfo
{
/**
* The PPQN resolution of timestamps in this file. You can use
* this to convert timestamps to the correct values in use in the
* TSE3 library. See @ref Clock's convert() method.
* This information is read from the file's "Header" chunk.
*/
int PPQN;
/**
* The current Song. This is set once by the @ref TSE3MDL class.
* You may not write over this value afterwards or you will
* create undefined behaviour.
*/
Song *song;
/**
* The files's najor version number, read from it's "Header" chunk.
* This should be informational since the TSE3MDL file format is
* forwards and backwards compatible.
*
* The (invalid) value -1 means that no major version has been read.
*/
int major;
/**
* The file's minor version number, read from it's "Header" chunk.
* This should be informational since the TSE3MDL file format is
* forwards and backwards compatible.
*
* The (invalid) value -1 means that no minor version has been read.
*/
int minor;
/**
* A boolean flag which reports whether the loading encountered
* any unknown chunks (which will have been skipped over).
*
* If you are not using the @ref FileBlockParser class to perform
* parsing, you must set this flag to true if you come across any
* unrecognised chunks. The @ref FileBlockParser class does this
* automatically.
*/
bool unknownChunks;
/**
* A boolean flag which reports whether the loading encountered
* any unknown data lines (which will have been ignored).
*
* If you are not using the @ref FileBlockParser class to perform
* parsing, you must set this flag to true if you come across any
* unrecognised data lines. The @ref FileBlockParser class does this
* automatically.
*/
bool unknownData;
/**
* A counter which reports how many chunks (and sub-chunks) were
* in the file.
*
* If you are not using the @ref FileBlockParser class to perform
* parsing, you must increment this counter if you come across a new
* chunk. The @ref FileBlockParser class does this automatically.
*/
size_t noChunks;
/**
* If the operation that triggered this serializable operation
* provided a @ref Progress callback object, this points to it.
*
* This information is used by the @ref FileBlockParser utility.
* You do not need to handle this in client code.
*/
Progress *progress;
/**
* Sets up some default values for the struct values.
*
* These are:
* @li PPQN - @ref Clock::PPQN
* @li song - 0
* @li major - -1
* @li minor - -1
* @li unknownChunks - false
* @li unknownData - false
* @li progress - 0
*/
SerializableLoadInfo();
};
/**
* Serializable is the base class of objects that can save their state
* to a file in the block structure of the TSE3MDL specification.
* Any class that wishes to be able to persist itself needs to implement
* this interface.
*
* @sect Important note
*
* The entry point to save/load facilities is the @ref TSE3MDL
* class, you should use that rather than the @ref Song class's Serializable
* interface directly.
*
* See the @ref TSE3MDL class documentation for more details.
*
* @sect File format
*
* Data is to be saved in the TSE3MDL file format. Each object will save
* an amount of data in a block, whose format follows the layout below.
*
*
* IDENTIFIER
* {
* DATA_TAG1:DATA
* DATA_TAG2:DATA
* }
*
*
* One data item exists per line. A mechanism exists to determine the
* number of indentation spaces that precedes each line (it is passed
* as a parameter to each @ref save() call). There are means to make
* it easy to produce this indentation (see the @ref indent() method).
*
* When parsing the data unrecognised data items should be ignored, and
* unrecognised chunks shall be skipped.
*
* The file format is further described in the HTML documentation that
* comes with the TSE3 library, in the "doc" directory.
*
* @short Interface for serializable data
* @author Pete Goodliffe
* @version 1.00
* @see TSE3MDL
*/
class Serializable
{
public:
Serializable() {}
virtual ~Serializable() {}
/**
* This method causes the Serializable object to save a block
* representing it's state to the ostream. The block will consist
* of an opening "{" line, the data, zero or more sub-blocks
* and a closing "}" line.
*
* It is the caller's responsibility to put an identifying tag
* line in the ostream before calling this method so that it can
* uniquely identify this Serializable.
*
* Calls to Serializable::save naturally nest. For example, the Song
* Serializable class calls save on the @ref Track Serializable
* class (amongst others).
*
* The default save will save an empty block.
* (Not much use really ;-)
*
* @param out ostream to send output to
* @param indentLevel Current indent level (this will produce
* indentLevel*4 spaces at the start of the
* output lines).
*/
virtual void save(std::ostream &out, int indentLevel) const;
/**
* This method loads a block for this particular Serializable
* object. It is a precondition that it was a Serialiazble object
* of this particular type that saved the block.
*
* The block tag will have been consumed from the stream, and the
* next line to be parsed will be the opening "{". The block
* and any sub-blocks (whether recognised or not) will be read
* from the stream up to and including the closing "}".
*
* The default load will just skip the block without attempting
* to interpret the contents.
*
* A utility class exists to aid writing the load method. This is
* the @ref FileBlockParser, and it's related classes.
*
* @param in istream to take input from
* @param info Object holding information about the @ref Song
* being loaded
* @see FileBlockParser.
* @see SerializableLoadInfo
*/
virtual void load(std::istream &in, SerializableLoadInfo &info);
protected:
class indent
{
public:
indent(int lvl) : level(lvl) {}
int level;
};
friend std::ostream &operator<<(std::ostream &, const indent &);
private:
Serializable &operator=(const Serializable &);
Serializable(const Serializable &);
};
/**
* Used by implementations of Serializable::save.
*
* An implementation can call this to indent the line to the
* given level.
*
* e.g. o << indent(5) << "DATA_TAG:" << data << "\n";
*
* @internal
*/
inline std::ostream &operator<<(std::ostream &s,
const Serializable::indent &i)
{
for (int n = 0; n < i.level; ++n) s << " ";
return s;
}
}
#endif
Generated by: pete on philemon on Wed May 25 14:39:52 2005, using kdoc 2.0a54. |