Serializable.cc

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 

mcslogo

MCS (My Customizable Server) ver. 0.3.3-alpha3
Documentation generated on Thu Mar 22 13:22:23 UTC 2012