OpenBarnyard
 
Loading...
Searching...
No Matches
TNativeFile_Win.cpp
Go to the documentation of this file.
1#include "ToshiPCH.h"
2#include "TNativeFile_Win.h"
3
4#include <windows.h>
5
6#undef CreateFile
7#undef FindFirstFile
8
9//-----------------------------------------------------------------------------
10// Enables memory debugging.
11// Note: Should be the last include!
12//-----------------------------------------------------------------------------
13#include "Core/TMemoryDebugOn.h"
14
16
17#pragma region TNativeFileSystem
18
20 : TFileSystem( name )
21{
22 m_NextFileHandle = INVALID_HANDLE_VALUE;
24}
25
30
31TFile* TNativeFileSystem::CreateFile( const TString8& a_rcFileName, TFILEMODE a_eFileMode )
32{
33 TNativeFile* nativeFile = new TNativeFile( this );
34
35 if ( !nativeFile->Open( a_rcFileName, a_eFileMode ) )
36 {
37 delete nativeFile;
38 return TNULL;
39 }
40
41 return nativeFile;
42}
43
45{
46 if ( file != TNULL )
47 {
48 TSTATICCAST( TNativeFile, file )->Close();
49 delete file;
50 }
51}
52
54{
55 return DeleteFileA( a_rcFileName ) != 0;
56}
57
59{
60 // Check if it's already an absolute path
61 if ( a_rcPath.Compare( "//", 2 ) == 0 ||
62 a_rcPath.Compare( "\\\\", 2 ) == 0 ||
63 ( a_rcPath.Length() >= 2 && a_rcPath[ 1 ] == ':' ) )
64 {
65 // Seems that the path is already an absolute path
66 TString8 strInternalPath = a_rcPath;
67 FixPathSlashes( strInternalPath );
68
69 return strInternalPath;
70 }
71
72 // It's definitely not an absolute path so let's make one
73 TString8 strInternalPath = m_Prefix;
74
75 // Remove slash at the end of the prefix
76 if ( strInternalPath.Length() > 0 )
77 {
78 TCHAR cLastChar = strInternalPath[ strInternalPath.Length() - 1 ];
79
80 if ( cLastChar == '/' || cLastChar == '\\' )
81 strInternalPath.Truncate( strInternalPath.Length() - 1 );
82 }
83
84 strInternalPath += TFileManager::GetSingleton()->MakeAbsolutePath( a_rcPath );
85 FixPathSlashes( strInternalPath );
86
87 return strInternalPath;
88}
89
90TBOOL TNativeFileSystem::GetFirstFile( const TString8& a_rcPath, TString8& a_rOutFileName, TFINDFILE a_ui8Flags )
91{
92 TString8 strPath( a_rcPath );
93
94 // Okay... I know using TString8::Mid here is kinda original but that's how it works in the original
95 const char* pchFilter =
96 ( strPath.Mid( strPath.Length() - 1, 1 ).Compare( "\\" ) != 0 &&
97 strPath.Mid( strPath.Length() - 1, 1 ).Compare( "/" ) != 0 ) ?
98 "\\*" :
99 "*";
100
101 strPath += pchFilter;
102
103 WIN32_FIND_DATAA oFindData;
104 HANDLE hFirstFile = FindFirstFileA( strPath, &oFindData );
105 m_NextFileHandle = hFirstFile;
106
107 if ( hFirstFile != INVALID_HANDLE_VALUE )
108 {
109 TFINDFILE ui8MaskedFlags;
110
111 if ( oFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
112 ui8MaskedFlags = a_ui8Flags & TFINDFILE_DIRECTORY;
113 else
114 ui8MaskedFlags = a_ui8Flags & TFINDFILE_FILE;
115
116 if ( ui8MaskedFlags != 0 )
117 {
118 a_rOutFileName = oFindData.cFileName;
119 return TTRUE;
120 }
121 }
122
123 return TFALSE;
124}
125
127{
128 return CreateDirectoryA( string, TNULL );
129}
130
132{
133 WIN32_FIND_DATAA findFileData;
134
135 if ( m_NextFileHandle != INVALID_HANDLE_VALUE )
136 {
137 TBOOL bResult = FindNextFileA( m_NextFileHandle, &findFileData );
138 if ( !bResult )
139 {
140 m_NextFileHandle = INVALID_HANDLE_VALUE;
141 }
142 else if ( findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
143 {
144 if ( a_ui8Flags & TFINDFILE_DIRECTORY )
145 {
146 a_rOutFileName = findFileData.cFileName;
147 return TTRUE;
148 }
149 }
150 else if ( a_ui8Flags & TFINDFILE_FILE )
151 {
152 a_rOutFileName = findFileData.cFileName;
153 return TTRUE;
154 }
155 }
156
157 return TFALSE;
158}
159
160#pragma endregion
161
163 : TFile( pFS )
164{
165 m_Handle = INVALID_HANDLE_VALUE;
166 m_Position = -1;
168 m_PrevBufferPos = -1;
174}
175
189
190// $Barnyard: FUNCTION 006dd450
194
195// $Barnyard: FUNCTION 006dce20
196TBOOL TNativeFile::LoadBuffer( TUINT32 bufferPos )
197{
198 // FUN_00689ff0
199 DWORD lpNumberOfBytesRead;
200 TASSERT( m_RBuffer != TNULL, "m_RBuffer doesn't exist" );
201
202 if ( m_PrevBufferPos != bufferPos )
203 {
204 if ( m_RBufferPosition != bufferPos )
205 {
206 m_RBufferPosition = SetFilePointer( m_Handle, bufferPos, TNULL, FILE_BEGIN );
207 if ( m_RBufferPosition != bufferPos ) return TFALSE;
208 }
209
210 if ( ReadFile( m_Handle, m_RBuffer, BUFFER_SIZE, &lpNumberOfBytesRead, TNULL ) == 0 )
211 {
212 return TFALSE;
213 }
214
215 m_RBufferPosition += lpNumberOfBytesRead;
216 m_LastBufferSize = lpNumberOfBytesRead;
217 m_PrevBufferPos = bufferPos;
218 }
219
220 return TTRUE;
221}
222
223// $Barnyard: FUNCTION 006dce90
224TINT TNativeFile::FlushWriteBuffer()
225{
226
227#ifdef BARNYARD_COMMUNITY_PATCH
228
229 // Slightly improves reading performance. No clue why this wasn't in the original engine.
230 // Helps to avoid extra calls of WriteFile that do nothing.
231 if ( m_WriteBufferUsed == 0 )
232 return 0;
233
234#endif // BARNYARD_COMMUNITY_PATCH
235
237 {
239 m_RBufferPosition = SetFilePointer( m_Handle, m_Position, NULL, FILE_BEGIN );
240
241 if ( m_RBufferPosition == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
242 {
243 return 0;
244 }
245
247 }
248
249 DWORD lpNumberOfBytesWritten;
250 if ( WriteFile( m_Handle, m_WBuffer, m_WriteBufferUsed, &lpNumberOfBytesWritten, TNULL ) == 0 )
251 return 0;
252
253 m_RBufferPosition += lpNumberOfBytesWritten;
256 return lpNumberOfBytesWritten;
257}
258
259// $Barnyard: FUNCTION 006dd4e0
260TINT TNativeFile::ReadUnbuffered( LPVOID dst, TUINT size )
261{
262 DWORD lpNumberOfBytesRead;
263 FlushWriteBuffer();
264
266 {
267 m_RBufferPosition = SetFilePointer( m_Handle, m_Position, TNULL, FILE_BEGIN );
268
269 if ( m_RBufferPosition == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
270 {
271 return 0;
272 }
273
275 }
276
277 if ( ReadFile( m_Handle, dst, size, &lpNumberOfBytesRead, TNULL ) == 0 )
278 {
279 return 0;
280 }
281
282 m_RBufferPosition += lpNumberOfBytesRead;
284
285 return lpNumberOfBytesRead;
286}
287
288// $Barnyard: FUNCTION 006dd560
289TSIZE TNativeFile::Read( void* a_pDst, TSIZE a_uiSize )
290{
291 FlushWriteBuffer();
292
293 if ( a_uiSize < 1 ) return 0;
294
295 if ( m_RBuffer != TNULL )
296 {
297 TSIZE readedCount = 0;
298 TSIZE startPos = m_Position;
299 TSIZE curBufferPos = startPos / BUFFER_SIZE * BUFFER_SIZE;
300 TSIZE newBufferPos = ( startPos + a_uiSize ) / BUFFER_SIZE * BUFFER_SIZE;
301 LPVOID curPosBuffer = a_pDst;
302
303 if ( curBufferPos != newBufferPos )
304 {
305 if ( curBufferPos == m_PrevBufferPos )
306 {
307 DWORD readCount = m_LastBufferSize - ( startPos - curBufferPos );
308
309 if ( readCount > 0 )
310 {
311 TUtil::MemCopy( a_pDst, m_RBuffer + startPos - curBufferPos, readCount );
312
313 curPosBuffer = (TCHAR*)a_pDst + readCount;
314 m_Position += readCount;
315 readedCount = readCount;
316 }
317 }
318
319 DWORD toReadCount = newBufferPos - m_Position;
320 curBufferPos = newBufferPos;
321
322 if ( toReadCount > 0 )
323 {
324 TUINT32 readed = ReadUnbuffered( curPosBuffer, toReadCount );
325 curPosBuffer = (TCHAR*)curPosBuffer + readed;
326 readedCount += readed;
327
328 if ( readed != toReadCount )
329 {
330 // end of file?
331 return readedCount;
332 }
333 }
334 }
335
336 if ( readedCount != a_uiSize && LoadBuffer( curBufferPos ) )
337 {
338 a_uiSize -= readedCount;
339 DWORD bufferLeftSize = m_Position - curBufferPos;
340 DWORD readCount = m_LastBufferSize - bufferLeftSize;
341 readCount = TMath::Min<DWORD>( readCount, a_uiSize );
342
343 if ( readCount > 0 )
344 {
345 TUtil::MemCopy( curPosBuffer, m_RBuffer + bufferLeftSize, readCount );
346 m_Position += readCount;
347 readedCount += readCount;
348 }
349 }
350
351 return readedCount;
352 }
353
354 return ReadUnbuffered( a_pDst, a_uiSize );
355}
356
357// $Barnyard: FUNCTION 006dcf00
358TSIZE TNativeFile::Write( const void* buffer, TSIZE size )
359{
361 {
363 m_RBufferPosition = SetFilePointer( m_Handle, m_Position, NULL, FILE_BEGIN );
364
365 if ( m_RBufferPosition == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
366 {
367 return 0;
368 }
369
371 }
372
373 if ( m_WriteBuffered == TFALSE )
374 {
375 DWORD written;
376 BOOL bRes = WriteFile( m_Handle, buffer, size, &written, NULL );
377
378 if ( bRes == FALSE )
379 {
380 return 0;
381 }
382
383 m_RBufferPosition += written;
385 return written;
386 }
387
388 // Flush write buffer if data doesn't fit it
389 if ( m_WriteBufferUsed + size >= BUFFER_SIZE )
390 {
391 FlushWriteBuffer();
392 }
393
394 if ( size < BUFFER_SIZE )
395 {
396 // Data fits the write buffer so append it to it
397 TUtil::MemCopy( m_WBuffer + m_WriteBufferUsed, buffer, size );
398 m_WriteBufferUsed += size;
399 return size;
400 }
401 else
402 {
403 // Data doesn't fit the write buffer at all so write it right now
404 DWORD written;
405 BOOL bRes = WriteFile( m_Handle, buffer, size, &written, NULL );
406
407 if ( bRes != FALSE )
408 {
409 m_RBufferPosition += size;
411 return written;
412 }
413 }
414
415 return 0;
416}
417
418// $Barnyard: FUNCTION 006dd190
420{
421 FlushWriteBuffer();
422 return m_Position;
423}
424
425// $Barnyard: FUNCTION 006dd000
426TBOOL TNativeFile::Seek( TINT a_iOffset, TSEEK a_eOrigin )
427{
428 FlushWriteBuffer();
429
430 if ( a_eOrigin == TSEEK_SET )
431 {
432 m_Position = a_iOffset;
433 }
434 else if ( a_eOrigin == TSEEK_CUR )
435 {
436 m_Position += a_iOffset;
437 }
438 else if ( a_eOrigin == TSEEK_END )
439 {
440 m_RBufferPosition = SetFilePointer( m_Handle, a_iOffset, TNULL, FILE_END );
441
442 if ( m_RBufferPosition == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
443 {
444 return TFALSE;
445 }
446
448 }
449
450 if ( m_Position < 0 ) m_Position = 0;
451
452 return TTRUE;
453}
454
455// $Barnyard: FUNCTION 006dd0c0
457{
458 FlushWriteBuffer();
459
460 if ( m_RBuffer != TNULL )
461 {
462 TUINT32 curBufferPos = m_Position / BUFFER_SIZE * BUFFER_SIZE;
463 if ( ( curBufferPos == m_PrevBufferPos ) && ( m_Position - curBufferPos <= m_LastBufferSize - 1 ) )
464 {
465 TCHAR c = m_RBuffer[ m_Position - curBufferPos ];
466 m_Position += sizeof( c );
467 return c;
468 }
469 }
470
471 TCHAR result;
472 if ( Read( &result, sizeof( result ) ) != sizeof( result ) )
473 return -1;
474
475 return result;
476}
477
478// $Barnyard: FUNCTION 006dd120
480{
481 FlushWriteBuffer();
482
483 if ( m_RBuffer != TNULL )
484 {
485 TUINT32 curBufferPos = m_Position / BUFFER_SIZE * BUFFER_SIZE;
486 if ( ( curBufferPos == m_PrevBufferPos ) && ( m_Position - curBufferPos <= m_LastBufferSize - 1 ) )
487 {
488 TWCHAR c = *TREINTERPRETCAST( TWCHAR*, &m_RBuffer[ m_Position - curBufferPos ] );
489 m_Position += sizeof( c );
490 return c;
491 }
492 }
493
494 TWCHAR result;
495 if ( Read( &result, sizeof( result ) ) != sizeof( result ) )
496 return L'\xFFFF';
497
498 return result;
499}
500
501// $Barnyard: FUNCTION 006dc670
503{
504 if ( Write( &a_cCharacter, 1 ) != 1 )
505 {
506 return -1;
507 }
508
509 return a_cCharacter & 0xFF;
510}
511
512// $Barnyard: FUNCTION 006dc690
514{
515 if ( Write( &a_wcCharacter, 2 ) != 2 )
516 {
517 return -1;
518 }
519
520 return a_wcCharacter & 0xFFFF;
521}
522
523// $Barnyard: FUNCTION 006dd1b0
524TINT TNativeFile::CPrintf( const TCHAR* a_szFormat, ... )
525{
526 va_list args;
527 va_start( args, a_szFormat );
528
529 TCHAR str[ 512 ];
530
531 TINT iResult = T2String8::FormatV( str, TARRAYSIZE( str ), a_szFormat, args );
532
533 va_end( args );
534
535 Write( str, iResult );
536
537 return iResult;
538}
539
540// $Barnyard: FUNCTION 006dd200
541TINT TNativeFile::WPrintf( const TWCHAR* a_wszFormat, ... )
542{
543 va_list args;
544 va_start( args, a_wszFormat );
545
546 TWCHAR str[ 512 ];
547
548 TINT iResult = T2String16::FormatV( str, TARRAYSIZE( str ), a_wszFormat, args );
549
550 Write( str, iResult * sizeof( TWCHAR ) );
551
552 va_end( args );
553
554 return iResult;
555}
556
557// $Barnyard: FUNCTION 006dd080
559{
560 m_RBufferPosition = SetFilePointer( m_Handle, 0, TNULL, TSEEK_END );
561
562 if ( m_RBufferPosition == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
563 {
564 return 0;
565 }
566
567 return m_RBufferPosition;
568}
569
570// $Barnyard: FUNCTION 006dd250
572{
573 TUINT64 uiLastWriteTime = 0;
574
575 if ( m_Handle != TNULL )
576 {
577 GetFileTime( m_Handle, NULL, NULL, (LPFILETIME)&uiLastWriteTime );
578 }
579
580 return uiLastWriteTime;
581}
582
583// $Barnyard: FUNCTION 006dcd00
584TBOOL TNativeFile::Open( const TString8& a_FileName, TFILEMODE a_Mode )
585{
586 TASSERT( a_FileName.IsIndexValid( 0 ), "TNativeFile::Open - wrong filename" );
587
588 DWORD dwCreationDisposition = OPEN_EXISTING;
589 DWORD dwDesiredAccess = 0;
590 DWORD dwShareMode = 0;
591
592 dwDesiredAccess |= ( a_Mode & TFILEMODE_READ ) ? GENERIC_READ : dwDesiredAccess;
593 dwDesiredAccess |= ( a_Mode & TFILEMODE_WRITE ) ? GENERIC_WRITE : dwDesiredAccess;
594 dwDesiredAccess |= ( a_Mode & TFILEMODE_READWRITE ) ? ( GENERIC_READ | GENERIC_WRITE ) : dwDesiredAccess;
595
596 if ( a_Mode & TFILEMODE_CREATENEW )
597 {
598 dwShareMode = FILE_SHARE_READ;
599 dwCreationDisposition = CREATE_ALWAYS;
600 dwDesiredAccess |= GENERIC_WRITE;
601 }
602
603 if ( dwDesiredAccess == 0 )
604 {
605 TWARN( "WARNING: File created with no access mode, assuming WRITEONLY\n" );
606 dwDesiredAccess = GENERIC_WRITE;
607 }
608
609 m_Handle = CreateFileA( a_FileName.GetString(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, NULL, NULL );
610
611 if ( m_Handle != INVALID_HANDLE_VALUE )
612 {
613 m_Position = 0;
615 m_PrevBufferPos = -1;
617
618 if ( a_Mode & TFILEMODE_NOBUFFER )
619 {
621 }
622 else
623 {
627 }
628 }
629 else
630 {
631 return TFALSE;
632 }
633
634 return TTRUE;
635}
636
637// $Barnyard: FUNCTION 006dd480
639{
640 FlushWriteBuffer();
641 CloseHandle( m_Handle );
642
643 m_Handle = INVALID_HANDLE_VALUE;
644 m_Position = -1;
646 m_PrevBufferPos = -1;
647 m_LastBufferSize = -1;
648
649 if ( m_RBuffer != TNULL )
650 {
651 TFree( m_RBuffer );
653 }
654
655 if ( m_WBuffer != TNULL )
656 {
657 TFree( m_WBuffer );
659 }
660}
661
663{
664 FlushWriteBuffer();
665}
666
void * TMalloc(TSIZE a_uiSize, Toshi::TMemory::MemBlock *a_pMemBlock, const TCHAR *a_szFileName, TINT a_iLineNum)
Allocates memory from a specific memory block.
Definition TMemory.cpp:973
void TFree(void *a_pMem)
Frees previously allocated memory.
Definition TMemory.cpp:1054
TUINT8 TFINDFILE
Definition TFile.h:45
TUINT16 TFILEMODE
Definition TFile.h:35
@ TFINDFILE_DIRECTORY
Definition TFile.h:49
@ TFINDFILE_FILE
Definition TFile.h:48
TSEEK
Definition TFile.h:29
@ TSEEK_SET
Definition TFile.h:30
@ TSEEK_END
Definition TFile.h:32
@ TSEEK_CUR
Definition TFile.h:31
@ TFILEMODE_READWRITE
Definition TFile.h:40
@ TFILEMODE_READ
Definition TFile.h:38
@ TFILEMODE_NOBUFFER
Definition TFile.h:42
@ TFILEMODE_WRITE
Definition TFile.h:39
@ TFILEMODE_CREATENEW
Definition TFile.h:41
#define TASSERT(X,...)
Definition Defines.h:138
#define TWARN(...)
Definition Defines.h:152
#define TSTATICCAST(POINTERTYPE, VALUE)
Definition Defines.h:69
#define TREINTERPRETCAST(TYPE, VALUE)
Definition Defines.h:68
#define TOSHI_NAMESPACE_START
Definition Defines.h:47
#define TARRAYSIZE(ARRAY)
Definition Defines.h:70
#define TOSHI_NAMESPACE_END
Definition Defines.h:50
void FixPathSlashes(TString8 &a_rPath)
wchar_t TWCHAR
Definition Typedefs.h:21
unsigned int TUINT
Definition Typedefs.h:8
uint64_t TUINT64
Definition Typedefs.h:11
size_t TSIZE
Definition Typedefs.h:9
char TCHAR
Definition Typedefs.h:20
#define TNULL
Definition Typedefs.h:23
uint32_t TUINT32
Definition Typedefs.h:13
int TINT
Definition Typedefs.h:7
#define TFALSE
Definition Typedefs.h:24
#define TTRUE
Definition Typedefs.h:25
bool TBOOL
Definition Typedefs.h:6
TFORCEINLINE const T & Min(const T &a, const T &b)
TFileSystem(const TCHAR *a_szName)
TFileLookupHandle m_NextFileHandle
Definition TFile.h:124
TString8 m_Prefix
Definition TFile.h:123
void UnmountFileSystem()
Unmounts this file system from the TFileManager.
Definition TFile.h:114
Definition TFile.h:128
TFile(TFileSystem *a_pFS)
Definition TFile.cpp:13
TString8 MakeAbsolutePath(const TString8 &a_rcRelativePath) const
void MountFileSystem(TFileSystem *a_pFileSystem)
TNativeFileSystem(const TCHAR *name)
virtual TBOOL GetFirstFile(const TString8 &a_rcPath, TString8 &a_rOutFileName, TFINDFILE a_ui8Flags) OVERRIDE
Finds out what's the first file at the specified path.
virtual TString8 MakeInternalPath(const TString8 &a_rcPath) OVERRIDE
Not documented.
virtual TBOOL MakeDirectory(const TString8 &a_rcDirectory)
virtual TBOOL GetNextFile(TString8 &a_rOutFileName, TFINDFILE a_ui8Flags) OVERRIDE
Not documented.
virtual TBOOL RemoveFile(const TString8 &a_rcFileName) OVERRIDE
Removes specified file.
virtual void DestroyFile(TFile *a_pFile) OVERRIDE
Destroys specified file.
virtual TFile * CreateFile(const TString8 &a_rcFileName, TFILEMODE a_eFileMode) OVERRIDE
Creates file.
TUINT32 m_WriteBufferUsed
TCHAR * m_RBuffer
TNativeFile(TNativeFileSystem *a_pFileSystem)
virtual TSIZE Write(const void *a_pSrc, TSIZE a_uiSize) OVERRIDE
Writes specified number of bytes to the file from the buffer.
TBOOL Open(const TString8 &a_FileName, TFILEMODE a_Mode)
TCHAR * m_WBuffer
virtual TINT PutWChar(TWCHAR a_wcCharacter) OVERRIDE
Writes one character of type wchar to the file.
virtual TINT PutCChar(TCHAR a_cCharacter) OVERRIDE
Writes one character of type TCHAR to the file.
static constexpr TUINT32 BUFFER_SIZE
virtual TSIZE Read(void *a_pDst, TSIZE a_uiSize) OVERRIDE
Reads specified number of bytes from the file into the buffer.
virtual TBOOL Seek(TINT a_iOffset, TSEEK a_eOrigin=TSEEK_CUR) OVERRIDE
Shifts current file cursor based on the specified offset and origin.
TBOOL m_WriteBuffered
virtual TSIZE GetSize() OVERRIDE
virtual void FlushBuffers() OVERRIDE
Flushes write buffers.
virtual TINT WPrintf(const TWCHAR *a_wszFormat,...) OVERRIDE
Analogue of wprintf but writes result to the file.
virtual TWCHAR GetWChar() OVERRIDE
Reads one character of type wchar from the file.
virtual TCHAR GetCChar() OVERRIDE
Reads one character of type TCHAR from the file.
virtual TUINT64 GetDate() OVERRIDE
virtual TINT CPrintf(const TCHAR *a_szFormat,...) OVERRIDE
Analogue of printf but writes result to the file.
TUINT32 m_Position
virtual TSIZE Tell() OVERRIDE
TUINT32 m_LastBufferSize
TUINT32 m_PrevBufferPos
TUINT32 m_RBufferPosition
static TINT FormatV(TWCHAR *a_pcString, TINT size, const TWCHAR *a_pcFormat, va_list args)
static TINT FormatV(TCHAR *a_pcString, TINT size, const TCHAR *a_pcFormat, va_list args)
Definition T2String8.cpp:22
static TFORCEINLINE TFileManager * GetSingleton()
Definition TSingleton.h:49
static TFORCEINLINE TFileManager * GetSingletonSafe()
Definition TSingleton.h:37
TString8 Mid(TINT a_iFirst, TINT a_iCount) const
Definition TString8.cpp:386
TINT Compare(const TCHAR *a_szString, TINT a_iLength=-1) const
Definition TString8.cpp:362
TBOOL IsIndexValid(TINT a_iIndex) const
Definition TString8.h:103
void Truncate(TINT length)
Definition TString8.cpp:257
TINT Length() const
Definition TString8.h:93
const TCHAR * GetString(TINT a_iIndex=0) const
Definition TString8.cpp:286
static void * MemCopy(void *dst, const void *src, TSIZE size)
Definition TUtil.h:90