00001 #include "LoadSave.h"
00002 #include <iostream>
00003 #include <string.h>
00004 #include <sys/types.h>
00005 #include <sys/stat.h>
00006
00007 LoadSave::~LoadSave() {}
00008
00009 unsigned int LoadSave::checkCreator(const char* creator, const char buf[], unsigned int len, bool isLoading) const throw() {
00010 const char* type=buf+getSerializedSize<unsigned int>();
00011 if(strcmp(type,creator)!=0) {
00012 if(isLoading)
00013 std::cout << "*** WARNING " << creator << "::loadBuffer - corruption detected, got '" << std::string(type) << "'" << std::endl;
00014 return 0;
00015 }
00016 unsigned int sz=0;
00017 decode(sz,buf,len);
00018 return sz+stringpad;
00019 }
00020 bool LoadSave::checkCreatorInc(const char* creator, const char*& buf, unsigned int& len, bool isLoading) const throw() {
00021 if(unsigned int used=checkCreator(creator,buf,len,isLoading)) { buf+=used; len-=used; return true; }
00022 else return false;
00023 }
00024 void LoadSave::checkCreatorIncT(const char* creator, const char*& buf, unsigned int& len, bool isLoading) const throw(std::runtime_error) {
00025 if(checkCreatorInc(creator,buf,len,isLoading))
00026 return;
00027 std::string err="incorrect creator code: ";
00028 err+=creator;
00029 err+=" vs ";
00030 err+=std::string(buf,strlen(creator));
00031 throw std::runtime_error(err);
00032 }
00033
00034 unsigned int LoadSave::checkCreator(const char* creator, FILE* f, bool isLoading) const throw() {
00035 unsigned int sz=0,last;
00036 unsigned int origpos=ftell(f);
00037 char* type=NULL;
00038 if(!(last=decode(type,f))) {
00039 fseek(f,origpos,SEEK_SET);
00040 return 0;
00041 } else
00042 sz+=last;
00043 if(strncmp(type,creator,strlen(creator))!=0) {
00044 if(isLoading)
00045 std::cout << "*** WARNING " << creator << "::loadBuffer - corruption detected" << std::endl;
00046 fseek(f,origpos,SEEK_SET);
00047 delete [] type;
00048 return 0;
00049 }
00050 delete [] type;
00051 return sz;
00052 }
00053
00054 unsigned int LoadSave::saveCreator(const char* creator, char buf[], unsigned int len) const throw() {
00055 return encode(std::string(creator),buf,len);
00056 }
00057 bool LoadSave::saveCreatorInc(const char* creator, char*& buf, unsigned int& len) const throw() {
00058 if(unsigned int used=saveCreator(creator,buf,len)) { buf+=used; len-=used; return true; }
00059 else return false;
00060 }
00061 void LoadSave::saveCreatorIncT(const char* creator, char*& buf, unsigned int& len) const throw(std::runtime_error) {
00062 if(saveCreatorInc(creator,buf,len))
00063 return;
00064 std::string err="unable to save creator code: ";
00065 err+=creator;
00066 err+=" (ran out of space?)";
00067 throw std::runtime_error(err);
00068 }
00069 unsigned int LoadSave::saveCreator(const char* creator, FILE* f) const throw() {
00070 return encode(creator,f);
00071 }
00072
00073 unsigned int LoadSave::loadFile(const char* file) {
00074 int err;
00075 std::cout << "Loading: " << file << std::endl;
00076 FILE* f = fopen(file,"r");
00077 if(f==NULL) {
00078 std::cout << "*** WARNING could not open file for loading \"" << file << "\"" << std::endl;
00079 return 0;
00080 }
00081 unsigned int sz = loadFileStream(f,file);
00082 if(sz==0)
00083 std::cout << "*** WARNING loading of " << file << " failed " << std::endl;
00084 err=fclose(f);
00085 if(err!=0) {
00086 std::cout << "*** WARNING error " << err << " while closing " << file << std::endl;
00087 return 0;
00088 }
00089 return sz;
00090 }
00091
00092 unsigned int LoadSave::saveFile(const char* file) const {
00093 int err;
00094 std::cout << "Saving: " << file << std::endl;
00095 FILE* f = fopen(file,"w");
00096 if(f==NULL) {
00097 std::cout << "*** WARNING could not open file for saving \"" << file << "\"" << std::endl;
00098 return 0;
00099 }
00100 unsigned int sz = saveFileStream(f);
00101 if(sz==0)
00102 std::cout << "*** WARNING saving of " << file << " failed " << std::endl;
00103 err=fclose(f);
00104 if(err!=0) {
00105 std::cout << "*** WARNING error " << err << " while closing " << file << std::endl;
00106 return 0;
00107 }
00108 return sz;
00109 }
00110
00111 unsigned int LoadSave::loadFileStream(FILE* f, const char* filename) {
00112 struct stat sb;
00113 int err=fstat(fileno(f),&sb);
00114 if(err!=0) {
00115 if (filename)
00116 std::cerr << "File: " << filename << std::endl;
00117 perror("fstat failed in LoadSave::loadFileStream()");
00118 return 0;
00119 }
00120 long origpos=ftell(f);
00121 if(origpos<0) {
00122 if (filename)
00123 std::cerr << "File: " << filename << std::endl;
00124 perror("ftell failed in LoadSave::loadFileStream()");
00125 return 0;
00126 }
00127 size_t cap=static_cast<size_t>(sb.st_size-origpos);
00128 char * buf = NULL;
00129 try { buf=new char[cap]; } catch(...) {}
00130 if(buf==NULL) {
00131 if (filename)
00132 std::cerr << "File: " << filename << std::endl;
00133 std::cout << "*** WARNING could not allocate " << cap << "+ bytes for loadFile";
00134 return 0;
00135 }
00136 unsigned int read=fread(buf,1,cap,f);
00137 unsigned int pos=0;
00138 while(cap!=pos+read) {
00139 pos+=read;
00140 read=fread(&buf[pos],1,cap-pos,f);
00141 }
00142 unsigned int resp=loadBuffer(buf,cap);
00143 delete [] buf;
00144 if(resp!=cap)
00145 fseek(f,origpos+resp,SEEK_SET);
00146 return resp;
00147 }
00148 unsigned int LoadSave::saveFileStream(FILE* f) const {
00149 unsigned int sz=getBinSize();
00150 char * buf = new char[sz];
00151 if(buf==NULL) {
00152 std::cout << "*** ERROR could not allocate " << sz << " bytes for loadFile";
00153 return 0;
00154 }
00155 unsigned int resp=saveBuffer(buf,sz);
00156 if(resp==0) {
00157 std::cout << "*** WARNING saveBuffer (from saveFileStream) didn't write any data (possibly due to overflow or other error)" << std::endl;
00158 } else {
00159 size_t wrote = fwrite(buf,1,resp,f);
00160 if(wrote!=(size_t)resp)
00161 std::cout << "*** ERROR short write (wrote " << wrote << ", expected " << resp << ")" << std::endl;
00162 }
00163 delete [] buf;
00164 return resp;
00165 }
00166 unsigned int LoadSave::saveStream(std::ostream& os) const {
00167 unsigned int sz=getBinSize();
00168 char * buf = new char[sz];
00169 if(buf==NULL) {
00170 std::cout << "*** ERROR could not allocate " << sz << " bytes for loadFile";
00171 return 0;
00172 }
00173 unsigned int resp=saveBuffer(buf,sz);
00174 if(resp==0) {
00175 std::cout << "*** WARNING saveBuffer (from saveStream) didn't write any data (possibly due to overflow or other error)" << std::endl;
00176 } else {
00177 os.write(buf,resp);
00178 if(!os)
00179 std::cout << "*** ERROR saveStream's output stream reported bad write" << std::endl;
00180 resp=0;
00181 }
00182 delete [] buf;
00183 return resp;
00184 }
00185
00186
00187 unsigned int LoadSave::LoadFile(const char* filename) { return loadFile(filename); }
00188 unsigned int LoadSave::SaveFile(const char* filename) const { return saveFile(filename); }
00189 bool LoadSave::chkAdvance(int res, const char** buf, unsigned int* len, const char* msg, ...) {
00190 va_list al;
00191 va_start(al,msg);
00192
00193 bool ans=checkInc(res,*buf,*len,"%s",msg);
00194 va_end(al);
00195 return ans;
00196 }
00197
00198
00199
00200
00201
00202