Subversion Repositories spk

Rev

Rev 197 | Rev 211 | 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
 
170 cycrow 481
size_t CFileIO::readLines(Utils::CStringList& to) const
482
{
483
	if (_sFilename.empty()) return 0;
166 cycrow 484
 
170 cycrow 485
	Utils::String line;
486
	std::ifstream infile(_sFilename.c_str(), std::ios_base::in);
487
	while (getline(infile, line, '\n')) {
488
		to.pushBack(Utils::String(line).removeChar((char)0));
489
	}
490
 
491
	infile.close();
492
 
493
	return to.size();
494
}
495
 
111 cycrow 496
Utils::CStringList *CFileIO::readLinesStr()
497
{
160 cycrow 498
	if ( _sFilename.empty() ) return 0;
111 cycrow 499
 
500
	Utils::CStringList *file = new Utils::CStringList();
501
	Utils::String line;
160 cycrow 502
	std::ifstream infile (_sFilename.c_str(), std::ios_base::in);
111 cycrow 503
	while (getline(infile, line, '\n'))	{
504
		file->pushBack(line.removeChar((char)0));
505
	}
506
 
507
	infile.close();
508
 
509
	return file;
510
}
511
 
512
 
52 cycrow 513
bool CFileIO::put(const unsigned char c)
1 cycrow 514
{
52 cycrow 515
	if ( !this->isOpened() ) return false;
516
 
517
	m_fId.put(c);
518
	return !m_fId.bad();
1 cycrow 519
}
520
 
123 cycrow 521
bool CFileIO::writeSize(size_t iSize)
1 cycrow 522
{
52 cycrow 523
	if ( !this->isOpened() ) return false;
524
	if ( !this->put(static_cast<unsigned char>(iSize >> 24)) ) return false;
525
	if ( !this->put(static_cast<unsigned char>(iSize >> 16)) ) return false;
526
	if ( !this->put(static_cast<unsigned char>(iSize >> 8)) ) return false;
527
	if ( !this->put(static_cast<unsigned char>(iSize)) ) return false;
528
	m_lSize += 4;
529
	return true;
1 cycrow 530
}
531
 
52 cycrow 532
bool CFileIO::write(CFileIO &file, size_t iSize)
1 cycrow 533
{
52 cycrow 534
	if ( !this->isOpened() ) startWrite();
535
	if ( !this->isOpened() ) return false;
536
 
537
	int iMaxSize = 1000000;
538
 
539
	unsigned char *data;
540
	try {
541
		data = new unsigned char[iMaxSize + 1];
1 cycrow 542
	}
52 cycrow 543
	catch (std::exception &e) {
544
		CLog::logf(CLog::Log_IO, 2, "ERROR: CFileIO::write(CFileIO, size_t) unable to malloc data, %d (%s)", iMaxSize + 1, e.what());
545
		return false;
546
	}
1 cycrow 547
 
52 cycrow 548
	int iSizeLeft = iSize;
549
	bool bSuccess = true;
550
	while ( iSizeLeft > 0 ) {
551
		int iDoSize = iMaxSize;
552
		if ( iDoSize > iSizeLeft ) iDoSize = iSizeLeft;
1 cycrow 553
 
52 cycrow 554
		if ( !file.read(data, iDoSize) ) bSuccess = false;
555
		if ( bSuccess && !this->write(data, iDoSize) ) bSuccess = false;
556
		if ( !bSuccess ) break;
557
		iSizeLeft -= iDoSize;
558
	}
1 cycrow 559
 
52 cycrow 560
	delete data;
1 cycrow 561
 
52 cycrow 562
	return bSuccess;
1 cycrow 563
}
564
 
123 cycrow 565
bool CFileIO::write(const char *buf, size_t iSize)
52 cycrow 566
{
567
	if ( !this->isOpened() ) startWrite();
568
	if ( !this->isOpened() ) return false;
569
	try {
197 cycrow 570
		m_fId.write((char*)buf, iSize);
52 cycrow 571
	}
572
	catch (std::exception &e) {
160 cycrow 573
		CLog::logf(CLog::Log_IO, 2, "CFileIO::write() unable to write to file: %s (%s)", _sFilename.c_str(), e.what());
52 cycrow 574
		return false;
575
	}
576
	m_lSize += iSize;
577
	return !m_fId.bad();
578
}
123 cycrow 579
bool CFileIO::write(const unsigned char *buf, size_t iSize)
52 cycrow 580
{
581
	return this->write((char *)buf, iSize);
582
}
583
 
584
bool CFileIO::write(const unsigned char *buf, ...)
585
{
586
	va_list args;
587
	va_start(args, buf);
588
	bool ret = this->_write((char *)buf, args);
589
	va_end(args);
590
	return ret;
591
}
197 cycrow 592
bool CFileIO::_write(const char* buf, va_list args)
52 cycrow 593
{
197 cycrow 594
	if (!this->isOpened()) return false;
52 cycrow 595
 
596
	char buffer[10000];
597
 
197 cycrow 598
	vsprintf(buffer, buf, args);
52 cycrow 599
	try {
600
		int iLen = strlen(buffer);
197 cycrow 601
		m_fId.write((char*)buffer, iLen);
52 cycrow 602
		m_lSize += iLen;
603
	}
197 cycrow 604
	catch (std::exception& e) {
160 cycrow 605
		CLog::logf(CLog::Log_IO, 2, "CFileIO::write() unable to write to file: %s (%s)", _sFilename.c_str(), e.what());
52 cycrow 606
		return false;
607
	}
608
	return !m_fId.bad();
609
}
197 cycrow 610
bool CFileIO::_write(const wchar_t* buf, va_list args)
611
{
612
	if (!this->isOpened()) return false;
52 cycrow 613
 
197 cycrow 614
	wchar_t buffer[10000];
615
 
616
#ifdef _WIN32
617
	vswprintf_s(buffer, 10000, buf, args);
618
#else
619
	vswprintf(buffer, buf, args);
620
#endif
621
	try {
622
		size_t iLen = wcslen(buffer);
623
		m_fId.write((char*)buffer, iLen);
624
		m_lSize += iLen;
625
	}
626
	catch (std::exception& e) {
627
		CLog::logf(CLog::Log_IO, 2, "CFileIO::write() unable to write to file: %ls (%s)", _sFilename.c_str(), e.what());
628
		return false;
629
	}
630
	return !m_fId.bad();
631
}
632
 
52 cycrow 633
bool CFileIO::write(const char *buf, ...)
634
{
635
	va_list args;
636
	va_start(args, buf);
637
	bool ret = this->_write((char *)buf, args);
638
	va_end(args);
639
	return ret;
640
}
641
 
642
void CFileIO::_seek(int iPos, int iFrom)
643
{
644
	if ( !this->isOpened() ) {
645
		if ( !this->startRead() ) return;
646
	}
647
	if ( m_bSeekP ) m_fId.seekp(iPos, iFrom);
648
	else m_fId.seekg(iPos, iFrom);
649
}
650
 
123 cycrow 651
void CFileIO::seek(size_t iPos)
52 cycrow 652
{
653
	_seek(iPos, std::ios::cur);
654
}
655
 
123 cycrow 656
void CFileIO::seekEnd(size_t iPos)
52 cycrow 657
{
53 cycrow 658
	_seek(iPos, std::ios::end);
52 cycrow 659
}
660
 
123 cycrow 661
void CFileIO::seekStart(size_t iPos)
52 cycrow 662
{
663
	_seek(iPos, std::ios::beg);
664
}
665
 
666
std::fstream &CFileIO::stream()
667
{
668
	return m_fId;
669
}
670
 
671
bool CFileIO::isOpened() const
672
{
673
	if ( m_fId.is_open() )
674
		return true;
675
	return false;
676
}
677
 
678
void CFileIO::close()
679
{
680
	if ( this->isOpened() ) m_fId.close();
84 cycrow 681
	this->_readFileSize();
52 cycrow 682
}
683
 
56 cycrow 684
int CFileIO::readSize()
1 cycrow 685
{
56 cycrow 686
	unsigned char size[4];
687
	if ( this->read(size, 4) ) return (size[0] << 24) + (size[1] << 16) + (size[2] << 8) + size[3];
688
	return 0;
689
}
690
 
691
bool CFileIO::atEnd() const
692
{
52 cycrow 693
	if ( !this->isOpened() ) return true;
51 cycrow 694
	if ( m_fId.eof() )		 return true;
1 cycrow 695
	return false;
696
}
697
 
82 cycrow 698
bool CFileIO::appendFile ( const Utils::String &filename )
699
{
700
	std::fstream fromFile(filename, _in());
701
	if ( !fromFile.is_open() ) return false;
702
 
160 cycrow 703
	std::fstream toFile(_sFilename, _append());
82 cycrow 704
	if ( !toFile.is_open() ) {
705
		fromFile.close();
706
		return false;
707
	}
708
 
709
	// move to the end of the file
710
	toFile.seekg(0, std::ios::end);
711
 
712
	// get size of file
713
	fromFile.seekg(0, std::ios::end);
121 cycrow 714
	size_t size = static_cast<size_t>(fromFile.tellg());
82 cycrow 715
	fromFile.seekg(0, std::ios::beg);
716
 
717
	char data[500000];
718
	while ( size > 0 )
719
	{
720
		size_t read = 500000;
721
		if ( read > size )
722
			read = size;
723
 
724
		size -= read;
725
 
726
		fromFile.read(data, read);
727
		toFile.write(data, read);
728
	}
729
 
730
	fromFile.close();
731
	toFile.close();
732
	return true;
733
}
734
 
1 cycrow 735
 
736
bool CFileIO::AppendData ( const char *d, size_t size )
737
{
160 cycrow 738
	std::ofstream File(_sFilename, _append());
51 cycrow 739
	if ( !File.is_open() ) return false;
1 cycrow 740
 
741
	// move to the end of the file
58 cycrow 742
	//File.seekg(0, std::ios::end);
1 cycrow 743
 
744
	char *pos = (char *)d;
51 cycrow 745
	while ( size > 0 ) {
1 cycrow 746
		size_t read = 500000;
51 cycrow 747
		if ( read > size ) read = size;
1 cycrow 748
 
749
		size -= read;
750
 
51 cycrow 751
		try {
752
			File.write(pos, read);
753
		} 
754
		catch(std::exception &e) {
160 cycrow 755
			CLog::logf(CLog::Log_IO, 2, "CFileIO::AppendData() unable to write data to file: %s (%s)", _sFilename.c_str(), e.what());
51 cycrow 756
			File.close();
757
			return false;
758
		}
1 cycrow 759
		pos += read;
760
	}
761
 
51 cycrow 762
	File.close();
1 cycrow 763
	return true;
764
}
765
 
766
bool CFileIO::AppendDataToPos ( const char *d, size_t size, size_t start )
767
{
52 cycrow 768
	if ( start > m_lSize ) return false;
769
	if ( m_lSize <= 0 ) {
770
		if ( !this->startWrite() ) return false;
1 cycrow 771
	}
52 cycrow 772
	else if ( start == m_lSize ) {
773
		if ( !this->startAppend() ) return false;
42 cycrow 774
	}
775
	else {
52 cycrow 776
		if ( !this->startModify() ) return false;
777
		this->seekStart(start);
42 cycrow 778
	}
1 cycrow 779
 
52 cycrow 780
	return this->write(d, size);
781
}
1 cycrow 782
 
197 cycrow 783
Utils::String CFileIO::readEndOfLineStr()
52 cycrow 784
{
197 cycrow 785
	if (!this->isOpened()) {
786
		if (!startRead())	return "";
1 cycrow 787
	}
788
 
197 cycrow 789
	std::string str;
52 cycrow 790
	std::getline(m_fId, str, '\n');
791
	return str;
1 cycrow 792
}
197 cycrow 793
Utils::WString CFileIO::readEndOfLine()
794
{
795
	if (!this->isOpened()) {
796
		if (!startRead())	return L"";
797
	}
1 cycrow 798
 
197 cycrow 799
	std::string str;
800
	std::getline(m_fId, str, '\n');
801
	return str;
802
}
803
 
196 cycrow 804
Utils::WString CFileIO::baseName() const
1 cycrow 805
{
197 cycrow 806
	return _sFile.tokens(L".", 1, -2);
1 cycrow 807
}
808
 
196 cycrow 809
const Utils::WString& CFileIO::fullFilename() const { return _sFilename; }
810
const Utils::WString& CFileIO::filename() const { return _sFile; }
811
 
812
const Utils::String CFileIO::fullFilenameStr() const { return _sFilename.toString(); }
813
const Utils::String CFileIO::filenameStr() const { return _sFile.toString(); }
814
 
815
Utils::WString CFileIO::extension () const
58 cycrow 816
{
196 cycrow 817
	if ( _sFilename.empty() ) return Utils::WString::Null();
818
	return _sFilename.token(L".", -1);
58 cycrow 819
}
820
 
196 cycrow 821
Utils::WString CFileIO::changeFileExtension(const Utils::WString &ext) const
124 cycrow 822
{
160 cycrow 823
	if ( _sFilename.empty() )
196 cycrow 824
		return Utils::WString::Null();
51 cycrow 825
 
196 cycrow 826
	return _sFilename.tokens(L".", 1, -2) + L"." + ext;
1 cycrow 827
}
828
 
197 cycrow 829
bool CFileIO::Remove(const Utils::WString& rem)
1 cycrow 830
{
197 cycrow 831
#ifdef _WIN32
832
	return DeleteFile(rem.c_str());
833
#else
52 cycrow 834
	//if ( !Exists() ) return false;
196 cycrow 835
	return (std::remove(_toFileData(rem)) == 0) ? true : false;
197 cycrow 836
#endif
52 cycrow 837
}
1 cycrow 838
 
197 cycrow 839
bool CFileIO::Rename(const Utils::WString& from, const Utils::WString &to) 
840
{
841
	if (std::rename(_toFileData(from).c_str(), _toFileData(to).c_str()) == 0)
842
		return true;
843
	return false;
844
}
845
 
52 cycrow 846
bool CFileIO::remove()
847
{
848
	if ( this->isOpened() ) this->close();
849
	if ( !this->exists() ) return false;
197 cycrow 850
	if ( CFileIO::Remove(_sFilename)) return true;
1 cycrow 851
	return false;
852
}
853
 
197 cycrow 854
bool CFileIO::writeFileUTF(std::vector<Utils::String>* lines)
121 cycrow 855
{
160 cycrow 856
	if (!lines || _sFilename.empty())
121 cycrow 857
		return false;
858
 
859
	// we need to create the directory
160 cycrow 860
	if (!_sDirIO.exists())
121 cycrow 861
	{
160 cycrow 862
		if (!_sDirIO.create())
121 cycrow 863
			return false;
864
	}
865
 
866
#ifdef _WIN32
867
	TCHAR buf[5000];
197 cycrow 868
	FILE* id = _wfopen(_sFilename.c_str(), L"wt+,ccs=UTF-8");
121 cycrow 869
	if (!id)
870
		return false;
871
 
872
	// write the rest
197 cycrow 873
	for (auto itr = lines->begin(); itr != lines->end(); itr++)
121 cycrow 874
	{
875
		Utils::String l = (*itr);
876
		if (l.isin('\n'))
877
		{
878
			int max;
197 cycrow 879
			Utils::String* strs = l.tokenise("\n", &max);
121 cycrow 880
			if (strs && max)
881
			{
882
				for (int i = 0; i < max; i++)
883
				{
884
					Utils::String line = strs[i];
885
					line += "\n";
886
					int size = wsprintf(buf, L"%hs", line.c_str());
887
					fwrite(buf, sizeof(TCHAR), wcslen(buf), id);
888
				}
889
 
890
				CLEANSPLIT(strs, max);
891
			}
892
		}
893
		else
894
		{
895
			l += "\n";
896
			int size = wsprintf(buf, L"%hs", l.c_str());
897
			fwrite(buf, sizeof(TCHAR), wcslen(buf), id);
898
		}
899
	}
900
 
901
	fclose(id);
902
 
903
	return true;
904
#else
905
	//TODO: write utf8 file writing function
906
	return false;
907
#endif
908
}
909
 
197 cycrow 910
bool CFileIO::writeFileUTF(std::vector<Utils::WString>* lines)
911
{
912
	if (!lines || _sFilename.empty())
913
		return false;
914
 
915
	// we need to create the directory
916
	if (!_sDirIO.exists())
917
	{
918
		if (!_sDirIO.create())
919
			return false;
920
	}
921
 
922
#ifdef _WIN32
923
	FILE* id = _wfopen(_sFilename.c_str(), L"wt+,ccs=UTF-8");
924
	if (!id)
925
		return false;
926
 
927
	// write the rest
928
	for (auto itr = lines->begin(); itr != lines->end(); itr++)
929
	{
930
		Utils::WString l = (*itr);
931
		if (l.contains('\n'))
932
		{
933
			std::vector<Utils::WString> strs;
934
			if(l.tokenise(L"\n", strs) && !strs.empty())
935
			{
936
				for(auto itr = strs.begin(); itr != strs.end(); itr++)
937
				{
938
					Utils::WString line = *itr;
939
					line += L"\n";
940
					fwrite(l.c_str(), sizeof(TCHAR), wcslen(l.c_str()), id);
941
				}
942
			}
943
		}
944
		else
945
		{
946
			l += L"\n";
947
			fwrite(l.c_str(), sizeof(TCHAR), wcslen(l.c_str()), id);
948
		}
949
	}
950
 
951
	fclose(id);
952
 
953
	return true;
954
#else
955
	//TODO: write utf8 file writing function
956
	return false;
957
#endif
958
}
959
 
121 cycrow 960
bool CFileIO::writeFile(std::vector<Utils::String> *lines)
961
{
160 cycrow 962
	if (!lines || _sFilename.empty())
121 cycrow 963
		return false;
964
 
965
	// we need to create the directory
160 cycrow 966
	if (!_sDirIO.exists())
121 cycrow 967
	{
160 cycrow 968
		if (!_sDirIO.create())
121 cycrow 969
			return false;
970
	}
971
 
972
 
160 cycrow 973
	std::ofstream out(_sFilename.c_str());
121 cycrow 974
	if (!out)
975
		return false;
976
 
977
	for (auto itr = lines->begin(); itr != lines->end(); itr++)
978
		out << (*itr).c_str() << std::endl;
979
 
980
	out.close();
981
 
982
	return true;
983
}
984
 
197 cycrow 985
bool CFileIO::writeFile(const std::vector<Utils::WString> &lines) const
986
{
987
	if (lines.empty() || _sFilename.empty())
988
		return false;
989
 
990
	// we need to create the directory
991
	if (!_sDirIO.exists())
992
	{
993
		if (!_sDirIO.create())
994
			return false;
995
	}
996
 
997
 
998
	std::wofstream out(_sFilename.c_str());
999
	if (!out)
1000
		return false;
1001
 
1002
	for (auto itr = lines.begin(); itr != lines.end(); itr++)
1003
		out << (*itr).c_str() << std::endl;
1004
 
1005
	out.close();
1006
 
1007
	return true;
1008
}
1009
 
1010
 
196 cycrow 1011
bool CFileIO::writeFile(Utils::WStringList* lines)
121 cycrow 1012
{
160 cycrow 1013
	if (!lines || _sFilename.empty())
121 cycrow 1014
		return false;
1015
 
1016
	// we need to create the directory
160 cycrow 1017
	if (!_sDirIO.exists())
121 cycrow 1018
	{
160 cycrow 1019
		if (!_sDirIO.create())
121 cycrow 1020
			return false;
1021
	}
1022
 
197 cycrow 1023
	std::wofstream out(_sFilename.c_str());
121 cycrow 1024
	if (!out)
1025
		return false;
1026
 
196 cycrow 1027
	for (auto itr = lines->begin(); itr != lines->end(); itr++)
1028
		out << (*itr)->str.c_str() << std::endl;
1029
 
1030
	out.close();
1031
 
1032
	return true;
1033
}
1034
bool CFileIO::writeFile(Utils::CStringList* lines)
1035
{
1036
	if (!lines || _sFilename.empty())
1037
		return false;
1038
 
1039
	// we need to create the directory
1040
	if (!_sDirIO.exists())
1041
	{
1042
		if (!_sDirIO.create())
1043
			return false;
1044
	}
1045
 
1046
	std::ofstream out(_sFilename.c_str());
1047
	if (!out)
1048
		return false;
1049
 
121 cycrow 1050
	for(auto itr = lines->begin(); itr != lines->end(); itr++)
1051
		out << (*itr)->str.c_str() << std::endl;
1052
 
1053
	out.close();
1054
 
1055
	return true;
1056
}
1057
 
196 cycrow 1058
bool CFileIO::Rename(const Utils::WString &toFile)
197 cycrow 1059
{	
1060
	return CFileIO::Rename(_sFilename, toFile);
1 cycrow 1061
}
1062
 
196 cycrow 1063
Utils::WString CFileIO::getWindowsFilename() const
1 cycrow 1064
{
196 cycrow 1065
	return _sFilename.findReplace(L"/", L"\\");
1 cycrow 1066
}
1067
 
160 cycrow 1068
void CFileIO::setCreationTime(time_t time)
1 cycrow 1069
{
1070
#ifdef _WIN32
1071
	// Note that LONGLONG is a 64-bit value
1072
    LONGLONG ll;
1073
 
1074
	FILETIME ft;
1075
    ll = Int32x32To64(time, 10000000) + 116444736000000000;
1076
    ft.dwLowDateTime = (DWORD)ll;
1077
    ft.dwHighDateTime = ll >> 32;
1078
 
196 cycrow 1079
	Utils::WString windowsFilename = getWindowsFilename();
160 cycrow 1080
 
196 cycrow 1081
	HANDLE filename = CreateFile(windowsFilename.c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1 cycrow 1082
	// Set the file time on the file
1083
	SetFileTime(filename,(LPFILETIME) NULL,(LPFILETIME) NULL,&ft);
1084
	// Close our handle.
1085
	CloseHandle(filename);
52 cycrow 1086
 
1 cycrow 1087
#endif
1088
}
1089
 
160 cycrow 1090
time_t CFileIO::creationTime() const
1 cycrow 1091
{
52 cycrow 1092
	return modifiedTime();
1093
}
1094
 
160 cycrow 1095
time_t CFileIO::modifiedTime() const
52 cycrow 1096
{
1 cycrow 1097
#ifdef _WIN32
196 cycrow 1098
	Utils::WString windowsFilename = getWindowsFilename();
52 cycrow 1099
 
1 cycrow 1100
	WIN32_FILE_ATTRIBUTE_DATA wfad;
196 cycrow 1101
	GetFileAttributesEx(windowsFilename.c_str(), GetFileExInfoStandard, &wfad);
1 cycrow 1102
 
1103
	LARGE_INTEGER date, adjust;
52 cycrow 1104
	date.HighPart = wfad.ftLastWriteTime.dwHighDateTime;
1105
	date.LowPart = wfad.ftLastWriteTime.dwLowDateTime;
1 cycrow 1106
 
1107
	// 100-nanoseconds = milliseconds * 10000
1108
	adjust.QuadPart = 11644473600000 * 10000;
1109
 
1110
	// removes the diff between 1970 and 1601
1111
	date.QuadPart -= adjust.QuadPart;
1112
 
1113
	// converts back from 100-nanoseconds to seconds
1114
	return (time_t)(date.QuadPart / 10000000);
1115
#else
1116
	struct stat fileStat;
1117
	if ( !stat(GetWindowsFilename().c_str(), &fileStat) )
1118
		return (time_t)fileStat.st_atime;
1119
#endif
1120
	return 0;
1121
}
58 cycrow 1122
 
1123
size_t CFileIO::position()
1124
{
121 cycrow 1125
	return static_cast<size_t>(m_fId.tellg());
58 cycrow 1126
}
1127
 
1 cycrow 1128
/**
1129
 * Copys the contents of a file to another
1130
 *
1131
 * Reads and writes the files in block
1132
 */
196 cycrow 1133
bool CFileIO::copy(const Utils::WString &toFile, bool keepTime)
1 cycrow 1134
{
160 cycrow 1135
	time_t time = creationTime();
1 cycrow 1136
 
52 cycrow 1137
	CFileIO File(toFile);
1138
	if ( File.write(*this, m_lSize) ) {
86 cycrow 1139
		this->close();
1140
		File.close();
160 cycrow 1141
		if ( keepTime )	File.setCreationTime(time);
52 cycrow 1142
		return true;
1 cycrow 1143
	}
52 cycrow 1144
/*
1145
	std::fstream f(GetWindowsFilename().c_str(), std::fstream::in | std::fstream::binary);
1146
	f << std::noskipws;
1147
	std::istream_iterator<unsigned char> begin(f);
1148
	std::istream_iterator<unsigned char> end;
1149
 
1150
	std::fstream f2(toFile.c_str(), std::fstream::out | std::fstream::trunc | std::fstream::binary);
1151
	std::ostream_iterator<char> begin2(f2);
1152
 
1153
	std::copy(begin, end, begin2);
1154
	return f2.good();
1155
*/
1156
	return false;
1157
}
1 cycrow 1158
 
52 cycrow 1159
size_t CFileIO::fileSize() const
1160
{
1161
	return m_lSize;
1 cycrow 1162
}
160 cycrow 1163
 
1164
 
1165
void CFileIO::_updateFilename()
1166
{
196 cycrow 1167
	if (_sFilename.empty()) _sExt = Utils::WString::Null();
1168
	_sExt = _sFilename.token(L".", -1);
160 cycrow 1169
}
196 cycrow 1170
 
197 cycrow 1171
std::string CFileIO::_fileData() const
196 cycrow 1172
{
197 cycrow 1173
	return _toFileData(_sFilename);
196 cycrow 1174
}
197 cycrow 1175
std::string CFileIO::_toFileData(const Utils::WString &str)
196 cycrow 1176
{
197 cycrow 1177
	return std::string(str.begin(), str.end());
196 cycrow 1178
}