00001 // ----------------------------------------------------------------------^ 00002 // Copyright (C) 2004, 2005, 2006, 2007, 2008 Giorgio Calderone 00003 // (mailto: <gcalderone@ifc.inaf.it>) 00004 // 00005 // This file is part of MCS. 00006 // 00007 // MCS is free software; you can redistribute it and/or modify 00008 // it under the terms of the GNU General Public License as published by 00009 // the Free Software Foundation; either version 2 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // MCS is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with MCS; if not, write to the Free Software 00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 // 00021 // ----------------------------------------------------------------------$ 00022 00023 00024 #include "mcs.hh" 00025 using namespace mcs; 00026 00027 00028 00029 00030 //-------------------------------------------------------- 00031 void mcs::Serializable::init(int type, unsigned int lmaxChunksize) 00032 { 00033 this->type = type; 00034 buf = NULL; 00035 stream = NULL; 00036 00037 lsize = 0; 00038 from = NULL; 00039 filename = ""; 00040 freeAfterUse = false; 00041 00042 maxChunksize = lmaxChunksize; 00043 if (maxChunksize == 0) 00044 throw MCS_ERROR(MSG_SIZE_CHUNK, maxChunksize); 00045 00046 switch(type) { 00047 case MCS_SERIAL_UNKNOWN: 00048 case MCS_SERIAL_FILENAME: 00049 case MCS_SERIAL_BUFFER: 00050 break; 00051 default: 00052 throw MCS_ERROR(MSG_INVALID_SWITCH, type); 00053 } 00054 00055 serialize_end(); 00056 } 00057 00058 00059 mcs::Serializable::Serializable(unsigned int lmaxChunksize) { 00060 init(MCS_SERIAL_UNKNOWN, lmaxChunksize); 00061 } 00062 00063 00064 mcs::Serializable::Serializable(void* from, unsigned int size, 00065 bool freeAfterUse, unsigned int lmaxChunksize) 00066 { 00067 init(MCS_SERIAL_BUFFER, lmaxChunksize); 00068 this->lsize = size; 00069 this->from = (char*) from; 00070 this->freeAfterUse = freeAfterUse; 00071 } 00072 00073 00074 mcs::Serializable::Serializable(string filename, unsigned int lmaxChunksize) 00075 { 00076 init(MCS_SERIAL_FILENAME, lmaxChunksize); 00077 this->filename = filename; 00078 File_Dir_Exist(filename, lsize); 00079 } 00080 00081 00082 mcs::Serializable::Serializable(int type, unsigned int lmaxChunksize) 00083 { 00084 init(type, lmaxChunksize); 00085 } 00086 00087 00088 mcs::Serializable::~Serializable() { 00089 serialize_end(); 00090 } 00091 00092 00093 char* mcs::Serializable::nextChunk_unknown(char* userdata, char* buf, 00094 unsigned int& chunksize, bool firstTime) 00095 { 00096 throw MCS_ERROR(MSG_METHOD_MUST_BE_OVERLOADED, "Serializable::nextChunk_unknown"); 00097 } 00098 00099 char* mcs::Serializable::serialize_unknown() 00100 { 00101 return NULL; 00102 } 00103 00104 bool mcs::Serializable::serialize_buffer(char*& from, unsigned int& size) 00105 { 00106 from = this->from; 00107 size = this->lsize; 00108 return freeAfterUse; 00109 } 00110 00111 string mcs::Serializable::serialize_filename() 00112 { 00113 return filename; 00114 } 00115 00116 00117 00118 void mcs::Serializable::serialize() 00119 { 00120 //if (buf) //Maybe from getEntireBuffer 00121 // free(buf); 00122 //buf = NULL; 00123 00124 switch (type) { 00125 case MCS_SERIAL_UNKNOWN: 00126 userdata = serialize_unknown(); 00127 buf = (char*) malloc(maxChunksize); 00128 break; 00129 case MCS_SERIAL_BUFFER: 00130 freeAfterUse = serialize_buffer(from, lsize); 00131 buf = from; 00132 break; 00133 case MCS_SERIAL_FILENAME: 00134 filename = serialize_filename(); 00135 if (! File_Dir_Exist(filename, lsize)) 00136 throw MCS_ERROR(MSG_CANT_OPEN_FILE, filename.csz); 00137 00138 stream = new ifstream(filename.c_str(), ios::binary); 00139 buf = (char*) malloc(maxChunksize); 00140 break; 00141 } 00142 } 00143 00144 00145 void mcs::Serializable::serialize_end() 00146 { 00147 // LN 00148 if (type != MCS_SERIAL_BUFFER) { 00149 if (buf) 00150 free(buf); 00151 } 00152 buf = NULL; 00153 00154 if (stream) 00155 delete stream; 00156 stream = NULL; 00157 00158 if (type == MCS_SERIAL_BUFFER) 00159 if (freeAfterUse) 00160 if (from) { 00161 free(from); 00162 from = NULL; 00163 } 00164 00165 firstTime = true; 00166 } 00167 00168 00169 void* mcs::Serializable::nextChunk(unsigned int& chunksize) 00170 { 00171 unsigned int size_to_send; //To be used only if type == MCS_SERIAL_BUFFER 00172 00173 if (firstTime) 00174 serialize(); 00175 00176 switch (type) { 00177 case MCS_SERIAL_BUFFER: 00178 size_to_send = lsize - (buf - from); 00179 chunksize = ( size_to_send < maxChunksize ? size_to_send : maxChunksize ); 00180 00181 if (! firstTime) { 00182 buf += chunksize; 00183 size_to_send = lsize - (buf - from); 00184 chunksize = ( size_to_send < maxChunksize ? size_to_send : maxChunksize ); 00185 } 00186 00187 if (size_to_send == 0) { 00188 buf = NULL; //Here buf is just a cursor, it must not be freed 00189 serialize_end(); 00190 } 00191 break; 00192 00193 case MCS_SERIAL_FILENAME: 00194 if (stream->eof()) 00195 serialize_end(); 00196 else { 00197 stream->read(buf, maxChunksize); 00198 chunksize = stream->gcount(); 00199 } 00200 break; 00201 00202 case MCS_SERIAL_UNKNOWN: 00203 chunksize = maxChunksize; 00204 if (! (userdata = nextChunk_unknown(userdata, buf, chunksize, firstTime))) 00205 serialize_end(); 00206 break; 00207 } 00208 00209 if (buf) //serialize_end() hasn't been called 00210 firstTime = false; 00211 00212 return buf; 00213 } 00214 00215 00216 void* mcs::Serializable::getEntireBuffer(unsigned int& size) 00217 { 00218 unsigned int chunk; 00219 void* tmp; 00220 Buffer abuf(DONT_FREE); //* 00221 00222 while(( tmp = nextChunk(chunk) )) 00223 abuf(chunk) << tmp; 00224 00225 size = abuf.size(); 00226 return abuf[0]; 00227 //buf = abuf.buffer(); //* = will be freed in the next call to serialize 00228 //return buf; 00229 } 00230 00231 00232 bool mcs::Serializable::knowSize() 00233 { 00234 return (lsize != 0); 00235 } 00236 00237 unsigned int mcs::Serializable::nChunk() 00238 { 00239 unsigned int nchunk = (unsigned int) (floor((((float) lsize)/maxChunksize))); 00240 nchunk++; 00241 00242 return nchunk; 00243 } 00244 00245 unsigned int mcs::Serializable::size() 00246 { 00247 return lsize; 00248 } 00249 00250 00251 unsigned int mcs::Serializable::maxChunkSize() 00252 { 00253 return maxChunksize; 00254 } 00255 00256
![]() |
MCS (My Customizable Server) ver. 0.3.3-alpha3
|