Subversion Repositories spk

Rev

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