Subversion Repositories spk

Rev

Rev 212 | Rev 223 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
#include "File_IO.h"
2
 
3
#ifdef _WIN32
4
#include <windows.h>
5
#endif
6
 
7
#include <locale>
8
 
9
#include "DirIO.h"
10
#include "File.h"
51 cycrow 11
#include "Logging/Log.h"
81 cycrow 12
#include "Packages.h"
1 cycrow 13
 
52 cycrow 14
CFileIO::CFileIO () : m_lSize(0), m_bBinary(true), m_bAutoDelete(false), m_bSeekP(false)
1 cycrow 15
{
16
}
17
 
196 cycrow 18
CFileIO::CFileIO(const Utils::WString &sFilename, bool bBinary) : m_lSize(0), m_bBinary(bBinary), m_bAutoDelete(false)
1 cycrow 19
{
82 cycrow 20
	open(sFilename, bBinary);
1 cycrow 21
}
121 cycrow 22
 
196 cycrow 23
CFileIO::CFileIO(const Utils::WString &filename) : m_lSize(0), m_bBinary(true), m_bAutoDelete(false), m_bSeekP(false)
52 cycrow 24
{
185 cycrow 25
	open(filename, true);
52 cycrow 26
}
1 cycrow 27
 
52 cycrow 28
CFileIO::CFileIO(C_File *file) : m_lSize(0), m_bBinary(true), m_bAutoDelete(false), m_bSeekP(false)
1 cycrow 29
{
129 cycrow 30
	open(file->filePointer(), true);
1 cycrow 31
}
32
 
33
CFileIO::~CFileIO()
34
{
52 cycrow 35
	if ( this->isOpened() ) m_fId.close();
36
	if ( m_bAutoDelete ) this->remove();
1 cycrow 37
}
38
 
52 cycrow 39
void CFileIO::setAutoDelete(bool bDelete)
40
{
41
	m_bAutoDelete = true;
42
}
43
 
196 cycrow 44
bool CFileIO::open(const Utils::WString& sFilename, bool bBinary)
1 cycrow 45
{
82 cycrow 46
	m_bBinary = bBinary;
160 cycrow 47
	_sFilename = sFilename.asFilename();
1 cycrow 48
 
82 cycrow 49
	// check if there are any directories, and split the file and directory parts
196 cycrow 50
	if ( _sFilename.contains('/') ) {
197 cycrow 51
		_sDirIO.setDir(_sFilename.tokens(L"/", 1, -2));
196 cycrow 52
		_sFile = _sFilename.token(L"/", -1);
1 cycrow 53
	}
54
	else
160 cycrow 55
		_sFile = _sFilename;
1 cycrow 56
 
160 cycrow 57
	_sFile.removeFirstSpace();
58
	_sFile.removeChar(13);
95 cycrow 59
 
160 cycrow 60
	_updateFilename();
61
 
51 cycrow 62
	this->_readFileSize();
1 cycrow 63
	return true;
64
}
119 cycrow 65
 
52 cycrow 66
unsigned char *CFileIO::read(size_t iAmount)
67
{
68
	if ( !this->isOpened() ) startRead();
69
	if ( !this->isOpened() ) return NULL;
70
 
71
	if ( iAmount > m_lSize ) iAmount = m_lSize;
72
 
73
	unsigned char *data;
74
	try {
75
		data = new unsigned char[iAmount + 1];
76
	}
77
	catch (std::exception &e) {
78
		CLog::logf(CLog::Log_IO, 2, "ERROR: CFileIO::read(size_t) unable to malloc data, %d (%s)", iAmount + 1, e.what());
79
		return NULL;
80
	}
81
 
82
	if ( !read(data, iAmount, true) ) {
160 cycrow 83
		CLog::logf(CLog::Log_IO, 2, "ERROR: CFileIO::read(size_t) unable to read data from file, %s/%d", _sFilename.c_str(), iAmount);
196 cycrow 84
		delete[] data;
52 cycrow 85
		return NULL;
86
	}
87
 
88
	return data;
89
}
90
 
91
unsigned char *CFileIO::readAll(size_t *pSize)
92
{
93
	if ( pSize ) (*pSize) = 0;
94
	if ( !this->isOpened() ) startRead();
95
	if ( !this->isOpened() ) return NULL;
96
 
97
	unsigned char *data;
98
	try {
99
		data = new unsigned char[m_lSize + 1];
100
	}
101
	catch (std::exception &e) {
102
		CLog::logf(CLog::Log_IO, 2, "ERROR: CFileIO::readAll() unable to malloc data, %d (%s)", m_lSize + 1, e.what());
103
		return NULL;
104
	}
105
 
106
	if ( !read(data, m_lSize, true) ) {
160 cycrow 107
		CLog::logf(CLog::Log_IO, 2, "ERROR: CFileIO::readAll() unable to read data from file, %s/%d", _sFilename.c_str(), m_lSize);
196 cycrow 108
		delete[] data;
52 cycrow 109
		return NULL;
110
	}
111
 
112
	if ( pSize ) (*pSize) = m_lSize;
113
	return data;
114
}
115
 
197 cycrow 116
bool CFileIO::read(wchar_t* buf, size_t iSize, bool bEndChar)
52 cycrow 117
{
197 cycrow 118
	if (!this->isOpened()) startRead();
119
	if (!this->isOpened()) return false;
52 cycrow 120
 
197 cycrow 121
	if (iSize > m_lSize) iSize = m_lSize;
52 cycrow 122
	try {
197 cycrow 123
		m_fId.read((char*)buf, iSize);
52 cycrow 124
	}
197 cycrow 125
	catch (std::exception& e) {
160 cycrow 126
		CLog::logf(CLog::Log_IO, 3, "ERROR: CFileIO::read() unable to read from file: %s (%s)", _sFilename.c_str(), e.what());
52 cycrow 127
		return false;
128
	}
129
 
197 cycrow 130
	if (bEndChar) buf[iSize] = '\0';
52 cycrow 131
 
132
	return !m_fId.bad();
133
}
197 cycrow 134
bool CFileIO::read(unsigned char* buf, size_t iSize, bool bEndChar)
135
{
136
	if (!this->isOpened()) startRead();
137
	if (!this->isOpened()) return false;
52 cycrow 138
 
197 cycrow 139
	if (iSize > m_lSize) iSize = m_lSize;
140
	try {
141
		m_fId.read((char*)buf, iSize);
142
	}
143
	catch (std::exception& e) {
144
		CLog::logf(CLog::Log_IO, 3, "ERROR: CFileIO::read() unable to read from file: %s (%s)", _sFilename.c_str(), e.what());
145
		return false;
146
	}
147
 
148
	if (bEndChar) buf[iSize] = '\0';
149
 
150
	return !m_fId.bad();
151
}
152
 
1 cycrow 153
bool CFileIO::WritePartFile ( size_t *offsets, size_t numOffset )
154
{
51 cycrow 155
	if ( NoFile() )	return false;
1 cycrow 156
 
160 cycrow 157
	std::fstream File(_sFilename, _in());
51 cycrow 158
	if ( !File.is_open() ) return false;
1 cycrow 159
 
160
	// first find file size
51 cycrow 161
	File.seekg(0, std::ios::end);
121 cycrow 162
	size_t fullsize = static_cast<size_t>(File.tellg()), size = fullsize;
51 cycrow 163
	File.seekg(0, std::ios::beg);
1 cycrow 164
 
81 cycrow 165
	std::fstream writeFile(CPackages::tempDirectory() + "/temp.tmp", _out());
51 cycrow 166
	if ( !File.is_open() ) {
167
		File.close();
1 cycrow 168
		return false;
169
	}
170
 
171
	size_t off = 0;
172
	size_t startPos = 0;
173
	size_t remainingSize = fullsize;
51 cycrow 174
 
175
	while ( off < numOffset ) {
121 cycrow 176
		startPos = static_cast<size_t>(File.tellg());
1 cycrow 177
		size_t offset = offsets[off++];
178
		size_t size = offset - startPos;
51 cycrow 179
		try {
180
			char *data = new char[size];
181
			File.read(data, size);
182
			writeFile.write(data, size);
196 cycrow 183
			delete []data;
51 cycrow 184
		}
185
		catch(std::exception &e) {
160 cycrow 186
			CLog::logf(CLog::Log_IO, 2, "CFileIO::WritePartFilea() unable to read data from file: %s (%s)", _sFilename.c_str(), e.what());
51 cycrow 187
			return false;
188
		}
189
 
1 cycrow 190
		size_t datasize = offsets[off++];
51 cycrow 191
		File.seekg(datasize, std::ios::beg);
1 cycrow 192
		remainingSize = fullsize - offset - datasize;
193
	}
194
 
51 cycrow 195
	if ( remainingSize ) {
1 cycrow 196
		char data[1000000];
197
		size_t amountLeft = 1000000;
198
		while ( remainingSize )
199
		{
51 cycrow 200
			if ( amountLeft > remainingSize ) amountLeft = remainingSize;
201
			try {
202
				File.read(data, amountLeft);
203
				writeFile.write(data, amountLeft);
204
			}
205
			catch(std::exception &e) {
160 cycrow 206
				CLog::logf(CLog::Log_IO, 2, "CFileIO::WritePartFilea() unable to read data from file: %s (%s)", _sFilename.c_str(), e.what());
51 cycrow 207
				return false;
208
			}
1 cycrow 209
 
210
			remainingSize -= amountLeft;
211
			amountLeft = 1000000;
212
		}
213
	}
214
 
51 cycrow 215
	File.close();
216
	writeFile.close();
1 cycrow 217
 
218
	// now copy to original file
197 cycrow 219
	CFileIO::Remove(_sFilename);
220
	return CFileIO::Rename(CPackages::tempDirectory() + L"/temp.tmp", _sFilename);
1 cycrow 221
}
222
 
223
 
196 cycrow 224
void CFileIO::setDir(const Utils::WString &dir)
1 cycrow 225
{
160 cycrow 226
	if ( _sFile.empty() )	_sDirIO.setDir(dir);
227
	else					open(dir + "/" + _sFile, m_bBinary);
1 cycrow 228
}
229
 
51 cycrow 230
void CFileIO::_readFileSize ()
1 cycrow 231
{
51 cycrow 232
	m_lSize = 0;
233
 
160 cycrow 234
	std::fstream file(_sFilename, (m_bBinary) ? (std::ios::in | std::ios::binary) : (std::ios::in));
51 cycrow 235
	if ( !file.is_open() ) return;
236
 
237
	file.seekg(0, std::ios::end);
121 cycrow 238
	m_lSize = static_cast<size_t>(file.tellg());
51 cycrow 239
	file.close();
1 cycrow 240
}
241
 
242
bool CFileIO::WipeFile()
243
{
51 cycrow 244
	if ( NoFile() )	return false;
245
	std::ofstream file;
160 cycrow 246
	file.open(_sFilename, std::ios::out | std::ios::trunc);
51 cycrow 247
	bool bDone = file.is_open();
248
	file.close();
1 cycrow 249
 
51 cycrow 250
	return bDone;
1 cycrow 251
}
52 cycrow 252
 
253
 
1 cycrow 254
int CFileIO::TruncateFile ( size_t offset, size_t datasize )
255
{
52 cycrow 256
	if ( NoFile() ) return FILEERR_NOFILE;
1 cycrow 257
 
52 cycrow 258
	if ( !this->startRead() ) return FILEERR_NOOPEN;
259
	if ( (offset + datasize) > m_lSize ) return FILEERR_TOSMALL;
1 cycrow 260
 
81 cycrow 261
	CFileIO File(CPackages::tempDirectory() + "/temp.tmp");
52 cycrow 262
	if ( !File.startWrite() ) return FILEERR_NOWRITE;
263
	File.setAutoDelete(true);
1 cycrow 264
 
52 cycrow 265
	if ( !File.write(*this, offset) ) return false;
1 cycrow 266
 
267
	// next fseek after and write
52 cycrow 268
	this->seek(datasize);
269
	size_t size = m_lSize - offset - datasize;
42 cycrow 270
	if ( size > 0 ) {
52 cycrow 271
		File.write(*this, size);
42 cycrow 272
	}
1 cycrow 273
 
52 cycrow 274
	File.close();
275
	this->close();
276
	File.setAutoDelete(false);
1 cycrow 277
 
278
	// now copy to original file
197 cycrow 279
	if (CFileIO::Remove(_sFilename)) {
280
		if (CFileIO::Rename(CPackages::tempDirectory() + L"/temp.tmp", _sFilename))
281
		{
282
			size_t oldSize = m_lSize;
283
			size_t checkFileSize = m_lSize - datasize;
284
			this->_readFileSize();
285
			if (checkFileSize != m_lSize) {
286
				CLog::log(CLog::Log_IO, 3, Utils::WString(L"WARNING: CFileIO::TruncateFile, file size mismatch, ") + (long)checkFileSize + L" => " + (long)m_lSize);
287
			}
288
			return FILEERR_NONE;
84 cycrow 289
		}
197 cycrow 290
		return FILEERR_NOWRITE;
58 cycrow 291
	}
1 cycrow 292
 
58 cycrow 293
	return FILEERR_NOWRITE;
1 cycrow 294
}
295
 
52 cycrow 296
int CFileIO::_in() const
51 cycrow 297
{
298
	if ( m_bBinary ) return std::ios::in | std::ios::binary;
299
	return std::ios::in;
300
}
301
 
52 cycrow 302
int CFileIO::_out() const
51 cycrow 303
{
304
	if ( m_bBinary ) return std::ios::out | std::ios::binary;
305
	return std::ios::out;
306
}
52 cycrow 307
int CFileIO::_inout() const
308
{
309
	if ( m_bBinary ) return std::ios::in | std::ios::out | std::ios::binary;
310
	return std::ios::in | std::ios::out;
311
}
51 cycrow 312
 
52 cycrow 313
int CFileIO::_append() const
51 cycrow 314
{
315
	if ( m_bBinary ) return std::ios::out | std::ios::binary | std::ios::app;
316
	return std::ios::out | std::ios::app;
317
}
318
 
1 cycrow 319
char *CFileIO::ReadToData ( size_t *size )
320
{
321
	*size = 0;
322
 
51 cycrow 323
	if ( NoFile() ) return NULL;
324
	if ( !m_lSize )	this->_readFileSize();
325
	if ( !m_lSize ) return NULL;
1 cycrow 326
 
160 cycrow 327
	std::fstream file(_sFilename, _in());
51 cycrow 328
	if ( !file.is_open() ) return NULL;
1 cycrow 329
 
51 cycrow 330
	char *data;
331
	try {
332
		data = new char[m_lSize + 1];
333
	}
334
	catch (std::exception &e) {
335
		CLog::logf(CLog::Log_IO, 2, "CFileIO::ReadToData() unable to malloc storage, %d (%s)", m_lSize + 1, e.what());
336
		file.close();
1 cycrow 337
		return NULL;
51 cycrow 338
	}
1 cycrow 339
 
51 cycrow 340
	try {
341
		file.read((char *)data, m_lSize);
342
	}
343
	catch (std::exception &e) {
344
		CLog::logf(CLog::Log_IO, 2, "CFileIO::ReadToData() unable to read data from file (%s)", e.what());
345
		file.close();
1 cycrow 346
		return NULL;
347
	}
348
 
349
	*size = m_lSize;
51 cycrow 350
	file.close();
1 cycrow 351
 
352
	return data;
353
}
354
 
355
bool CFileIO::WriteData ( const char *data, size_t size )
356
{
357
	if ( NoFile() )
358
		return false;
359
 
200 cycrow 360
	std::fstream File(_fileData(), _out());
51 cycrow 361
	if ( !File.is_open() ) return false;
1 cycrow 362
 
51 cycrow 363
	bool ret = true;
364
	try {
365
		File.write(data, size);
366
	}
367
	catch (std::exception &e) {
160 cycrow 368
		CLog::logf(CLog::Log_IO, 2, "CFileIO::ReadToData() unable to read data from file: %s (%s)", _sFilename.c_str(), e.what());
51 cycrow 369
		ret = false;
370
	}
1 cycrow 371
 
51 cycrow 372
	File.close();
1 cycrow 373
 
51 cycrow 374
	if ( ret ) this->_readFileSize();
375
	return ret;
1 cycrow 376
}
377
 
82 cycrow 378
bool CFileIO::writeString ( const Utils::String &data )
1 cycrow 379
{
82 cycrow 380
	return WriteData ( data.c_str(), data.length() );
1 cycrow 381
}
382
 
196 cycrow 383
bool CFileIO::Exists(const Utils::WString &filename)
1 cycrow 384
{
197 cycrow 385
	std::wfstream File(filename, std::ios::in | std::ios::binary);
52 cycrow 386
	bool bRet = File.good();
387
	File.close();
388
	return bRet;
389
}
390
 
391
bool CFileIO::ExistsOld () const
392
{
393
	return this->exists();
394
}
395
bool CFileIO::exists () const
396
{
397
	if ( this->isOpened() ) return true;
160 cycrow 398
	std::fstream File(_sFilename, _in());
51 cycrow 399
	bool bRet = File.good();
400
	File.close();
401
	return bRet;
1 cycrow 402
}
403
 
52 cycrow 404
bool CFileIO::startRead()
1 cycrow 405
{
52 cycrow 406
	return _start(_in(), false);
407
}
408
 
409
bool CFileIO::startWrite()
410
{
411
	return _start(_out(), true);
412
}
413
 
414
bool CFileIO::startModify()
415
{
416
	return _start(_inout(), true);
417
}
418
 
419
bool CFileIO::startAppend()
420
{
421
	return _start(_append(), false);
422
}
423
 
424
bool CFileIO::_start(int iFlags, bool bSeekP)
425
{
160 cycrow 426
	if ( !_sFilename.empty() ) {
52 cycrow 427
		if ( this->isOpened() ) this->close();
1 cycrow 428
 
160 cycrow 429
		m_fId.open(_sFilename, iFlags);
1 cycrow 430
	}
52 cycrow 431
	m_bSeekP = bSeekP;
432
	return m_fId.is_open();
1 cycrow 433
}
434
 
166 cycrow 435
std::vector<Utils::String>* CFileIO::readLines() const
82 cycrow 436
{
166 cycrow 437
	if (_sFilename.empty()) return 0;
82 cycrow 438
 
166 cycrow 439
	std::vector<Utils::String>* file = new std::vector<Utils::String>;
84 cycrow 440
	Utils::String line;
82 cycrow 441
	file->clear();
166 cycrow 442
	std::ifstream infile(_sFilename.c_str(), std::ios_base::in);
82 cycrow 443
	while (getline(infile, line, '\n')) {
444
		file->push_back(Utils::String(line).removeChar((char)0));
445
	}
446
 
447
	infile.close();
448
 
449
	return file;
450
}
170 cycrow 451
size_t CFileIO::readLines(std::vector<Utils::String>& to) const
166 cycrow 452
{
453
	if (_sFilename.empty()) return 0;
83 cycrow 454
 
166 cycrow 455
	Utils::String line;
456
	std::ifstream infile(_sFilename.c_str(), std::ios_base::in);
457
	while (getline(infile, line, '\n')) {
458
		to.push_back(Utils::String(line).removeChar((char)0));
459
	}
1 cycrow 460
 
166 cycrow 461
	infile.close();
462
 
463
	return to.size();
464
}
465
 
197 cycrow 466
size_t CFileIO::readLines(std::vector<Utils::WString>& to) const
467
{
468
	if (_sFilename.empty()) return 0;
469
 
470
	std::wstring line;
471
	std::wifstream infile(_sFilename.c_str(), std::ios_base::in);
472
	while (getline(infile, line, L'\n')) {
473
		to.push_back(Utils::WString(line).remove((char)0));
474
	}
475
 
476
	infile.close();
477
 
478
	return to.size();
479
}
480
 
211 cycrow 481
size_t CFileIO::readLines(Utils::WStringList& to) const
111 cycrow 482
{
211 cycrow 483
	if (_sFilename.empty()) return 0;
111 cycrow 484
 
211 cycrow 485
	std::wstring line;
486
	std::wifstream infile(_sFilename.c_str(), std::ios_base::in);
487
	while (getline(infile, line, L'\n')) {
488
		to.pushBack(Utils::WString(line).remove((char)0));
111 cycrow 489
	}
490
 
491
	infile.close();
492
 
211 cycrow 493
	return to.size();
111 cycrow 494
}
495
 
52 cycrow 496
bool CFileIO::put(const unsigned char c)
1 cycrow 497
{
52 cycrow 498
	if ( !this->isOpened() ) return false;
499
 
500
	m_fId.put(c);
501
	return !m_fId.bad();
1 cycrow 502
}
503
 
123 cycrow 504
bool CFileIO::writeSize(size_t iSize)
1 cycrow 505
{
52 cycrow 506
	if ( !this->isOpened() ) return false;
507
	if ( !this->put(static_cast<unsigned char>(iSize >> 24)) ) return false;
508
	if ( !this->put(static_cast<unsigned char>(iSize >> 16)) ) return false;
509
	if ( !this->put(static_cast<unsigned char>(iSize >> 8)) ) return false;
510
	if ( !this->put(static_cast<unsigned char>(iSize)) ) return false;
511
	m_lSize += 4;
512
	return true;
1 cycrow 513
}
514
 
52 cycrow 515
bool CFileIO::write(CFileIO &file, size_t iSize)
1 cycrow 516
{
52 cycrow 517
	if ( !this->isOpened() ) startWrite();
518
	if ( !this->isOpened() ) return false;
519
 
520
	int iMaxSize = 1000000;
521
 
522
	unsigned char *data;
523
	try {
524
		data = new unsigned char[iMaxSize + 1];
1 cycrow 525
	}
52 cycrow 526
	catch (std::exception &e) {
527
		CLog::logf(CLog::Log_IO, 2, "ERROR: CFileIO::write(CFileIO, size_t) unable to malloc data, %d (%s)", iMaxSize + 1, e.what());
528
		return false;
529
	}
1 cycrow 530
 
52 cycrow 531
	int iSizeLeft = iSize;
532
	bool bSuccess = true;
533
	while ( iSizeLeft > 0 ) {
534
		int iDoSize = iMaxSize;
535
		if ( iDoSize > iSizeLeft ) iDoSize = iSizeLeft;
1 cycrow 536
 
52 cycrow 537
		if ( !file.read(data, iDoSize) ) bSuccess = false;
538
		if ( bSuccess && !this->write(data, iDoSize) ) bSuccess = false;
539
		if ( !bSuccess ) break;
540
		iSizeLeft -= iDoSize;
541
	}
1 cycrow 542
 
52 cycrow 543
	delete data;
1 cycrow 544
 
52 cycrow 545
	return bSuccess;
1 cycrow 546
}
547
 
123 cycrow 548
bool CFileIO::write(const char *buf, size_t iSize)
52 cycrow 549
{
550
	if ( !this->isOpened() ) startWrite();
551
	if ( !this->isOpened() ) return false;
552
	try {
197 cycrow 553
		m_fId.write((char*)buf, iSize);
52 cycrow 554
	}
555
	catch (std::exception &e) {
160 cycrow 556
		CLog::logf(CLog::Log_IO, 2, "CFileIO::write() unable to write to file: %s (%s)", _sFilename.c_str(), e.what());
52 cycrow 557
		return false;
558
	}
559
	m_lSize += iSize;
560
	return !m_fId.bad();
561
}
123 cycrow 562
bool CFileIO::write(const unsigned char *buf, size_t iSize)
52 cycrow 563
{
564
	return this->write((char *)buf, iSize);
565
}
566
 
567
bool CFileIO::write(const unsigned char *buf, ...)
568
{
569
	va_list args;
570
	va_start(args, buf);
571
	bool ret = this->_write((char *)buf, args);
572
	va_end(args);
573
	return ret;
574
}
197 cycrow 575
bool CFileIO::_write(const char* buf, va_list args)
52 cycrow 576
{
197 cycrow 577
	if (!this->isOpened()) return false;
52 cycrow 578
 
579
	char buffer[10000];
580
 
197 cycrow 581
	vsprintf(buffer, buf, args);
52 cycrow 582
	try {
583
		int iLen = strlen(buffer);
197 cycrow 584
		m_fId.write((char*)buffer, iLen);
52 cycrow 585
		m_lSize += iLen;
586
	}
197 cycrow 587
	catch (std::exception& e) {
160 cycrow 588
		CLog::logf(CLog::Log_IO, 2, "CFileIO::write() unable to write to file: %s (%s)", _sFilename.c_str(), e.what());
52 cycrow 589
		return false;
590
	}
591
	return !m_fId.bad();
592
}
197 cycrow 593
bool CFileIO::_write(const wchar_t* buf, va_list args)
594
{
595
	if (!this->isOpened()) return false;
52 cycrow 596
 
197 cycrow 597
	wchar_t buffer[10000];
598
 
599
#ifdef _WIN32
600
	vswprintf_s(buffer, 10000, buf, args);
601
#else
602
	vswprintf(buffer, buf, args);
603
#endif
604
	try {
605
		size_t iLen = wcslen(buffer);
606
		m_fId.write((char*)buffer, iLen);
607
		m_lSize += iLen;
608
	}
609
	catch (std::exception& e) {
610
		CLog::logf(CLog::Log_IO, 2, "CFileIO::write() unable to write to file: %ls (%s)", _sFilename.c_str(), e.what());
611
		return false;
612
	}
613
	return !m_fId.bad();
614
}
615
 
52 cycrow 616
bool CFileIO::write(const char *buf, ...)
617
{
618
	va_list args;
619
	va_start(args, buf);
620
	bool ret = this->_write((char *)buf, args);
621
	va_end(args);
622
	return ret;
623
}
624
 
625
void CFileIO::_seek(int iPos, int iFrom)
626
{
627
	if ( !this->isOpened() ) {
628
		if ( !this->startRead() ) return;
629
	}
630
	if ( m_bSeekP ) m_fId.seekp(iPos, iFrom);
631
	else m_fId.seekg(iPos, iFrom);
632
}
633
 
123 cycrow 634
void CFileIO::seek(size_t iPos)
52 cycrow 635
{
636
	_seek(iPos, std::ios::cur);
637
}
638
 
123 cycrow 639
void CFileIO::seekEnd(size_t iPos)
52 cycrow 640
{
53 cycrow 641
	_seek(iPos, std::ios::end);
52 cycrow 642
}
643
 
123 cycrow 644
void CFileIO::seekStart(size_t iPos)
52 cycrow 645
{
646
	_seek(iPos, std::ios::beg);
647
}
648
 
649
std::fstream &CFileIO::stream()
650
{
651
	return m_fId;
652
}
653
 
654
bool CFileIO::isOpened() const
655
{
656
	if ( m_fId.is_open() )
657
		return true;
658
	return false;
659
}
660
 
661
void CFileIO::close()
662
{
663
	if ( this->isOpened() ) m_fId.close();
84 cycrow 664
	this->_readFileSize();
52 cycrow 665
}
666
 
56 cycrow 667
int CFileIO::readSize()
1 cycrow 668
{
56 cycrow 669
	unsigned char size[4];
670
	if ( this->read(size, 4) ) return (size[0] << 24) + (size[1] << 16) + (size[2] << 8) + size[3];
671
	return 0;
672
}
673
 
674
bool CFileIO::atEnd() const
675
{
52 cycrow 676
	if ( !this->isOpened() ) return true;
51 cycrow 677
	if ( m_fId.eof() )		 return true;
1 cycrow 678
	return false;
679
}
680
 
82 cycrow 681
bool CFileIO::appendFile ( const Utils::String &filename )
682
{
683
	std::fstream fromFile(filename, _in());
684
	if ( !fromFile.is_open() ) return false;
685
 
160 cycrow 686
	std::fstream toFile(_sFilename, _append());
82 cycrow 687
	if ( !toFile.is_open() ) {
688
		fromFile.close();
689
		return false;
690
	}
691
 
692
	// move to the end of the file
693
	toFile.seekg(0, std::ios::end);
694
 
695
	// get size of file
696
	fromFile.seekg(0, std::ios::end);
121 cycrow 697
	size_t size = static_cast<size_t>(fromFile.tellg());
82 cycrow 698
	fromFile.seekg(0, std::ios::beg);
699
 
700
	char data[500000];
701
	while ( size > 0 )
702
	{
703
		size_t read = 500000;
704
		if ( read > size )
705
			read = size;
706
 
707
		size -= read;
708
 
709
		fromFile.read(data, read);
710
		toFile.write(data, read);
711
	}
712
 
713
	fromFile.close();
714
	toFile.close();
715
	return true;
716
}
717
 
1 cycrow 718
 
719
bool CFileIO::AppendData ( const char *d, size_t size )
720
{
160 cycrow 721
	std::ofstream File(_sFilename, _append());
51 cycrow 722
	if ( !File.is_open() ) return false;
1 cycrow 723
 
724
	// move to the end of the file
58 cycrow 725
	//File.seekg(0, std::ios::end);
1 cycrow 726
 
727
	char *pos = (char *)d;
51 cycrow 728
	while ( size > 0 ) {
1 cycrow 729
		size_t read = 500000;
51 cycrow 730
		if ( read > size ) read = size;
1 cycrow 731
 
732
		size -= read;
733
 
51 cycrow 734
		try {
735
			File.write(pos, read);
736
		} 
737
		catch(std::exception &e) {
160 cycrow 738
			CLog::logf(CLog::Log_IO, 2, "CFileIO::AppendData() unable to write data to file: %s (%s)", _sFilename.c_str(), e.what());
51 cycrow 739
			File.close();
740
			return false;
741
		}
1 cycrow 742
		pos += read;
743
	}
744
 
51 cycrow 745
	File.close();
1 cycrow 746
	return true;
747
}
748
 
749
bool CFileIO::AppendDataToPos ( const char *d, size_t size, size_t start )
750
{
52 cycrow 751
	if ( start > m_lSize ) return false;
752
	if ( m_lSize <= 0 ) {
753
		if ( !this->startWrite() ) return false;
1 cycrow 754
	}
52 cycrow 755
	else if ( start == m_lSize ) {
756
		if ( !this->startAppend() ) return false;
42 cycrow 757
	}
758
	else {
52 cycrow 759
		if ( !this->startModify() ) return false;
760
		this->seekStart(start);
42 cycrow 761
	}
1 cycrow 762
 
52 cycrow 763
	return this->write(d, size);
764
}
1 cycrow 765
 
197 cycrow 766
Utils::String CFileIO::readEndOfLineStr()
52 cycrow 767
{
197 cycrow 768
	if (!this->isOpened()) {
769
		if (!startRead())	return "";
1 cycrow 770
	}
771
 
197 cycrow 772
	std::string str;
52 cycrow 773
	std::getline(m_fId, str, '\n');
774
	return str;
1 cycrow 775
}
197 cycrow 776
Utils::WString CFileIO::readEndOfLine()
777
{
778
	if (!this->isOpened()) {
779
		if (!startRead())	return L"";
780
	}
1 cycrow 781
 
197 cycrow 782
	std::string str;
783
	std::getline(m_fId, str, '\n');
784
	return str;
785
}
786
 
196 cycrow 787
Utils::WString CFileIO::baseName() const
1 cycrow 788
{
197 cycrow 789
	return _sFile.tokens(L".", 1, -2);
1 cycrow 790
}
791
 
196 cycrow 792
const Utils::WString& CFileIO::fullFilename() const { return _sFilename; }
793
const Utils::WString& CFileIO::filename() const { return _sFile; }
794
 
795
const Utils::String CFileIO::fullFilenameStr() const { return _sFilename.toString(); }
796
const Utils::String CFileIO::filenameStr() const { return _sFile.toString(); }
797
 
798
Utils::WString CFileIO::extension () const
58 cycrow 799
{
196 cycrow 800
	if ( _sFilename.empty() ) return Utils::WString::Null();
801
	return _sFilename.token(L".", -1);
58 cycrow 802
}
803
 
196 cycrow 804
Utils::WString CFileIO::changeFileExtension(const Utils::WString &ext) const
124 cycrow 805
{
160 cycrow 806
	if ( _sFilename.empty() )
196 cycrow 807
		return Utils::WString::Null();
51 cycrow 808
 
196 cycrow 809
	return _sFilename.tokens(L".", 1, -2) + L"." + ext;
1 cycrow 810
}
811
 
197 cycrow 812
bool CFileIO::Remove(const Utils::WString& rem)
1 cycrow 813
{
197 cycrow 814
#ifdef _WIN32
815
	return DeleteFile(rem.c_str());
816
#else
52 cycrow 817
	//if ( !Exists() ) return false;
196 cycrow 818
	return (std::remove(_toFileData(rem)) == 0) ? true : false;
197 cycrow 819
#endif
52 cycrow 820
}
1 cycrow 821
 
197 cycrow 822
bool CFileIO::Rename(const Utils::WString& from, const Utils::WString &to) 
823
{
824
	if (std::rename(_toFileData(from).c_str(), _toFileData(to).c_str()) == 0)
825
		return true;
826
	return false;
827
}
828
 
52 cycrow 829
bool CFileIO::remove()
830
{
831
	if ( this->isOpened() ) this->close();
832
	if ( !this->exists() ) return false;
197 cycrow 833
	if ( CFileIO::Remove(_sFilename)) return true;
1 cycrow 834
	return false;
835
}
836
 
197 cycrow 837
bool CFileIO::writeFileUTF(std::vector<Utils::String>* lines)
121 cycrow 838
{
160 cycrow 839
	if (!lines || _sFilename.empty())
121 cycrow 840
		return false;
841
 
842
	// we need to create the directory
160 cycrow 843
	if (!_sDirIO.exists())
121 cycrow 844
	{
160 cycrow 845
		if (!_sDirIO.create())
121 cycrow 846
			return false;
847
	}
848
 
849
#ifdef _WIN32
850
	TCHAR buf[5000];
197 cycrow 851
	FILE* id = _wfopen(_sFilename.c_str(), L"wt+,ccs=UTF-8");
121 cycrow 852
	if (!id)
853
		return false;
854
 
855
	// write the rest
197 cycrow 856
	for (auto itr = lines->begin(); itr != lines->end(); itr++)
121 cycrow 857
	{
858
		Utils::String l = (*itr);
859
		if (l.isin('\n'))
860
		{
861
			int max;
197 cycrow 862
			Utils::String* strs = l.tokenise("\n", &max);
121 cycrow 863
			if (strs && max)
864
			{
865
				for (int i = 0; i < max; i++)
866
				{
867
					Utils::String line = strs[i];
868
					line += "\n";
869
					int size = wsprintf(buf, L"%hs", line.c_str());
870
					fwrite(buf, sizeof(TCHAR), wcslen(buf), id);
871
				}
872
 
873
				CLEANSPLIT(strs, max);
874
			}
875
		}
876
		else
877
		{
878
			l += "\n";
879
			int size = wsprintf(buf, L"%hs", l.c_str());
880
			fwrite(buf, sizeof(TCHAR), wcslen(buf), id);
881
		}
882
	}
883
 
884
	fclose(id);
885
 
886
	return true;
887
#else
888
	//TODO: write utf8 file writing function
889
	return false;
890
#endif
891
}
892
 
197 cycrow 893
bool CFileIO::writeFileUTF(std::vector<Utils::WString>* lines)
894
{
895
	if (!lines || _sFilename.empty())
896
		return false;
897
 
898
	// we need to create the directory
899
	if (!_sDirIO.exists())
900
	{
901
		if (!_sDirIO.create())
902
			return false;
903
	}
904
 
905
#ifdef _WIN32
906
	FILE* id = _wfopen(_sFilename.c_str(), L"wt+,ccs=UTF-8");
907
	if (!id)
908
		return false;
909
 
910
	// write the rest
911
	for (auto itr = lines->begin(); itr != lines->end(); itr++)
912
	{
913
		Utils::WString l = (*itr);
914
		if (l.contains('\n'))
915
		{
916
			std::vector<Utils::WString> strs;
917
			if(l.tokenise(L"\n", strs) && !strs.empty())
918
			{
919
				for(auto itr = strs.begin(); itr != strs.end(); itr++)
920
				{
921
					Utils::WString line = *itr;
922
					line += L"\n";
923
					fwrite(l.c_str(), sizeof(TCHAR), wcslen(l.c_str()), id);
924
				}
925
			}
926
		}
927
		else
928
		{
929
			l += L"\n";
930
			fwrite(l.c_str(), sizeof(TCHAR), wcslen(l.c_str()), id);
931
		}
932
	}
933
 
934
	fclose(id);
935
 
936
	return true;
937
#else
938
	//TODO: write utf8 file writing function
939
	return false;
940
#endif
941
}
942
 
121 cycrow 943
bool CFileIO::writeFile(std::vector<Utils::String> *lines)
944
{
160 cycrow 945
	if (!lines || _sFilename.empty())
121 cycrow 946
		return false;
947
 
948
	// we need to create the directory
160 cycrow 949
	if (!_sDirIO.exists())
121 cycrow 950
	{
160 cycrow 951
		if (!_sDirIO.create())
121 cycrow 952
			return false;
953
	}
954
 
955
 
160 cycrow 956
	std::ofstream out(_sFilename.c_str());
121 cycrow 957
	if (!out)
958
		return false;
959
 
960
	for (auto itr = lines->begin(); itr != lines->end(); itr++)
961
		out << (*itr).c_str() << std::endl;
962
 
963
	out.close();
964
 
965
	return true;
966
}
967
 
197 cycrow 968
bool CFileIO::writeFile(const std::vector<Utils::WString> &lines) const
969
{
970
	if (lines.empty() || _sFilename.empty())
971
		return false;
972
 
973
	// we need to create the directory
974
	if (!_sDirIO.exists())
975
	{
976
		if (!_sDirIO.create())
977
			return false;
978
	}
979
 
980
 
981
	std::wofstream out(_sFilename.c_str());
982
	if (!out)
983
		return false;
984
 
985
	for (auto itr = lines.begin(); itr != lines.end(); itr++)
986
		out << (*itr).c_str() << std::endl;
987
 
988
	out.close();
989
 
990
	return true;
991
}
992
 
993
 
196 cycrow 994
bool CFileIO::writeFile(Utils::WStringList* lines)
121 cycrow 995
{
160 cycrow 996
	if (!lines || _sFilename.empty())
121 cycrow 997
		return false;
998
 
999
	// we need to create the directory
160 cycrow 1000
	if (!_sDirIO.exists())
121 cycrow 1001
	{
160 cycrow 1002
		if (!_sDirIO.create())
121 cycrow 1003
			return false;
1004
	}
1005
 
197 cycrow 1006
	std::wofstream out(_sFilename.c_str());
121 cycrow 1007
	if (!out)
1008
		return false;
1009
 
196 cycrow 1010
	for (auto itr = lines->begin(); itr != lines->end(); itr++)
1011
		out << (*itr)->str.c_str() << std::endl;
1012
 
1013
	out.close();
1014
 
1015
	return true;
1016
}
1017
bool CFileIO::Rename(const Utils::WString &toFile)
197 cycrow 1018
{	
1019
	return CFileIO::Rename(_sFilename, toFile);
1 cycrow 1020
}
1021
 
196 cycrow 1022
Utils::WString CFileIO::getWindowsFilename() const
1 cycrow 1023
{
196 cycrow 1024
	return _sFilename.findReplace(L"/", L"\\");
1 cycrow 1025
}
1026
 
160 cycrow 1027
void CFileIO::setCreationTime(time_t time)
1 cycrow 1028
{
1029
#ifdef _WIN32
1030
	// Note that LONGLONG is a 64-bit value
1031
    LONGLONG ll;
1032
 
1033
	FILETIME ft;
1034
    ll = Int32x32To64(time, 10000000) + 116444736000000000;
1035
    ft.dwLowDateTime = (DWORD)ll;
1036
    ft.dwHighDateTime = ll >> 32;
1037
 
196 cycrow 1038
	Utils::WString windowsFilename = getWindowsFilename();
160 cycrow 1039
 
196 cycrow 1040
	HANDLE filename = CreateFile(windowsFilename.c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1 cycrow 1041
	// Set the file time on the file
1042
	SetFileTime(filename,(LPFILETIME) NULL,(LPFILETIME) NULL,&ft);
1043
	// Close our handle.
1044
	CloseHandle(filename);
52 cycrow 1045
 
1 cycrow 1046
#endif
1047
}
1048
 
160 cycrow 1049
time_t CFileIO::creationTime() const
1 cycrow 1050
{
52 cycrow 1051
	return modifiedTime();
1052
}
1053
 
160 cycrow 1054
time_t CFileIO::modifiedTime() const
52 cycrow 1055
{
1 cycrow 1056
#ifdef _WIN32
196 cycrow 1057
	Utils::WString windowsFilename = getWindowsFilename();
52 cycrow 1058
 
1 cycrow 1059
	WIN32_FILE_ATTRIBUTE_DATA wfad;
196 cycrow 1060
	GetFileAttributesEx(windowsFilename.c_str(), GetFileExInfoStandard, &wfad);
1 cycrow 1061
 
1062
	LARGE_INTEGER date, adjust;
52 cycrow 1063
	date.HighPart = wfad.ftLastWriteTime.dwHighDateTime;
1064
	date.LowPart = wfad.ftLastWriteTime.dwLowDateTime;
1 cycrow 1065
 
1066
	// 100-nanoseconds = milliseconds * 10000
1067
	adjust.QuadPart = 11644473600000 * 10000;
1068
 
1069
	// removes the diff between 1970 and 1601
1070
	date.QuadPart -= adjust.QuadPart;
1071
 
1072
	// converts back from 100-nanoseconds to seconds
1073
	return (time_t)(date.QuadPart / 10000000);
1074
#else
1075
	struct stat fileStat;
1076
	if ( !stat(GetWindowsFilename().c_str(), &fileStat) )
1077
		return (time_t)fileStat.st_atime;
1078
#endif
1079
	return 0;
1080
}
58 cycrow 1081
 
1082
size_t CFileIO::position()
1083
{
121 cycrow 1084
	return static_cast<size_t>(m_fId.tellg());
58 cycrow 1085
}
1086
 
1 cycrow 1087
/**
1088
 * Copys the contents of a file to another
1089
 *
1090
 * Reads and writes the files in block
1091
 */
196 cycrow 1092
bool CFileIO::copy(const Utils::WString &toFile, bool keepTime)
1 cycrow 1093
{
160 cycrow 1094
	time_t time = creationTime();
1 cycrow 1095
 
52 cycrow 1096
	CFileIO File(toFile);
1097
	if ( File.write(*this, m_lSize) ) {
86 cycrow 1098
		this->close();
1099
		File.close();
160 cycrow 1100
		if ( keepTime )	File.setCreationTime(time);
52 cycrow 1101
		return true;
1 cycrow 1102
	}
52 cycrow 1103
/*
1104
	std::fstream f(GetWindowsFilename().c_str(), std::fstream::in | std::fstream::binary);
1105
	f << std::noskipws;
1106
	std::istream_iterator<unsigned char> begin(f);
1107
	std::istream_iterator<unsigned char> end;
1108
 
1109
	std::fstream f2(toFile.c_str(), std::fstream::out | std::fstream::trunc | std::fstream::binary);
1110
	std::ostream_iterator<char> begin2(f2);
1111
 
1112
	std::copy(begin, end, begin2);
1113
	return f2.good();
1114
*/
1115
	return false;
1116
}
1 cycrow 1117
 
52 cycrow 1118
size_t CFileIO::fileSize() const
1119
{
1120
	return m_lSize;
1 cycrow 1121
}
160 cycrow 1122
 
1123
 
1124
void CFileIO::_updateFilename()
1125
{
196 cycrow 1126
	if (_sFilename.empty()) _sExt = Utils::WString::Null();
1127
	_sExt = _sFilename.token(L".", -1);
160 cycrow 1128
}
196 cycrow 1129
 
197 cycrow 1130
std::string CFileIO::_fileData() const
196 cycrow 1131
{
197 cycrow 1132
	return _toFileData(_sFilename);
196 cycrow 1133
}
197 cycrow 1134
std::string CFileIO::_toFileData(const Utils::WString &str)
196 cycrow 1135
{
211 cycrow 1136
#pragma warning(disable:4244)
197 cycrow 1137
	return std::string(str.begin(), str.end());
211 cycrow 1138
#pragma warning(default:4244)
196 cycrow 1139
}