factored out the EFFv2 saving into EFFImporter
[gemrb.git] / gemrb / core / System / CachedFileStream.cpp
blobf9ae24892b667ded087560546cfba3ccb5d15171
1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "System/CachedFileStream.h"
23 #include "win32def.h"
25 #include "Interface.h"
27 CachedFileStream::CachedFileStream(const char* stream, bool autoFree)
29 ExtractFileFromPath( filename, stream );
30 PathJoin( originalfile, core->CachePath, filename, NULL );
32 str = _fopen( originalfile, "rb" );
33 if (str == NULL) { // File was not found in cache
34 if (core->GameOnCD) {
35 _FILE* src = _fopen( stream, "rb" );
36 #ifdef _DEBUG
37 core->CachedFileStreamPtrCount++;
38 #endif
39 _FILE* dest = _fopen( originalfile, "wb" );
40 #ifdef _DEBUG
41 core->CachedFileStreamPtrCount++;
42 #endif
43 void* buff = malloc( 1024 * 1000 );
44 do {
45 size_t len = _fread( buff, 1, 1024 * 1000, src );
46 size_t c = _fwrite( buff, 1, len, dest );
47 if (c != len) {
48 printf("CachedFileStream failed to write to cached file '%s' (from '%s')\n", originalfile, stream);
49 abort();
51 } while (!_feof( src ));
52 free( buff );
53 _fclose( src );
54 #ifdef _DEBUG
55 core->CachedFileStreamPtrCount--;
56 #endif
57 _fclose( dest );
58 #ifdef _DEBUG
59 core->CachedFileStreamPtrCount--;
60 #endif
61 } else { // Don't cache files already on hdd
62 strncpy(originalfile, stream, _MAX_PATH);
64 str = _fopen( originalfile, "rb" );
66 #ifdef _DEBUG
67 core->CachedFileStreamPtrCount++;
68 #endif
69 startpos = 0;
70 _fseek( str, 0, SEEK_END );
71 size = _ftell( str );
72 _fseek( str, 0, SEEK_SET );
73 Pos = 0;
74 this->autoFree = autoFree;
77 CachedFileStream::CachedFileStream(CachedFileStream* cfs, int startpos,
78 int size, bool autoFree)
80 this->size = size;
81 this->startpos = startpos;
82 this->autoFree = autoFree;
83 char cpath[_MAX_PATH];
84 PathJoin( cpath, core->CachePath, cfs->filename, NULL );
85 str = _fopen( cpath, "rb" );
86 if (str == NULL) {
87 str = _fopen( cfs->originalfile, "rb" );
88 if (str == NULL) {
89 printf( "Can't open stream (maybe leaking?)\n" );
90 return;
92 strncpy( originalfile, cfs->originalfile, sizeof(originalfile) );
93 strncpy( filename, cfs->filename, sizeof(filename) );
94 } else {
95 strncpy( originalfile, cpath, sizeof(originalfile) );
96 strncpy( filename, cfs->filename, sizeof(filename) );
98 #ifdef _DEBUG
99 core->CachedFileStreamPtrCount++;
100 #endif
101 _fseek( str, startpos, SEEK_SET );
104 Pos = 0;
107 CachedFileStream::~CachedFileStream(void)
109 if (autoFree && str) {
110 #ifdef _DEBUG
111 core->CachedFileStreamPtrCount--;
112 #endif
113 _fclose( str );
115 str = NULL;
116 //autoFree = false; //File stream destructor hack
119 int CachedFileStream::Read(void* dest, unsigned int length)
121 //we don't allow partial reads anyway, so it isn't a problem that
122 //i don't adjust length here (partial reads are evil)
123 if (Pos+length>size ) {
124 return GEM_ERROR;
127 unsigned int c = (unsigned int) _fread( dest, 1, length, str );
128 if (c != length) {
129 return GEM_ERROR;
131 if (Encrypted) {
132 ReadDecrypted( dest, c );
134 Pos += c;
135 return c;
138 int CachedFileStream::Write(const void* src, unsigned int length)
140 // do encryption here if needed
142 unsigned int c = (unsigned int) _fwrite( src, 1, length, str );
143 if (c != length) {
144 return GEM_ERROR;
146 Pos += c;
147 //this is needed only if you want to Seek in a written file
148 if (Pos>size) {
149 size = Pos;
151 return c;
154 int CachedFileStream::Seek(int newpos, int type)
156 switch (type) {
157 case GEM_CURRENT_POS:
158 _fseek( str, newpos, SEEK_CUR );
159 Pos += newpos;
160 break;
162 case GEM_STREAM_START:
163 _fseek( str, startpos + newpos, SEEK_SET );
164 Pos = newpos;
165 break;
167 default:
168 return GEM_ERROR;
170 //we went past the buffer
171 if (Pos>size) {
172 printf("[Streams]: Invalid seek position: %ld (limit: %ld)\n",Pos, size);
173 return GEM_ERROR;
175 return GEM_OK;
178 /** No descriptions */
179 int CachedFileStream::ReadLine(void* buf, unsigned int maxlen)
181 if (!maxlen) {
182 return 0;
184 unsigned char * p = ( unsigned char * ) buf;
185 if (_feof( str )) {
186 p[0]=0;
187 return -1;
189 if (Pos >= size) {
190 p[0]=0;
191 return -1;
193 unsigned int i = 0;
194 while (i < ( maxlen - 1 )) {
195 int ch = _fgetc( str );
196 if (Pos == size)
197 break;
198 if (Encrypted)
199 ch ^= GEM_ENCRYPTION_KEY[Pos & 63];
200 Pos++;
201 if (( ( char ) ch ) == '\n')
202 break;
203 if (( ( char ) ch ) == '\t')
204 ch = ' ';
205 if (( ( char ) ch ) != '\r')
206 p[i++] = ch;
207 //Warning:this feof implementation reads forward one byte
208 if (_feof( str ))
209 break;
211 p[i] = 0;
212 return i;