00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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");
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
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
00111
00112
00113 void Flex::write_header
00114 (
00115 DataSource* out,
00116 const char *title,
00117 int count
00118 )
00119 {
00120 char titlebuf[0x50];
00121 memset(titlebuf, 0, sizeof(titlebuf));
00122 strncpy(titlebuf, title, sizeof(titlebuf) - 1);
00123 out->write(titlebuf, sizeof(titlebuf));
00124 out->write4(0xFFFF1A00);
00125 out->write4(count);
00126 out->write4(0x000000CC);
00127 long pos = out->getPos();
00128 long fill = 0x80 + 8*count - pos;
00129 while (fill--)
00130 out->write1((char) 0);
00131 }
00132
00133
00134
00135
00136
00137 bool Flex::is_flex(DataSource *in)
00138 {
00139 long pos = in->getPos();
00140 long len = in->getSize() - pos;
00141 uint32 magic = 0;
00142 if (len >= 0x80)
00143 {
00144 in->seek(0x50);
00145 magic = in->read4();
00146 }
00147 in->seek(pos);
00148
00149
00150 if(magic==0xffff1a00UL) return true;
00151
00152
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
00171
00172
00173 Flex_writer::Flex_writer
00174 (
00175 std::ofstream& o,
00176 const char *title,
00177 int cnt
00178 ) : out(&o), count(cnt), index(0)
00179 {
00180
00181 StreamDataSource ds(out);
00182 Flex::write_header(&ds, title, count);
00183
00184 tptr = table = new uint8[2*count*4];
00185 cur_start = out->tellp();
00186 }
00187
00188
00189
00190
00191
00192 Flex_writer::~Flex_writer
00193 (
00194 )
00195 {
00196 close();
00197 }
00198
00199
00200
00201
00202
00203 void Flex_writer::mark_section_done
00204 (
00205 )
00206 {
00207 long pos = out->tellp();
00208 Write4(tptr, cur_start);
00209 Write4(tptr, pos - cur_start);
00210 cur_start = pos;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219 bool Flex_writer::close
00220 (
00221 )
00222 {
00223 if (!table)
00224 return true;
00225 out->seekp(0x80, ios::beg);
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