// $Id: mmdb_io_stream.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2008. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program 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 Lesser General Public License for more details. // // ================================================================= // // 11.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : Stream // ~~~~~~~~~ // **** Classes : mmdb::io::Stream ( Basic Stream Class ) // ~~~~~~~~~ // // (C) E. Krissinel 1995-2013 // // ================================================================= // #ifndef __MMDB_IO_Stream__ #define __MMDB_IO_Stream__ #include "mmdb_io_file.h" // ******************************************************************* #ifndef __ClassMacros # define __ClassMacros // A Class definition macros # define DefineClass(ClassName) \ class ClassName; \ typedef ClassName * P##ClassName; \ typedef ClassName & R##ClassName; \ typedef P##ClassName * PP##ClassName; \ typedef P##ClassName & RP##ClassName; // A Structure definition macros # define DefineStructure(StructureName) \ struct StructureName; \ typedef StructureName * P##StructureName; \ typedef StructureName & R##StructureName; \ typedef P##StructureName * PP##StructureName; \ typedef P##StructureName & RP##StructureName; #endif #define DefineStreamFunctions(ClassName) \ extern void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ); \ extern void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ); #define MakeStreamFunctions(ClassName) \ void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ) { \ StreamWrite_ ( f,(mmdb::io::RPStream)Object ); \ } \ mmdb::io::PStream StreamInit##ClassName ( mmdb::io::RPStream Object ) { \ return (mmdb::io::PStream)(new ClassName(Object)); \ } \ void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ) { \ StreamRead_ ( f,(mmdb::io::RPStream)Object,StreamInit##ClassName );\ } #define DefineFactoryFunctions(ClassName) \ typedef P##ClassName Make##ClassName(); \ typedef Make##ClassName * PMake##ClassName; \ typedef P##ClassName StreamMake##ClassName ( mmdb::io::RPStream Object ); \ P##ClassName new##ClassName (); \ P##ClassName streamNew##ClassName ( mmdb::io::RPStream Object ); \ typedef StreamMake##ClassName * PStreamMake##ClassName; \ extern void SetMakers##ClassName ( void * defMk, void * streamMk ); \ extern void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ); \ extern void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ); #define MakeFactoryFunctions(ClassName) \ static PMake##ClassName make##ClassName = NULL; \ static PStreamMake##ClassName streamMake##ClassName = NULL; \ P##ClassName new##ClassName() { \ if (make##ClassName) return (*make##ClassName)(); \ else return new ClassName(); \ } \ P##ClassName streamNew##ClassName ( mmdb::io::RPStream Object ) { \ if (streamMake##ClassName) \ return (*streamMake##ClassName)(Object); \ else return new ClassName(Object); \ } \ void SetMakers##ClassName ( void * defMk, void * streamMk ) { \ make##ClassName = PMake##ClassName(defMk); \ streamMake##ClassName = PStreamMake##ClassName(streamMk); \ } \ void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ) { \ StreamWrite_ ( f,(mmdb::io::RPStream)Object ); \ } \ mmdb::io::PStream StreamInit##ClassName ( mmdb::io::RPStream Object ) { \ return (mmdb::io::PStream)(streamNew##ClassName(Object)); \ } \ void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ) { \ StreamRead_ ( f,(mmdb::io::RPStream)Object,StreamInit##ClassName ); \ } namespace mmdb { namespace io { // ========================== Stream =========================== // Each streamable class should be derived from Stream // and have constructor Class(PStream & Object), which should // initialize all memory of the class, and virtual functions // read(..) and write(..) (see below). Constructor Class(PStream&) // must not touch the Object variable. This constructor is used // only once just before the read(..) function. It is assumed that // read(..)/write(..) functions of the Class provide storage/reading // of all vital data. Function read(..) must read data in exactly // the same way as function write(..) stores it. // For using Class in streams, three following functions should // be supplied: // // 1. // void StreamWrite ( File & f, PClass & Object ) { // StreamWrite ( f,(PStream)Object ); // } // // 2. // PStream ClassInit ( PStream & Object ) { // return (PStream)(new Class(Object)); // } // // 3. // void StreamRead ( File & f, PClass & Object ) { // StreamRead_ ( f,(PStream)Object,ClassInit ); // } // // All these functions are automatically generated by macros // DefineStreamFunctions(Class) -- in the header -- and // MakeStreamFunctions(Class) -- in the implementation body. Note // that macro DefineClass(Class) should always be issued for // streamable classes prior to the stream-making macros. Then // Class may be streamed using functions #1 and #3. // StreamRead will return NULL for Object if it was not in // the stream. If Object existed before calling StreamRead(..) // but was not found in the stream, it will be disposed (NULL // assigned). DefineClass(Stream); DefineStreamFunctions(Stream); class Stream { public : Stream () {} Stream ( RPStream ) {} virtual ~Stream () {} virtual void read ( RFile ) {} virtual void write ( RFile ) {} }; typedef PStream InitStreamObject(RPStream Object); extern void StreamRead_ ( RFile f, RPStream Object, InitStreamObject Init ); extern void StreamWrite_ ( RFile f, RPStream Object ); } } #endif