1 // $Id: mmdb_io_stream.h $ 2 // ================================================================= 3 // 4 // CCP4 Coordinate Library: support of coordinate-related 5 // functionality in protein crystallography applications. 6 // 7 // Copyright (C) Eugene Krissinel 2000-2008. 8 // 9 // This library is free software: you can redistribute it and/or 10 // modify it under the terms of the GNU Lesser General Public 11 // License version 3, modified in accordance with the provisions 12 // of the license to address the requirements of UK law. 13 // 14 // You should have received a copy of the modified GNU Lesser 15 // General Public License along with this library. If not, copies 16 // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php 17 // 18 // This program is distributed in the hope that it will be useful, 19 // but WITHOUT ANY WARRANTY; without even the implied warranty of 20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 // GNU Lesser General Public License for more details. 22 // 23 // ================================================================= 24 // 25 // 11.09.13 <-- Date of Last Modification. 26 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 // ----------------------------------------------------------------- 28 // 29 // **** Module : Stream <interface> 30 // ~~~~~~~~~ 31 // **** Classes : mmdb::io::Stream ( Basic Stream Class ) 32 // ~~~~~~~~~ 33 // 34 // (C) E. Krissinel 1995-2013 35 // 36 // ================================================================= 37 // 38 39 #ifndef __MMDB_IO_Stream__ 40 #define __MMDB_IO_Stream__ 41 42 #include "mmdb_io_file.h" 43 44 // ******************************************************************* 45 46 #ifndef __ClassMacros 47 48 # define __ClassMacros 49 50 // A Class definition macros 51 # define DefineClass(ClassName) \ 52 class ClassName; \ 53 typedef ClassName * P##ClassName; \ 54 typedef ClassName & R##ClassName; \ 55 typedef P##ClassName * PP##ClassName; \ 56 typedef P##ClassName & RP##ClassName; 57 58 // A Structure definition macros 59 # define DefineStructure(StructureName) \ 60 struct StructureName; \ 61 typedef StructureName * P##StructureName; \ 62 typedef StructureName & R##StructureName; \ 63 typedef P##StructureName * PP##StructureName; \ 64 typedef P##StructureName & RP##StructureName; 65 66 #endif 67 68 69 #define DefineStreamFunctions(ClassName) \ 70 extern void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ); \ 71 extern void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ); 72 73 74 #define MakeStreamFunctions(ClassName) \ 75 void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ) { \ 76 StreamWrite_ ( f,(mmdb::io::RPStream)Object ); \ 77 } \ 78 mmdb::io::PStream StreamInit##ClassName ( mmdb::io::RPStream Object ) { \ 79 return (mmdb::io::PStream)(new ClassName(Object)); \ 80 } \ 81 void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ) { \ 82 StreamRead_ ( f,(mmdb::io::RPStream)Object,StreamInit##ClassName );\ 83 } 84 85 #define DefineFactoryFunctions(ClassName) \ 86 typedef P##ClassName Make##ClassName(); \ 87 typedef Make##ClassName * PMake##ClassName; \ 88 typedef P##ClassName StreamMake##ClassName ( mmdb::io::RPStream Object ); \ 89 P##ClassName new##ClassName (); \ 90 P##ClassName streamNew##ClassName ( mmdb::io::RPStream Object ); \ 91 typedef StreamMake##ClassName * PStreamMake##ClassName; \ 92 extern void SetMakers##ClassName ( void * defMk, void * streamMk ); \ 93 extern void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ); \ 94 extern void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ); 95 96 97 #define MakeFactoryFunctions(ClassName) \ 98 static PMake##ClassName make##ClassName = NULL; \ 99 static PStreamMake##ClassName streamMake##ClassName = NULL; \ 100 P##ClassName new##ClassName() { \ 101 if (make##ClassName) return (*make##ClassName)(); \ 102 else return new ClassName(); \ 103 } \ 104 P##ClassName streamNew##ClassName ( mmdb::io::RPStream Object ) { \ 105 if (streamMake##ClassName) \ 106 return (*streamMake##ClassName)(Object); \ 107 else return new ClassName(Object); \ 108 } \ 109 void SetMakers##ClassName ( void * defMk, void * streamMk ) { \ 110 make##ClassName = PMake##ClassName(defMk); \ 111 streamMake##ClassName = PStreamMake##ClassName(streamMk); \ 112 } \ 113 void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ) { \ 114 StreamWrite_ ( f,(mmdb::io::RPStream)Object ); \ 115 } \ 116 mmdb::io::PStream StreamInit##ClassName ( mmdb::io::RPStream Object ) { \ 117 return (mmdb::io::PStream)(streamNew##ClassName(Object)); \ 118 } \ 119 void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ) { \ 120 StreamRead_ ( f,(mmdb::io::RPStream)Object,StreamInit##ClassName ); \ 121 } 122 123 namespace mmdb { 124 125 namespace io { 126 127 // ========================== Stream =========================== 128 129 // Each streamable class should be derived from Stream 130 // and have constructor Class(PStream & Object), which should 131 // initialize all memory of the class, and virtual functions 132 // read(..) and write(..) (see below). Constructor Class(PStream&) 133 // must not touch the Object variable. This constructor is used 134 // only once just before the read(..) function. It is assumed that 135 // read(..)/write(..) functions of the Class provide storage/reading 136 // of all vital data. Function read(..) must read data in exactly 137 // the same way as function write(..) stores it. 138 // For using Class in streams, three following functions should 139 // be supplied: 140 // 141 // 1. 142 // void StreamWrite ( File & f, PClass & Object ) { 143 // StreamWrite ( f,(PStream)Object ); 144 // } 145 // 146 // 2. 147 // PStream ClassInit ( PStream & Object ) { 148 // return (PStream)(new Class(Object)); 149 // } 150 // 151 // 3. 152 // void StreamRead ( File & f, PClass & Object ) { 153 // StreamRead_ ( f,(PStream)Object,ClassInit ); 154 // } 155 // 156 // All these functions are automatically generated by macros 157 // DefineStreamFunctions(Class) -- in the header -- and 158 // MakeStreamFunctions(Class) -- in the implementation body. Note 159 // that macro DefineClass(Class) should always be issued for 160 // streamable classes prior to the stream-making macros. Then 161 // Class may be streamed using functions #1 and #3. 162 // StreamRead will return NULL for Object if it was not in 163 // the stream. If Object existed before calling StreamRead(..) 164 // but was not found in the stream, it will be disposed (NULL 165 // assigned). 166 167 168 DefineClass(Stream); 169 DefineStreamFunctions(Stream); 170 171 class Stream { 172 public : Stream()173 Stream () {} Stream(RPStream)174 Stream ( RPStream ) {} ~Stream()175 virtual ~Stream () {} read(RFile)176 virtual void read ( RFile ) {} write(RFile)177 virtual void write ( RFile ) {} 178 }; 179 180 181 typedef PStream InitStreamObject(RPStream Object); 182 183 extern void StreamRead_ ( RFile f, RPStream Object, 184 InitStreamObject Init ); 185 186 extern void StreamWrite_ ( RFile f, RPStream Object ); 187 188 189 } 190 191 } 192 193 #endif 194