Subversion Repositories spk

Rev

Rev 166 | Rev 173 | 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
 
121 cycrow 18
CFileIO::CFileIO(const Utils::String &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
 
52 cycrow 23
CFileIO::CFileIO(CyString filename) : m_lSize(0), m_bBinary(true), m_bAutoDelete(false), m_bSeekP(false)
24
{
82 cycrow 25
	open(filename.ToString(), 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
 
82 cycrow 44
bool CFileIO::open(const Utils::String &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
160 cycrow 50
	if ( _sFilename.isin('/') ) {
51
		_sDirIO.setDir(_sFilename.tokens("/", 1, -2));
52
		_sFile = _sFilename.token("/", -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);
52 cycrow 84
		delete data;
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);
52 cycrow 108
		delete data;
109
		return NULL;
110
	}
111
 
112
	if ( pSize ) (*pSize) = m_lSize;
113
	return data;
114
}
115
 
116
bool CFileIO::read(unsigned char *buf, size_t iSize, bool bEndChar)
117
{
118
	if ( !this->isOpened() ) startRead();
119
	if ( !this->isOpened() ) return false;
120
 
53 cycrow 121
	if ( iSize > m_lSize ) iSize = m_lSize;
52 cycrow 122
	try {
123
		m_fId.read((char *)buf, iSize);
124
	}
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
 
130
	if ( bEndChar ) buf[iSize] = '\0';
131
 
132
	return !m_fId.bad();
133
}
134
 
1 cycrow 135
bool CFileIO::WritePartFile ( size_t *offsets, size_t numOffset )
136
{
51 cycrow 137
	if ( NoFile() )	return false;
1 cycrow 138
 
160 cycrow 139
	std::fstream File(_sFilename, _in());
51 cycrow 140
	if ( !File.is_open() ) return false;
1 cycrow 141
 
142
	// first find file size
51 cycrow 143
	File.seekg(0, std::ios::end);
121 cycrow 144
	size_t fullsize = static_cast<size_t>(File.tellg()), size = fullsize;
51 cycrow 145
	File.seekg(0, std::ios::beg);
1 cycrow 146
 
81 cycrow 147
	std::fstream writeFile(CPackages::tempDirectory() + "/temp.tmp", _out());
51 cycrow 148
	if ( !File.is_open() ) {
149
		File.close();
1 cycrow 150
		return false;
151
	}
152
 
153
	size_t off = 0;
154
	size_t startPos = 0;
155
	size_t remainingSize = fullsize;
51 cycrow 156
 
157
	while ( off < numOffset ) {
121 cycrow 158
		startPos = static_cast<size_t>(File.tellg());
1 cycrow 159
		size_t offset = offsets[off++];
160
		size_t size = offset - startPos;
51 cycrow 161
		try {
162
			char *data = new char[size];
163
			File.read(data, size);
164
			writeFile.write(data, size);
165
			delete data;
166
		}
167
		catch(std::exception &e) {
160 cycrow 168
			CLog::logf(CLog::Log_IO, 2, "CFileIO::WritePartFilea() unable to read data from file: %s (%s)", _sFilename.c_str(), e.what());
51 cycrow 169
			return false;
170
		}
171
 
1 cycrow 172
		size_t datasize = offsets[off++];
51 cycrow 173
		File.seekg(datasize, std::ios::beg);
1 cycrow 174
		remainingSize = fullsize - offset - datasize;
175
	}
176
 
51 cycrow 177
	if ( remainingSize ) {
1 cycrow 178
		char data[1000000];
179
		size_t amountLeft = 1000000;
180
		while ( remainingSize )
181
		{
51 cycrow 182
			if ( amountLeft > remainingSize ) amountLeft = remainingSize;
183
			try {
184
				File.read(data, amountLeft);
185
				writeFile.write(data, amountLeft);
186
			}
187
			catch(std::exception &e) {
160 cycrow 188
				CLog::logf(CLog::Log_IO, 2, "CFileIO::WritePartFilea() unable to read data from file: %s (%s)", _sFilename.c_str(), e.what());
51 cycrow 189
				return false;
190
			}
1 cycrow 191
 
192
			remainingSize -= amountLeft;
193
			amountLeft = 1000000;
194
		}
195
	}
196
 
51 cycrow 197
	File.close();
198
	writeFile.close();
1 cycrow 199
 
200
	// now copy to original file
160 cycrow 201
	std::remove(_sFilename);
202
	std::rename(CPackages::tempDirectory() + "/temp.tmp", _sFilename);
1 cycrow 203
 
204
	return true;
205
}
206
 
207
 
118 cycrow 208
void CFileIO::setDir(const Utils::String &dir)
1 cycrow 209
{
160 cycrow 210
	if ( _sFile.empty() )	_sDirIO.setDir(dir);
211
	else					open(dir + "/" + _sFile, m_bBinary);
1 cycrow 212
}
213
 
51 cycrow 214
void CFileIO::_readFileSize ()
1 cycrow 215
{
51 cycrow 216
	m_lSize = 0;
217
 
160 cycrow 218
	std::fstream file(_sFilename, (m_bBinary) ? (std::ios::in | std::ios::binary) : (std::ios::in));
51 cycrow 219
	if ( !file.is_open() ) return;
220
 
221
	file.seekg(0, std::ios::end);
121 cycrow 222
	m_lSize = static_cast<size_t>(file.tellg());
51 cycrow 223
	file.close();
1 cycrow 224
}
225
 
226
bool CFileIO::WipeFile()
227
{
51 cycrow 228
	if ( NoFile() )	return false;
229
	std::ofstream file;
160 cycrow 230
	file.open(_sFilename, std::ios::out | std::ios::trunc);
51 cycrow 231
	bool bDone = file.is_open();
232
	file.close();
1 cycrow 233
 
51 cycrow 234
	return bDone;
1 cycrow 235
}
52 cycrow 236
 
237
 
1 cycrow 238
int CFileIO::TruncateFile ( size_t offset, size_t datasize )
239
{
52 cycrow 240
	if ( NoFile() ) return FILEERR_NOFILE;
1 cycrow 241
 
52 cycrow 242
	if ( !this->startRead() ) return FILEERR_NOOPEN;
243
	if ( (offset + datasize) > m_lSize ) return FILEERR_TOSMALL;
1 cycrow 244
 
81 cycrow 245
	CFileIO File(CPackages::tempDirectory() + "/temp.tmp");
52 cycrow 246
	if ( !File.startWrite() ) return FILEERR_NOWRITE;
247
	File.setAutoDelete(true);
1 cycrow 248
 
52 cycrow 249
	if ( !File.write(*this, offset) ) return false;
1 cycrow 250
 
251
	// next fseek after and write
52 cycrow 252
	this->seek(datasize);
253
	size_t size = m_lSize - offset - datasize;
42 cycrow 254
	if ( size > 0 ) {
52 cycrow 255
		File.write(*this, size);
42 cycrow 256
	}
1 cycrow 257
 
52 cycrow 258
	File.close();
259
	this->close();
260
	File.setAutoDelete(false);
1 cycrow 261
 
262
	// now copy to original file
160 cycrow 263
	if ( std::remove(_sFilename.c_str()) == 0 ) {
264
		std::rename(CPackages::tempDirectory() + "/temp.tmp", _sFilename.c_str());
85 cycrow 265
		size_t oldSize = m_lSize;
84 cycrow 266
		size_t checkFileSize = m_lSize - datasize;
267
		this->_readFileSize();
268
		if ( checkFileSize != m_lSize ) {
269
			CLog::log(CLog::Log_IO, 3, Utils::String("WARNING: CFileIO::TruncateFile, file size mismatch, ") + (long)checkFileSize + " => " + (long)m_lSize);
270
		}
58 cycrow 271
		return FILEERR_NONE;
272
	}
1 cycrow 273
 
58 cycrow 274
	return FILEERR_NOWRITE;
1 cycrow 275
}
276
 
52 cycrow 277
int CFileIO::_in() const
51 cycrow 278
{
279
	if ( m_bBinary ) return std::ios::in | std::ios::binary;
280
	return std::ios::in;
281
}
282
 
52 cycrow 283
int CFileIO::_out() const
51 cycrow 284
{
285
	if ( m_bBinary ) return std::ios::out | std::ios::binary;
286
	return std::ios::out;
287
}
52 cycrow 288
int CFileIO::_inout() const
289
{
290
	if ( m_bBinary ) return std::ios::in | std::ios::out | std::ios::binary;
291
	return std::ios::in | std::ios::out;
292
}
51 cycrow 293
 
52 cycrow 294
int CFileIO::_append() const
51 cycrow 295
{
296
	if ( m_bBinary ) return std::ios::out | std::ios::binary | std::ios::app;
297
	return std::ios::out | std::ios::app;
298
}
299
 
1 cycrow 300
char *CFileIO::ReadToData ( size_t *size )
301
{
302
	*size = 0;
303
 
51 cycrow 304
	if ( NoFile() ) return NULL;
305
	if ( !m_lSize )	this->_readFileSize();
306
	if ( !m_lSize ) return NULL;
1 cycrow 307
 
160 cycrow 308
	std::fstream file(_sFilename, _in());
51 cycrow 309
	if ( !file.is_open() ) return NULL;
1 cycrow 310
 
51 cycrow 311
	char *data;
312
	try {
313
		data = new char[m_lSize + 1];
314
	}
315
	catch (std::exception &e) {
316
		CLog::logf(CLog::Log_IO, 2, "CFileIO::ReadToData() unable to malloc storage, %d (%s)", m_lSize + 1, e.what());
317
		file.close();
1 cycrow 318
		return NULL;
51 cycrow 319
	}
1 cycrow 320
 
51 cycrow 321
	try {
322
		file.read((char *)data, m_lSize);
323
	}
324
	catch (std::exception &e) {
325
		CLog::logf(CLog::Log_IO, 2, "CFileIO::ReadToData() unable to read data from file (%s)", e.what());
326
		file.close();
1 cycrow 327
		return NULL;
328
	}
329
 
330
	*size = m_lSize;
51 cycrow 331
	file.close();
1 cycrow 332
 
333
	return data;
334
}
335
 
336
bool CFileIO::WriteData ( const char *data, size_t size )
337
{
338
	if ( NoFile() )
339
		return false;
340
 
160 cycrow 341
	std::fstream File(_sFilename, _out());
51 cycrow 342
	if ( !File.is_open() ) return false;
1 cycrow 343
 
51 cycrow 344
	bool ret = true;
345
	try {
346
		File.write(data, size);
347
	}
348
	catch (std::exception &e) {
160 cycrow 349
		CLog::logf(CLog::Log_IO, 2, "CFileIO::ReadToData() unable to read data from file: %s (%s)", _sFilename.c_str(), e.what());
51 cycrow 350
		ret = false;
351
	}
1 cycrow 352
 
51 cycrow 353
	File.close();
1 cycrow 354
 
51 cycrow 355
	if ( ret ) this->_readFileSize();
356
	return ret;
1 cycrow 357
}
358
 
82 cycrow 359
bool CFileIO::writeString ( const Utils::String &data )
1 cycrow 360
{
82 cycrow 361
	return WriteData ( data.c_str(), data.length() );
1 cycrow 362
}
363
 
52 cycrow 364
bool CFileIO::Exists(const Utils::String &filename)
1 cycrow 365
{
52 cycrow 366
	std::fstream File(filename, std::ios::in | std::ios::binary);
367
	bool bRet = File.good();
368
	File.close();
369
	return bRet;
370
}
371
 
372
bool CFileIO::ExistsOld () const
373
{
374
	return this->exists();
375
}
376
bool CFileIO::exists () const
377
{
378
	if ( this->isOpened() ) return true;
160 cycrow 379
	std::fstream File(_sFilename, _in());
51 cycrow 380
	bool bRet = File.good();
381
	File.close();
382
	return bRet;
1 cycrow 383
}
384
 
52 cycrow 385
bool CFileIO::startRead()
1 cycrow 386
{
52 cycrow 387
	return _start(_in(), false);
388
}
389
 
390
bool CFileIO::startWrite()
391
{
392
	return _start(_out(), true);
393
}
394
 
395
bool CFileIO::startModify()
396
{
397
	return _start(_inout(), true);
398
}
399
 
400
bool CFileIO::startAppend()
401
{
402
	return _start(_append(), false);
403
}
404
 
405
bool CFileIO::_start(int iFlags, bool bSeekP)
406
{
160 cycrow 407
	if ( !_sFilename.empty() ) {
52 cycrow 408
		if ( this->isOpened() ) this->close();
1 cycrow 409
 
160 cycrow 410
		m_fId.open(_sFilename, iFlags);
1 cycrow 411
	}
52 cycrow 412
	m_bSeekP = bSeekP;
413
	return m_fId.is_open();
1 cycrow 414
}
415
 
166 cycrow 416
std::vector<Utils::String>* CFileIO::readLines() const
82 cycrow 417
{
166 cycrow 418
	if (_sFilename.empty()) return 0;
82 cycrow 419
 
166 cycrow 420
	std::vector<Utils::String>* file = new std::vector<Utils::String>;
84 cycrow 421
	Utils::String line;
82 cycrow 422
	file->clear();
166 cycrow 423
	std::ifstream infile(_sFilename.c_str(), std::ios_base::in);
82 cycrow 424
	while (getline(infile, line, '\n')) {
425
		file->push_back(Utils::String(line).removeChar((char)0));
426
	}
427
 
428
	infile.close();
429
 
430
	return file;
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
 
170 cycrow 447
size_t CFileIO::readLines(Utils::CStringList& to) const
448
{
449
	if (_sFilename.empty()) return 0;
166 cycrow 450
 
170 cycrow 451
	Utils::String line;
452
	std::ifstream infile(_sFilename.c_str(), std::ios_base::in);
453
	while (getline(infile, line, '\n')) {
454
		to.pushBack(Utils::String(line).removeChar((char)0));
455
	}
456
 
457
	infile.close();
458
 
459
	return to.size();
460
}
461
 
462
 
1 cycrow 463
CyStringList *CFileIO::ReadLinesStr()
464
{
160 cycrow 465
	if ( _sFilename.empty() ) return 0;
1 cycrow 466
 
467
	CyStringList *file = new CyStringList;
84 cycrow 468
	Utils::String line;
160 cycrow 469
	std::ifstream infile (_sFilename.c_str(), std::ios_base::in);
111 cycrow 470
	while (getline(infile, line, '\n')) {
84 cycrow 471
		file->PushBack(CyString(line.removeChar((char)0)));
1 cycrow 472
	}
473
 
474
	infile.close();
475
 
476
	return file;
477
}
478
 
111 cycrow 479
Utils::CStringList *CFileIO::readLinesStr()
480
{
160 cycrow 481
	if ( _sFilename.empty() ) return 0;
111 cycrow 482
 
483
	Utils::CStringList *file = new Utils::CStringList();
484
	Utils::String line;
160 cycrow 485
	std::ifstream infile (_sFilename.c_str(), std::ios_base::in);
111 cycrow 486
	while (getline(infile, line, '\n'))	{
487
		file->pushBack(line.removeChar((char)0));
488
	}
489
 
490
	infile.close();
491
 
492
	return file;
493
}
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 {
553
		m_fId.write((char *)buf, iSize);
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
}
575
bool CFileIO::_write(const char *buf, va_list args) 
576
{
577
	if ( !this->isOpened() ) return false;
578
 
579
	char buffer[10000];
580
 
581
	vsprintf (buffer, buf, args);
582
	try {
583
		int iLen = strlen(buffer);
584
		m_fId.write((char *)buffer, iLen);
585
		m_lSize += iLen;
586
	}
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
}
593
 
594
bool CFileIO::write(const char *buf, ...)
595
{
596
	va_list args;
597
	va_start(args, buf);
598
	bool ret = this->_write((char *)buf, args);
599
	va_end(args);
600
	return ret;
601
}
602
 
603
void CFileIO::_seek(int iPos, int iFrom)
604
{
605
	if ( !this->isOpened() ) {
606
		if ( !this->startRead() ) return;
607
	}
608
	if ( m_bSeekP ) m_fId.seekp(iPos, iFrom);
609
	else m_fId.seekg(iPos, iFrom);
610
}
611
 
123 cycrow 612
void CFileIO::seek(size_t iPos)
52 cycrow 613
{
614
	_seek(iPos, std::ios::cur);
615
}
616
 
123 cycrow 617
void CFileIO::seekEnd(size_t iPos)
52 cycrow 618
{
53 cycrow 619
	_seek(iPos, std::ios::end);
52 cycrow 620
}
621
 
123 cycrow 622
void CFileIO::seekStart(size_t iPos)
52 cycrow 623
{
624
	_seek(iPos, std::ios::beg);
625
}
626
 
627
std::fstream &CFileIO::stream()
628
{
629
	return m_fId;
630
}
631
 
632
bool CFileIO::isOpened() const
633
{
634
	if ( m_fId.is_open() )
635
		return true;
636
	return false;
637
}
638
 
639
void CFileIO::close()
640
{
641
	if ( this->isOpened() ) m_fId.close();
84 cycrow 642
	this->_readFileSize();
52 cycrow 643
}
644
 
56 cycrow 645
int CFileIO::readSize()
1 cycrow 646
{
56 cycrow 647
	unsigned char size[4];
648
	if ( this->read(size, 4) ) return (size[0] << 24) + (size[1] << 16) + (size[2] << 8) + size[3];
649
	return 0;
650
}
651
 
652
bool CFileIO::atEnd() const
653
{
52 cycrow 654
	if ( !this->isOpened() ) return true;
51 cycrow 655
	if ( m_fId.eof() )		 return true;
1 cycrow 656
	return false;
657
}
658
 
82 cycrow 659
bool CFileIO::appendFile ( const Utils::String &filename )
660
{
661
	std::fstream fromFile(filename, _in());
662
	if ( !fromFile.is_open() ) return false;
663
 
160 cycrow 664
	std::fstream toFile(_sFilename, _append());
82 cycrow 665
	if ( !toFile.is_open() ) {
666
		fromFile.close();
667
		return false;
668
	}
669
 
670
	// move to the end of the file
671
	toFile.seekg(0, std::ios::end);
672
 
673
	// get size of file
674
	fromFile.seekg(0, std::ios::end);
121 cycrow 675
	size_t size = static_cast<size_t>(fromFile.tellg());
82 cycrow 676
	fromFile.seekg(0, std::ios::beg);
677
 
678
	char data[500000];
679
	while ( size > 0 )
680
	{
681
		size_t read = 500000;
682
		if ( read > size )
683
			read = size;
684
 
685
		size -= read;
686
 
687
		fromFile.read(data, read);
688
		toFile.write(data, read);
689
	}
690
 
691
	fromFile.close();
692
	toFile.close();
693
	return true;
694
}
695
 
1 cycrow 696
 
697
bool CFileIO::AppendData ( const char *d, size_t size )
698
{
160 cycrow 699
	std::ofstream File(_sFilename, _append());
51 cycrow 700
	if ( !File.is_open() ) return false;
1 cycrow 701
 
702
	// move to the end of the file
58 cycrow 703
	//File.seekg(0, std::ios::end);
1 cycrow 704
 
705
	char *pos = (char *)d;
51 cycrow 706
	while ( size > 0 ) {
1 cycrow 707
		size_t read = 500000;
51 cycrow 708
		if ( read > size ) read = size;
1 cycrow 709
 
710
		size -= read;
711
 
51 cycrow 712
		try {
713
			File.write(pos, read);
714
		} 
715
		catch(std::exception &e) {
160 cycrow 716
			CLog::logf(CLog::Log_IO, 2, "CFileIO::AppendData() unable to write data to file: %s (%s)", _sFilename.c_str(), e.what());
51 cycrow 717
			File.close();
718
			return false;
719
		}
1 cycrow 720
		pos += read;
721
	}
722
 
51 cycrow 723
	File.close();
1 cycrow 724
	return true;
725
}
726
 
727
bool CFileIO::AppendDataToPos ( const char *d, size_t size, size_t start )
728
{
52 cycrow 729
	if ( start > m_lSize ) return false;
730
	if ( m_lSize <= 0 ) {
731
		if ( !this->startWrite() ) return false;
1 cycrow 732
	}
52 cycrow 733
	else if ( start == m_lSize ) {
734
		if ( !this->startAppend() ) return false;
42 cycrow 735
	}
736
	else {
52 cycrow 737
		if ( !this->startModify() ) return false;
738
		this->seekStart(start);
42 cycrow 739
	}
1 cycrow 740
 
52 cycrow 741
	return this->write(d, size);
742
}
1 cycrow 743
 
52 cycrow 744
Utils::String CFileIO::readEndOfLine()
745
{
746
	if ( !this->isOpened() ) {
82 cycrow 747
		if ( !startRead() )	return "";
1 cycrow 748
	}
749
 
52 cycrow 750
	Utils::String str;
751
	std::getline(m_fId, str, '\n');
752
	return str;
1 cycrow 753
}
754
 
57 cycrow 755
Utils::String CFileIO::baseName() const
1 cycrow 756
{
160 cycrow 757
	return _sFile.tokens(".", 1, -2);
1 cycrow 758
}
759
 
160 cycrow 760
Utils::String CFileIO::extension () const
58 cycrow 761
{
160 cycrow 762
	if ( _sFilename.empty() ) return Utils::String::Null();
763
	return _sFilename.token(".", -1);
58 cycrow 764
}
765
 
124 cycrow 766
Utils::String CFileIO::changeFileExtension(const Utils::String &ext) const
767
{
160 cycrow 768
	if ( _sFilename.empty() )
124 cycrow 769
		return Utils::String::Null();
51 cycrow 770
 
160 cycrow 771
	return _sFilename.tokens(".", 1, -2) + "." + ext;
1 cycrow 772
}
773
 
52 cycrow 774
bool CFileIO::Remove(const Utils::String &rem)
1 cycrow 775
{
52 cycrow 776
	//if ( !Exists() ) return false;
777
	return (std::remove(rem) == 0) ? true : false;
778
}
1 cycrow 779
 
52 cycrow 780
bool CFileIO::remove()
781
{
782
	if ( this->isOpened() ) this->close();
783
	if ( !this->exists() ) return false;
160 cycrow 784
	if ( std::remove(_sFilename.c_str()) == 0 ) return true;
1 cycrow 785
	return false;
786
}
787
 
121 cycrow 788
bool CFileIO::writeFileUTF(std::vector<Utils::String> *lines)
789
{
160 cycrow 790
	if (!lines || _sFilename.empty())
121 cycrow 791
		return false;
792
 
793
	// we need to create the directory
160 cycrow 794
	if (!_sDirIO.exists())
121 cycrow 795
	{
160 cycrow 796
		if (!_sDirIO.create())
121 cycrow 797
			return false;
798
	}
799
 
800
#ifdef _WIN32
801
	TCHAR buf[5000];
160 cycrow 802
	wsprintf(buf, L"%hs", _sFilename.c_str());
121 cycrow 803
	FILE *id = _wfopen(buf, L"wt+,ccs=UTF-8");
804
	if (!id)
805
		return false;
806
 
807
	// write the rest
808
	for(auto itr = lines->begin(); itr != lines->end(); itr++)
809
	{
810
		Utils::String l = (*itr);
811
		if (l.isin('\n'))
812
		{
813
			int max;
814
			Utils::String *strs = l.tokenise("\n", &max);
815
			if (strs && max)
816
			{
817
				for (int i = 0; i < max; i++)
818
				{
819
					Utils::String line = strs[i];
820
					line += "\n";
821
					int size = wsprintf(buf, L"%hs", line.c_str());
822
					fwrite(buf, sizeof(TCHAR), wcslen(buf), id);
823
				}
824
 
825
				CLEANSPLIT(strs, max);
826
			}
827
		}
828
		else
829
		{
830
			l += "\n";
831
			int size = wsprintf(buf, L"%hs", l.c_str());
832
			fwrite(buf, sizeof(TCHAR), wcslen(buf), id);
833
		}
834
	}
835
 
836
	fclose(id);
837
 
838
	return true;
839
#else
840
	//TODO: write utf8 file writing function
841
	return false;
842
#endif
843
}
844
 
1 cycrow 845
bool CFileIO::WriteFile(CyStringList *lines)
846
{
160 cycrow 847
	if ( !lines || _sFilename.empty() )
1 cycrow 848
		return false;
849
 
850
	// we need to create the directory
160 cycrow 851
	if ( !_sDirIO.exists() )
1 cycrow 852
	{
160 cycrow 853
		if ( !_sDirIO.create() )
1 cycrow 854
			return false;
855
	}
856
 
160 cycrow 857
	std::ofstream out(_sFilename.c_str());
1 cycrow 858
	if ( !out )
859
		return false;
860
 
861
	/*
862
	if ( utf )
863
	{
864
		unsigned char smarker[4];
865
		smarker[0] = 0xEF;
866
		smarker[1] = 0xBB;
867
		smarker[2] = 0xBF;
868
		smarker[3] = 0x00;
869
 
870
		out << smarker;
871
	}
872
*/
873
	for ( int i = 0; i < (int)lines->Count(); i++ )
874
	{
875
		CyString l = lines->StringAt(i);
876
		out << l.c_str() << std::endl;
877
	}
878
 
879
	out.close();
880
 
881
	return true;
882
}
883
 
121 cycrow 884
bool CFileIO::writeFile(std::vector<Utils::String> *lines)
885
{
160 cycrow 886
	if (!lines || _sFilename.empty())
121 cycrow 887
		return false;
888
 
889
	// we need to create the directory
160 cycrow 890
	if (!_sDirIO.exists())
121 cycrow 891
	{
160 cycrow 892
		if (!_sDirIO.create())
121 cycrow 893
			return false;
894
	}
895
 
896
 
160 cycrow 897
	std::ofstream out(_sFilename.c_str());
121 cycrow 898
	if (!out)
899
		return false;
900
 
901
	for (auto itr = lines->begin(); itr != lines->end(); itr++)
902
		out << (*itr).c_str() << std::endl;
903
 
904
	out.close();
905
 
906
	return true;
907
}
908
 
909
bool CFileIO::writeFile(Utils::CStringList *lines)
910
{
160 cycrow 911
	if (!lines || _sFilename.empty())
121 cycrow 912
		return false;
913
 
914
	// we need to create the directory
160 cycrow 915
	if (!_sDirIO.exists())
121 cycrow 916
	{
160 cycrow 917
		if (!_sDirIO.create())
121 cycrow 918
			return false;
919
	}
920
 
160 cycrow 921
	std::ofstream out(_sFilename.c_str());
121 cycrow 922
	if (!out)
923
		return false;
924
 
925
	for(auto itr = lines->begin(); itr != lines->end(); itr++)
926
		out << (*itr)->str.c_str() << std::endl;
927
 
928
	out.close();
929
 
930
	return true;
931
}
932
 
158 cycrow 933
bool CFileIO::Rename(const Utils::String &toFile)
1 cycrow 934
{
160 cycrow 935
	if ( rename(_sFilename.c_str(), toFile.c_str()) == 0 )
1 cycrow 936
		return true;
937
	return false;
938
}
939
 
160 cycrow 940
Utils::String CFileIO::getWindowsFilename() const
1 cycrow 941
{
160 cycrow 942
	Utils::String returnString = _sFilename;
943
	returnString = returnString.findReplace("/", "\\");
1 cycrow 944
	return returnString;
945
}
946
 
160 cycrow 947
void CFileIO::setCreationTime(time_t time)
1 cycrow 948
{
949
#ifdef _WIN32
950
	// Note that LONGLONG is a 64-bit value
951
    LONGLONG ll;
952
 
953
	FILETIME ft;
954
    ll = Int32x32To64(time, 10000000) + 116444736000000000;
955
    ft.dwLowDateTime = (DWORD)ll;
956
    ft.dwHighDateTime = ll >> 32;
957
 
160 cycrow 958
	Utils::String windowsFilename = getWindowsFilename();
959
 
52 cycrow 960
	WCHAR    str[MAX_PATH];
160 cycrow 961
	MultiByteToWideChar(CP_ACP, NULL, windowsFilename.c_str(), -1, str, windowsFilename.length() + 1);
52 cycrow 962
	HANDLE filename = CreateFile(str, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1 cycrow 963
	// Set the file time on the file
964
	SetFileTime(filename,(LPFILETIME) NULL,(LPFILETIME) NULL,&ft);
965
	// Close our handle.
966
	CloseHandle(filename);
52 cycrow 967
 
1 cycrow 968
#endif
969
}
970
 
160 cycrow 971
time_t CFileIO::creationTime() const
1 cycrow 972
{
52 cycrow 973
	return modifiedTime();
974
}
975
 
160 cycrow 976
time_t CFileIO::modifiedTime() const
52 cycrow 977
{
1 cycrow 978
#ifdef _WIN32
52 cycrow 979
	WCHAR    str[MAX_PATH];
160 cycrow 980
	Utils::String windowsFilename = getWindowsFilename();
981
	MultiByteToWideChar(CP_ACP, NULL, windowsFilename.c_str(), windowsFilename.length() + 1, str, MAX_PATH);
52 cycrow 982
 
1 cycrow 983
	WIN32_FILE_ATTRIBUTE_DATA wfad;
52 cycrow 984
	GetFileAttributesEx(str, GetFileExInfoStandard, &wfad);
1 cycrow 985
 
986
	LARGE_INTEGER date, adjust;
52 cycrow 987
	date.HighPart = wfad.ftLastWriteTime.dwHighDateTime;
988
	date.LowPart = wfad.ftLastWriteTime.dwLowDateTime;
1 cycrow 989
 
990
	// 100-nanoseconds = milliseconds * 10000
991
	adjust.QuadPart = 11644473600000 * 10000;
992
 
993
	// removes the diff between 1970 and 1601
994
	date.QuadPart -= adjust.QuadPart;
995
 
996
	// converts back from 100-nanoseconds to seconds
997
	return (time_t)(date.QuadPart / 10000000);
998
#else
999
	struct stat fileStat;
1000
	if ( !stat(GetWindowsFilename().c_str(), &fileStat) )
1001
		return (time_t)fileStat.st_atime;
1002
#endif
1003
	return 0;
1004
}
58 cycrow 1005
 
1006
size_t CFileIO::position()
1007
{
121 cycrow 1008
	return static_cast<size_t>(m_fId.tellg());
58 cycrow 1009
}
1010
 
1 cycrow 1011
/**
1012
 * Copys the contents of a file to another
1013
 *
1014
 * Reads and writes the files in block
1015
 */
52 cycrow 1016
bool CFileIO::copy(const Utils::String &toFile, bool keepTime)
1 cycrow 1017
{
160 cycrow 1018
	time_t time = creationTime();
1 cycrow 1019
 
52 cycrow 1020
	CFileIO File(toFile);
1021
	if ( File.write(*this, m_lSize) ) {
86 cycrow 1022
		this->close();
1023
		File.close();
160 cycrow 1024
		if ( keepTime )	File.setCreationTime(time);
52 cycrow 1025
		return true;
1 cycrow 1026
	}
52 cycrow 1027
/*
1028
	std::fstream f(GetWindowsFilename().c_str(), std::fstream::in | std::fstream::binary);
1029
	f << std::noskipws;
1030
	std::istream_iterator<unsigned char> begin(f);
1031
	std::istream_iterator<unsigned char> end;
1032
 
1033
	std::fstream f2(toFile.c_str(), std::fstream::out | std::fstream::trunc | std::fstream::binary);
1034
	std::ostream_iterator<char> begin2(f2);
1035
 
1036
	std::copy(begin, end, begin2);
1037
	return f2.good();
1038
*/
1039
	return false;
1040
}
1 cycrow 1041
 
52 cycrow 1042
size_t CFileIO::fileSize() const
1043
{
1044
	return m_lSize;
1 cycrow 1045
}
160 cycrow 1046
 
1047
 
1048
void CFileIO::_updateFilename()
1049
{
1050
	if (_sFilename.empty()) _sExt = Utils::String::Null();
1051
	_sExt = _sFilename.token(".", -1);
1052
}