00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "Core/precomp.h"
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <iostream>
00024 #include <string.h>
00025
00026 #ifndef WIN32
00027 #include <unistd.h>
00028 #else
00029 #include <io.h>
00030 #endif
00031
00032 #include <sys/types.h>
00033 #include <sys/stat.h>
00034 #include <fcntl.h>
00035
00036 #include "datafile_inputprovider.h"
00037 #include "API/Core/System/error.h"
00038
00039
00040 CL_InputSourceProvider *CL_InputSourceProvider::create_datafile_provider(const char *filename)
00041 {
00042 return new CL_InputSourceProvider_Datafile(filename);
00043 }
00044
00045
00046 CL_InputSourceProvider_Datafile::CL_InputSourceProvider_Datafile(const char *_datafile)
00047 {
00048 datafile = _datafile;
00049 }
00050
00051 CL_InputSource *CL_InputSourceProvider_Datafile::open_source(const char *filename)
00052 {
00053 return new CL_InputSource_Datafile(filename, datafile.c_str());
00054 }
00055
00056 CL_InputSourceProvider *CL_InputSourceProvider_Datafile::clone()
00057 {
00058 return new CL_InputSourceProvider_Datafile(datafile.c_str());
00059 }
00060
00061
00062
00063
00064
00065 #ifdef WIN32
00066 #define OPENFLAGS O_RDONLY|O_BINARY
00067 #else
00068 #define OPENFLAGS O_RDONLY
00069 #endif
00070
00071 char datafile_id[]="ClanSoft datafile version 3.0";
00072
00073 CL_InputSource_Datafile::CL_InputSource_Datafile(
00074 const char *_filename, const char *_datafile)
00075 {
00076 filename = _filename;
00077 datafile = _datafile;
00078
00079 datafile_open = 0;
00080 index_open = 0;
00081
00082 open();
00083 }
00084
00085 CL_InputSource_Datafile::CL_InputSource_Datafile(const CL_InputSource_Datafile *source)
00086 {
00087 filename = source->filename;
00088 datafile = source->datafile;
00089
00090 datafile_open = 0;
00091 index_open = 0;
00092
00093 open();
00094 }
00095
00096 CL_InputSource_Datafile::~CL_InputSource_Datafile()
00097 {
00098 close();
00099 }
00100
00101 void CL_InputSource_Datafile::set_system_mode()
00102 {
00103 throw CL_Error("CL_InputSource_Datafile::set_system_mode() is not yet implemented");
00104
00105 }
00106
00107 void CL_InputSource_Datafile::set_big_endian_mode()
00108 {
00109 throw CL_Error("CL_InputSource_Datafile::set_big_endian_mode() is not yet implemented");
00110
00111 }
00112
00113 void CL_InputSource_Datafile::set_little_endian_mode()
00114 {
00115
00116 }
00117
00118 int CL_InputSource_Datafile::read_int32()
00119 {
00120 int svar;
00121
00122 if (gzread(gzfile, &svar, sizeof(int))!=sizeof(int))
00123 {
00124 throw CL_Error("CL_InputSource_Datafile::read_int32() failed");
00125 }
00126
00127 seek_pos+=sizeof(int);
00128 return svar;
00129 }
00130
00131 unsigned int CL_InputSource_Datafile::read_uint32()
00132 {
00133 unsigned int svar;
00134
00135 if (gzread(gzfile, &svar, sizeof(unsigned int))!=sizeof(unsigned int))
00136 {
00137 throw CL_Error("CL_InputSource_Datafile::read_uint32() failed");
00138 }
00139
00140 seek_pos+=sizeof(unsigned int);
00141 return svar;
00142 }
00143
00144 short CL_InputSource_Datafile::read_short16()
00145 {
00146 short svar;
00147
00148 if (gzread(gzfile, &svar, sizeof(short))!=sizeof(short))
00149 {
00150 throw CL_Error("CL_InputSource_Datafile::read_short16() failed");
00151 }
00152
00153 seek_pos+=sizeof(short);
00154 return svar;
00155 }
00156
00157 unsigned short CL_InputSource_Datafile::read_ushort16()
00158 {
00159 unsigned short svar;
00160
00161 if (gzread(gzfile, &svar, sizeof(unsigned short))!=sizeof(unsigned short))
00162 {
00163 throw CL_Error("CL_InputSource_Datafile::read_ushort16() failed");
00164 }
00165
00166 seek_pos+=sizeof(unsigned short);
00167 return svar;
00168 }
00169
00170 char CL_InputSource_Datafile::read_char8()
00171 {
00172 char svar;
00173
00174 if (gzread(gzfile, &svar, sizeof(char))!=sizeof(char))
00175 {
00176 throw CL_Error("CL_InputSource_Datafile::read_char8() failed");
00177 }
00178
00179 seek_pos += sizeof(char);
00180 return svar;
00181 }
00182
00183 unsigned char CL_InputSource_Datafile::read_uchar8()
00184 {
00185 unsigned char svar;
00186
00187 if (gzread(gzfile, &svar, sizeof(unsigned char))!=sizeof(unsigned char))
00188 {
00189 throw CL_Error("CL_InputSource_Datafile::read_uchar8() failed");
00190 }
00191
00192 seek_pos += sizeof(unsigned char);
00193 return svar;
00194 }
00195
00196 float CL_InputSource_Datafile::read_float32()
00197 {
00198 float svar;
00199
00200 if (gzread(gzfile, &svar, sizeof(float))!=sizeof(float))
00201 {
00202 throw CL_Error("CL_InputSource_Datafile::read_float32() failed");
00203 }
00204
00205 seek_pos += sizeof(float);
00206 return svar;
00207 }
00208
00209 int CL_InputSource_Datafile::read(void *addr, int size)
00210 {
00211 int svar = gzread(gzfile, addr, size);
00212 seek_pos += svar;
00213 return svar;
00214 }
00215
00216 void CL_InputSource_Datafile::open()
00217 {
00218 if (datafile_open) return;
00219 datafile_handle = ::open(datafile.c_str(), OPENFLAGS);
00220
00221 if (datafile_handle == -1)
00222 {
00223 std::string err("Could not open datafile ");
00224 err += std::string(datafile);
00225 throw CL_Error(err.c_str());
00226 }
00227
00228 int id_len = strlen(datafile_id);
00229
00230 char *temp = new char[id_len+1];
00231
00232 ::read(datafile_handle, temp, id_len);
00233
00234 temp[id_len] = 0;
00235
00236 if (strcmp(temp, datafile_id) != 0)
00237 {
00238 ::close(datafile_handle);
00239 datafile_handle = -1;
00240
00241 throw CL_Error("Invalid datafile format");
00242
00243
00244 }
00245
00246 delete temp;
00247
00248 datafile_open = 1;
00249 open_index();
00250
00251 }
00252
00253 void CL_InputSource_Datafile::close()
00254 {
00255 if (datafile_open == 0) return;
00256
00257 close_index();
00258 ::close(datafile_handle);
00259
00260 datafile_open = 0;
00261 }
00262
00263 void CL_InputSource_Datafile::open_index()
00264 {
00265 if (index_open != 0) close_index();
00266
00267 lseek(datafile_handle, strlen(datafile_id), SEEK_SET);
00268 int index_pos;
00269 ::read(datafile_handle, &index_pos, sizeof(int));
00270 lseek(datafile_handle, index_pos, SEEK_SET);
00271
00272
00273
00274 int num_indexes = 0;
00275 ::read(datafile_handle, &num_indexes, sizeof(int));
00276 for (int i=0; i<num_indexes; i++)
00277 {
00278 short length;
00279 ::read(datafile_handle, &length,sizeof(short));
00280
00281 char *objname = new char[length];
00282 int objpos;
00283
00284 ::read(datafile_handle, objname, length);
00285 ::read(datafile_handle, &objpos, sizeof(int));
00286 ::read(datafile_handle, &objsize, sizeof(int));
00287
00288
00289
00290 if (strcmp(objname, filename.c_str()) == 0)
00291 {
00292 lseek(datafile_handle, objpos, SEEK_SET);
00293
00294 gzfile = gzdopen(dup(datafile_handle), "rb");
00295 index_open = 1;
00296 seek_pos = 0;
00297
00298 delete[] objname;
00299 return;
00300 }
00301
00302 delete[] objname;
00303 }
00304
00305 index_open = 0;
00306
00307 std::string err("ClanLib: Couldn't find datafile index: ");
00308 err += std::string(filename);
00309 throw CL_Error(err);
00310 }
00311
00312 void CL_InputSource_Datafile::close_index()
00313 {
00314 if (index_open==0) return;
00315
00316 gzclose(gzfile);
00317 index_open=0;
00318 }
00319
00320 CL_InputSource *CL_InputSource_Datafile::clone() const
00321 {
00322 return new CL_InputSource_Datafile(this);
00323 }
00324
00325 int CL_InputSource_Datafile::tell() const
00326 {
00327 return seek_pos;
00328 }
00329
00330 void CL_InputSource_Datafile::seek(int pos, SeekEnum seek_type)
00331 {
00332 if (seek_type == seek_cur)
00333 {
00334 if (pos > 0)
00335 {
00336 char *temp = new char[pos];
00337 read(temp, pos);
00338 delete temp;
00339 }
00340 else if (pos < 0)
00341 {
00342 seek(tell()+pos, seek_set);
00343 }
00344 return;
00345 }
00346 else if (seek_type == seek_set)
00347 {
00348 int cur_pos = tell();
00349 if (pos >= cur_pos)
00350 {
00351 seek(pos - cur_pos, seek_cur);
00352 return;
00353 }
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363 if (seek_type == seek_set && pos == 0)
00364 {
00365 close();
00366 open();
00367 return;
00368 }
00369
00370 std::cout << "ClanLib: seek() in datafiles only supports forward seeks" << std::endl;
00371 cl_assert(false);
00372 }
00373
00374 int CL_InputSource_Datafile::size() const
00375 {
00376 return objsize;
00377 }
00378
00379 std::string CL_InputSource_Datafile::read_string()
00380 {
00381 int size = read_int32();
00382
00383 char *str = new char[size];
00384 read(str, size);
00385
00386 std::string ret = str;
00387 delete[] str;
00388
00389 return ret;
00390 }
00391
00392 void CL_InputSource_Datafile::push_position()
00393 {
00394 CL_Zipped_Position indexpos;
00395
00396 indexpos.gzfile = gzfile;
00397 indexpos.datafile_pos = lseek(datafile_handle, 0, SEEK_CUR);
00398 indexpos.seek_pos = seek_pos;
00399
00400 index_stack.push(indexpos);
00401
00402 index_open=0;
00403 }
00404
00405 void CL_InputSource_Datafile::pop_position()
00406 {
00407 if (index_open != 0) close_index();
00408
00409 index_open = 1;
00410
00411 CL_Zipped_Position pushed_index = index_stack.top();
00412 index_stack.pop();
00413
00414 gzfile = pushed_index.gzfile;
00415 lseek(datafile_handle, pushed_index.datafile_pos, SEEK_SET);
00416 seek_pos = pushed_index.seek_pos;
00417 }