Flex.cc

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2000  Dancer A.L Vesperman
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #  include <config.h>
00021 #endif
00022 
00023 #ifndef PENTAGRAM // DONT'T INCLUDE THIS IN PENTAGRAM!
00024 
00025 #define DEBUGFLEX 0
00026 
00027 #include "Flex.h"
00028 
00029 #ifndef ALPHA_LINUX_CXX
00030 #  include <cstdio>
00031 #endif
00032 #include <fstream>
00033 #include <iostream>
00034 #include "exceptions.h"
00035 #include "utils.h"
00036 #include "databuf.h"
00037 
00038 #ifndef UNDER_CE
00039 using std::cerr;
00040 using std::endl;
00041 using std::FILE;
00042 using std::memset;
00043 using std::size_t;
00044 using std::string;
00045 using std::strncpy;
00046 using std::ofstream;
00047 using std::ios;
00048 #endif
00049 
00050 Flex::Flex(const string &n) : U7file(n)
00051 {
00052   IndexFlexFile();
00053 }
00054 
00055 void  Flex::IndexFlexFile(void)
00056 {
00057   FILE  *fp;
00058   fp=U7open(filename.c_str(),"rb");
00059   FileDataSource flex(fp);
00060   flex.read(title, sizeof(title));
00061   magic1 = flex.read4();
00062   count = flex.read4();
00063   magic2 = flex.read4();
00064   if(magic1!=0xffff1a00UL) {
00065     std::fclose (fp);
00066     throw wrong_file_type_exception(filename,"FLEX"); // Not a flex file
00067   }
00068 
00069   for(int i=0;i<9;i++)
00070     padding[i] = flex.read4();
00071 #if DEBUGFLEX
00072   cout << "Title: " << title << endl;
00073   cout << "Count: " << count << endl;
00074 #endif
00075 
00076   // We should already be there.
00077   fseek(fp,128,SEEK_SET);
00078   for(uint32 c=0;c<count;c++)
00079   {
00080     Flex::Reference f;
00081     f.offset = flex.read4();
00082     f.size = flex.read4();
00083 #if DEBUGFLEX
00084     cout << "Item " << c << ": " << f.size << " bytes @ " << f.offset << endl;
00085 #endif
00086     object_list.push_back(f);
00087   }
00088   fclose(fp);
00089 }
00090 
00091 char *  Flex::retrieve(uint32 objnum, size_t &len)
00092 {
00093   FILE  *fp;
00094   char  *buffer;
00095 
00096   if (objnum >= object_list.size())
00097     throw exult_exception("objnum too large in Flex::retrieve()");
00098 
00099   fp = U7open(filename.c_str(), "rb");
00100   fseek(fp, object_list[objnum].offset, SEEK_SET);
00101   len = object_list[objnum].size;
00102   buffer = new char[len];
00103   std::fread(buffer, len, 1, fp);
00104   fclose(fp);
00105   
00106   return buffer;
00107 }
00108 
00109 /*
00110  *  Write out a FLEX header.  Note that this is a STATIC method.
00111  */
00112 
00113 void Flex::write_header
00114   (
00115   DataSource* out,      // File to write to.
00116   const char *title,
00117   int count     // # entries.
00118   )
00119   {
00120   char titlebuf[0x50];    // Use savename for title.
00121   memset(titlebuf, 0, sizeof(titlebuf));
00122   strncpy(titlebuf, title, sizeof(titlebuf) - 1);
00123   out->write(titlebuf, sizeof(titlebuf));
00124   out->write4(0xFFFF1A00);  // Magic number.
00125   out->write4(count);
00126   out->write4(0x000000CC);  // 2nd magic number.
00127   long pos = out->getPos();   // Fill to data (past table at 0x80).
00128   long fill = 0x80 + 8*count - pos;
00129   while (fill--)
00130     out->write1((char) 0);
00131   }
00132 
00133 /*
00134  *  Verify if a file is a FLEX.  Note that this is a STATIC method.
00135  */
00136 
00137 bool Flex::is_flex(DataSource *in)
00138 {
00139   long pos = in->getPos();    // Fill to data (past table at 0x80).
00140   long len = in->getSize() - pos; // Check length.
00141   uint32 magic = 0;
00142   if (len >= 0x80)    // Has to be at least this long.
00143     {
00144     in->seek(0x50);
00145     magic = in->read4();
00146     }
00147   in->seek(pos);
00148 
00149   // Is a flex
00150   if(magic==0xffff1a00UL) return true;
00151 
00152   // Isn't a flex
00153   return false;
00154 }
00155 
00156 bool Flex::is_flex(const char *fname)
00157 {
00158   bool is = false;
00159   std::ifstream in;
00160   U7open (in, fname);
00161   StreamDataSource ds(&in);
00162 
00163   if (in.good()) is = is_flex(&ds);
00164 
00165   in.close();
00166   return is;
00167 }
00168 
00169 /*
00170  *  Start writing out a new Flex file.
00171  */
00172 
00173 Flex_writer::Flex_writer
00174   (
00175   std::ofstream& o,     // Where to write.
00176   const char *title,    // Flex title.
00177   int cnt       // #entries we'll write.
00178   ) : out(&o), count(cnt), index(0)
00179   {
00180           // Write out header.
00181   StreamDataSource ds(out);
00182   Flex::write_header(&ds, title, count);
00183           // Create table.
00184   tptr = table = new uint8[2*count*4];
00185   cur_start = out->tellp(); // Store start of 1st entry.
00186   }
00187 
00188 /*
00189  *  Clean up.
00190  */
00191 
00192 Flex_writer::~Flex_writer
00193   (
00194   )
00195   {
00196   close();
00197   }
00198 
00199 /*
00200  *  Call this when done writing out a section.
00201  */
00202 
00203 void Flex_writer::mark_section_done
00204   (
00205   )
00206   {
00207   long pos = out->tellp();  // Location past end of section.
00208   Write4(tptr, cur_start);  // Store start of section.
00209   Write4(tptr, pos - cur_start);  // Store length.
00210   cur_start = pos;
00211   }
00212 
00213 /*
00214  *  All done.
00215  *
00216  *  Output: False if error.
00217  */
00218 
00219 bool Flex_writer::close
00220   (
00221   )
00222   {
00223   if (!table)
00224     return true;    // Already done.
00225   out->seekp(0x80, ios::beg); // Write table.
00226   out->write(reinterpret_cast<char*>(table), 2*count*4);
00227   out->flush();
00228   bool ok = out->good();
00229   out->close();
00230   delete table;
00231   table = 0;
00232   return ok;
00233   }
00234 
00235 #endif // PENTAGRAM

Generated on Mon Jul 9 14:42:45 2007 for ExultEngine by  doxygen 1.5.1