mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-23 06:36:54 +00:00
1323 lines
28 KiB
C++
1323 lines
28 KiB
C++
#include "toollib.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define HEAP_CHECK
|
|
#endif
|
|
|
|
int g_tl_argc;
|
|
char** g_tl_argv;
|
|
int g_tl_byteorder;
|
|
int g_tl_dircount;
|
|
char** g_tl_dirlist;
|
|
int g_tl_start;
|
|
int g_tl_abort;
|
|
bool g_tl_quiet;
|
|
|
|
#pragma warning(disable:4311)
|
|
#pragma warning(disable:4267)
|
|
|
|
/*****************************************************************************
|
|
TL_Setup
|
|
|
|
*****************************************************************************/
|
|
void TL_Setup(char* appname, int argc, char** argv)
|
|
{
|
|
const char* buildStr;
|
|
|
|
g_tl_argc = argc;
|
|
g_tl_argv = argv;
|
|
|
|
g_tl_quiet = (TL_CheckParm("q") > 0) || (TL_CheckParm("quiet") > 0) || (TL_CheckParm("noheader") > 0);
|
|
|
|
if (appname)
|
|
{
|
|
TL_printf("\n%s \n",appname);
|
|
#ifdef _DEBUG
|
|
buildStr = "Debug Build";
|
|
#else
|
|
buildStr = "Release Build";
|
|
#endif
|
|
TL_printf("%s - %s %s\n\n", buildStr, __DATE__, __TIME__);
|
|
}
|
|
|
|
g_tl_abort = TL_CheckParm("abort");
|
|
g_tl_start = TL_CPUCount();
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_End
|
|
|
|
*****************************************************************************/
|
|
void TL_End(bool showtime)
|
|
{
|
|
int end;
|
|
|
|
if (showtime && !g_tl_quiet)
|
|
{
|
|
end = TL_CPUCount();
|
|
TL_printf("\n%f seconds.\n",TL_CPUTime(g_tl_start,end));
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_Error
|
|
|
|
*****************************************************************************/
|
|
void TL_Error(char* error, ...)
|
|
{
|
|
va_list argptr;
|
|
|
|
va_start(argptr,error);
|
|
vprintf(error,argptr);
|
|
va_end(argptr);
|
|
|
|
printf("\n");
|
|
|
|
#if !defined( _X360 )
|
|
__asm
|
|
{
|
|
int 3;
|
|
}
|
|
#endif
|
|
|
|
if (g_tl_abort)
|
|
abort();
|
|
|
|
exit(-1);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_CheckParm
|
|
|
|
Returns the argument number (1 to argc-1) or 0 if not present
|
|
*****************************************************************************/
|
|
int TL_CheckParm(char* check)
|
|
{
|
|
int i;
|
|
char* parm;
|
|
|
|
for (i=1; i<g_tl_argc; i++)
|
|
{
|
|
parm = g_tl_argv[i];
|
|
|
|
if (!isalpha(*parm))
|
|
if (!*++parm)
|
|
continue;
|
|
|
|
if (!stricmp(check,parm))
|
|
return (i);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_SafeRead
|
|
|
|
*****************************************************************************/
|
|
void TL_SafeRead(int handle, void* buffer, long count)
|
|
{
|
|
if (_read(handle,buffer,count) != count)
|
|
TL_Error("SafeRead(): read failure");
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_SafeOpenRead
|
|
|
|
*****************************************************************************/
|
|
int TL_SafeOpenRead(const char* filename)
|
|
{
|
|
int handle;
|
|
|
|
handle = _open(filename,_O_RDONLY|_O_BINARY);
|
|
if (handle == -1)
|
|
TL_Error("TL_SafeOpenRead(): Error opening %s: %s",filename,strerror(errno));
|
|
|
|
return (handle);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_SafeOpenWrite
|
|
|
|
*****************************************************************************/
|
|
int TL_SafeOpenWrite(const char* filename)
|
|
{
|
|
int handle;
|
|
|
|
handle = _open(filename,_O_RDWR|_O_BINARY|_O_CREAT|_O_TRUNC,0666);
|
|
if (handle == -1)
|
|
TL_Error("TL_SafeOpenWrite(): Error opening %s: %s",filename,strerror(errno));
|
|
|
|
return (handle);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_SafeWrite
|
|
|
|
*****************************************************************************/
|
|
void TL_SafeWrite(int handle, void* buffer, long count)
|
|
{
|
|
int status;
|
|
|
|
status = _write(handle,buffer,count);
|
|
if (status != count)
|
|
TL_Error("TL_SafeWrite(): write failure %d, errno=%d",status,errno);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_SafeClose
|
|
|
|
*****************************************************************************/
|
|
void TL_SafeClose(int handle, int touch)
|
|
{
|
|
// ensure date and time of modification get set
|
|
if (touch)
|
|
_futime(handle,NULL);
|
|
|
|
close(handle);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_Malloc
|
|
|
|
*****************************************************************************/
|
|
void* TL_Malloc(int size)
|
|
{
|
|
void* ptr;
|
|
int newsize;
|
|
|
|
newsize = size + sizeof(tlmem_t);
|
|
newsize = (newsize + 3) & ~3;
|
|
|
|
ptr = malloc(newsize);
|
|
if (!ptr)
|
|
TL_Error("TL_Malloc(): failure for %lu bytes",size);
|
|
|
|
memset(ptr,0,newsize);
|
|
|
|
((tlmem_t*)ptr)->id = TL_MEMID;
|
|
((tlmem_t*)ptr)->size = size;
|
|
|
|
return ((byte_t*)ptr + sizeof(tlmem_t));
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_Free
|
|
|
|
*****************************************************************************/
|
|
void TL_Free(void* ptr)
|
|
{
|
|
tlmem_t* memptr;
|
|
|
|
if (!ptr)
|
|
TL_Error("TL_Free(): null pointer");
|
|
|
|
memptr = (tlmem_t*)((byte_t*)ptr - sizeof(tlmem_t));
|
|
|
|
if (((u32)memptr) & 3)
|
|
TL_Error("TL_Free(): bad pointer %8.8x",ptr);
|
|
|
|
if (memptr->id != TL_MEMID)
|
|
TL_Error("TL_Free(): corrupted pointer %8.8x",ptr);
|
|
|
|
memptr->id = 0;
|
|
memptr->size = 0;
|
|
|
|
free(memptr);
|
|
|
|
#ifdef HEAP_CHECK
|
|
if (_heapchk() != _HEAPOK)
|
|
TL_Error("TL_Free(): heap corrupted");
|
|
#endif
|
|
}
|
|
|
|
bool TL_Check(void* ptr)
|
|
{
|
|
tlmem_t* memptr;
|
|
|
|
if (!ptr)
|
|
return false;
|
|
|
|
memptr = (tlmem_t*)((byte_t*)ptr - sizeof(tlmem_t));
|
|
|
|
if (((u32)memptr) & 3)
|
|
return false;
|
|
|
|
if (memptr->id != TL_MEMID)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_Realloc
|
|
|
|
*****************************************************************************/
|
|
void* TL_Realloc(void* ptr, int newsize)
|
|
{
|
|
int len;
|
|
tlmem_t* oldmemptr;
|
|
void* newptr;
|
|
|
|
if (!ptr)
|
|
{
|
|
newptr = TL_Malloc(newsize);
|
|
return (newptr);
|
|
}
|
|
|
|
oldmemptr = (tlmem_t*)((byte_t*)ptr - sizeof(tlmem_t));
|
|
|
|
if ((u32)oldmemptr & 3)
|
|
TL_Error("TL_Realloc(): bad pointer %8.8x",ptr);
|
|
|
|
if (oldmemptr->id != TL_MEMID)
|
|
TL_Error("TL_Realloc(): corrupted pointer %8.8x",ptr);
|
|
|
|
newptr = TL_Malloc(newsize);
|
|
|
|
len = TL_min(newsize,oldmemptr->size);
|
|
|
|
memcpy(newptr,ptr,len);
|
|
|
|
TL_Free(ptr);
|
|
|
|
return (newptr);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_strncpyz
|
|
|
|
Copy up to (N) bytes including appending null.
|
|
*****************************************************************************/
|
|
void TL_strncpyz(char* dst, char* src, int n)
|
|
{
|
|
if (n <= 0)
|
|
return;
|
|
|
|
if (n > 1)
|
|
strncpy(dst,src,n-1);
|
|
|
|
dst[n-1] = '\0';
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_strncatz
|
|
|
|
Concatenate up to dstsize bytes including appending null.
|
|
*****************************************************************************/
|
|
void TL_strncatz(char* dst, char* src, int dstsize)
|
|
{
|
|
int len;
|
|
|
|
if (dstsize <= 0)
|
|
return;
|
|
|
|
len = (int)strlen(dst);
|
|
|
|
TL_strncpyz(dst+len,src,dstsize-len);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_LoadFile
|
|
|
|
*****************************************************************************/
|
|
long TL_LoadFile(const char* filename, void** bufferptr)
|
|
{
|
|
int handle;
|
|
long length;
|
|
char* buffer;
|
|
|
|
handle = TL_SafeOpenRead(filename);
|
|
length = TL_FileLength(handle);
|
|
buffer = (char*)TL_Malloc(length+1);
|
|
TL_SafeRead(handle,buffer,length);
|
|
close(handle);
|
|
|
|
// for parsing
|
|
buffer[length] = '\0';
|
|
|
|
*bufferptr = (void*)buffer;
|
|
|
|
return (length);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_TouchFile
|
|
|
|
*****************************************************************************/
|
|
void TL_TouchFile(char* filename)
|
|
{
|
|
int h;
|
|
|
|
h = _open(filename,_O_RDWR|_O_BINARY,0666);
|
|
if (h < 0)
|
|
return;
|
|
|
|
_futime(h,NULL);
|
|
_close(h);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_SaveFile
|
|
|
|
*****************************************************************************/
|
|
void TL_SaveFile(char* filename, void* buffer, long count)
|
|
{
|
|
int handle;
|
|
|
|
handle = TL_SafeOpenWrite(filename);
|
|
TL_SafeWrite(handle,buffer,count);
|
|
|
|
TL_SafeClose(handle,true);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_FileLength
|
|
|
|
*****************************************************************************/
|
|
long TL_FileLength(int handle)
|
|
{
|
|
long pos;
|
|
long length;
|
|
|
|
pos = lseek(handle,0,SEEK_CUR);
|
|
length = lseek(handle,0,SEEK_END);
|
|
lseek(handle,pos,SEEK_SET);
|
|
|
|
return (length);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_StripFilename
|
|
|
|
Removes filename from path.
|
|
*****************************************************************************/
|
|
void TL_StripFilename(char* path)
|
|
{
|
|
int length;
|
|
|
|
length = (int)strlen(path)-1;
|
|
while ((length > 0) && (path[length] != '\\') && (path[length] != '/') && (path[length] != ':'))
|
|
length--;
|
|
|
|
/* leave possible seperator */
|
|
if (!length)
|
|
path[0] = '\0';
|
|
else
|
|
path[length+1] = '\0';
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_StripExtension
|
|
|
|
Removes extension from path.
|
|
*****************************************************************************/
|
|
void TL_StripExtension(char* path)
|
|
{
|
|
int length;
|
|
|
|
length = (int)strlen(path)-1;
|
|
while (length > 0 && path[length] != '.')
|
|
length--;
|
|
|
|
if (length && path[length] == '.')
|
|
path[length] = 0;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_StripPath
|
|
|
|
Removes path from full path.
|
|
*****************************************************************************/
|
|
void TL_StripPath(char* path, char* dest)
|
|
{
|
|
char* src;
|
|
|
|
src = path + strlen(path);
|
|
while ((src != path) && (*(src-1) != '\\') && (*(src-1) != '/') && (*(src-1) != ':'))
|
|
src--;
|
|
|
|
strcpy(dest,src);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_GetExtension
|
|
|
|
Gets any extension from the full path.
|
|
*****************************************************************************/
|
|
void TL_GetExtension(char* path, char* dest)
|
|
{
|
|
char* src;
|
|
|
|
src = path + strlen(path) - 1;
|
|
|
|
// back up until a . or the start
|
|
while (src != path && *(src-1) != '.')
|
|
src--;
|
|
|
|
if (src == path)
|
|
{
|
|
*dest = '\0'; // no extension
|
|
return;
|
|
}
|
|
|
|
strcpy(dest,src);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_DefaultPath
|
|
|
|
Adds basepath to head of path.
|
|
*****************************************************************************/
|
|
void TL_DefaultPath(char* path, char* basepath)
|
|
{
|
|
char temp[TL_MAXPATH];
|
|
char* ptr;
|
|
char ch;
|
|
|
|
if (path[0] == '\\')
|
|
{
|
|
// path is absolute
|
|
return;
|
|
}
|
|
|
|
ptr = path;
|
|
while (1)
|
|
{
|
|
ch = *ptr++;
|
|
if (!ch)
|
|
break;
|
|
|
|
if (ch == ':')
|
|
{
|
|
// path has a device - must be absolute
|
|
return;
|
|
}
|
|
}
|
|
|
|
// place basepath at head of path
|
|
// do intermediate copy to preserve any arg wierdness
|
|
strcpy(temp,path);
|
|
strcpy(path,basepath);
|
|
strcat(path,temp);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_AddSeperatorToPath
|
|
|
|
*****************************************************************************/
|
|
void TL_AddSeperatorToPath(char* inpath, char* outpath)
|
|
{
|
|
int len;
|
|
|
|
strcpy(outpath,inpath);
|
|
|
|
len = (int)strlen(outpath);
|
|
if (outpath[len-1] != '\\')
|
|
{
|
|
outpath[len] = '\\';
|
|
outpath[len+1] = '\0';
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_DefaultExtension
|
|
|
|
Adds extension a path that has no extension.
|
|
*****************************************************************************/
|
|
void TL_DefaultExtension(char* path, char* extension, bool bForce)
|
|
{
|
|
char* src;
|
|
|
|
if ( !bForce && path[0] )
|
|
{
|
|
src = path + strlen(path) - 1;
|
|
while ((src != path) && (*src != '\\') && (*src != '/'))
|
|
{
|
|
if (*src == '.')
|
|
return;
|
|
src--;
|
|
}
|
|
}
|
|
|
|
strcat(path,extension);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_ReplaceDosExtension
|
|
|
|
Handles files of the form xxxx.xxxxxxx.xxxxx.zzz
|
|
*****************************************************************************/
|
|
void TL_ReplaceDosExtension(char* path, char* extension)
|
|
{
|
|
int len;
|
|
|
|
len = (int)strlen(path);
|
|
if (!len)
|
|
return;
|
|
|
|
if (path[len-1] == '.')
|
|
{
|
|
path[len-1] = '\0';
|
|
strcat(path,extension);
|
|
return;
|
|
}
|
|
|
|
if (len-4 > 0 && path[len-4] == '.')
|
|
path[len-4] = '\0';
|
|
|
|
strcat(path,extension);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_ReplaceExtension
|
|
|
|
Replaces any extension found after '.'
|
|
*****************************************************************************/
|
|
void TL_ReplaceExtension(const char* inPath, const char* extension, char* outPath)
|
|
{
|
|
int len;
|
|
char* src;
|
|
|
|
if (outPath != inPath)
|
|
strcpy(outPath, inPath);
|
|
|
|
len = (int)strlen(outPath);
|
|
if (!len)
|
|
return;
|
|
|
|
if (outPath[len-1] == '.')
|
|
{
|
|
outPath[len-1] = '\0';
|
|
strcat(outPath, extension);
|
|
return;
|
|
}
|
|
|
|
src = outPath + len - 1;
|
|
while ((src != outPath) && (*src != '\\') && (*src != '/'))
|
|
{
|
|
if (*src == '.')
|
|
{
|
|
*src = '\0';
|
|
break;
|
|
}
|
|
src--;
|
|
}
|
|
|
|
strcat(outPath, extension);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_TempFilename
|
|
|
|
Builds a temporary filename at specified path.
|
|
*****************************************************************************/
|
|
void TL_TempFilename(char* path)
|
|
{
|
|
int len;
|
|
|
|
len = (int)strlen(path);
|
|
if (len)
|
|
{
|
|
/* tack on appending seperator */
|
|
if (path[len-1] != '\\')
|
|
{
|
|
path[len] = '\\';
|
|
path[len+1] = '\0';
|
|
}
|
|
}
|
|
|
|
strcat(path,tmpnam(NULL));
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_AlignFile
|
|
|
|
TL_Aligns data in file to any boundary.
|
|
*****************************************************************************/
|
|
int TL_AlignFile(int handle, int align)
|
|
{
|
|
int i;
|
|
int pos;
|
|
int empty;
|
|
int count;
|
|
|
|
empty = 0;
|
|
pos = lseek(handle,0,SEEK_CUR);
|
|
count = ((pos+align-1)/align)*align - pos;
|
|
|
|
for (i=0; i<count; i++)
|
|
TL_SafeWrite(handle,&empty,1);
|
|
|
|
return (pos+count);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_GetByteOrder
|
|
|
|
Gets byte ordering, true is bigendian.
|
|
*****************************************************************************/
|
|
int TL_GetByteOrder(void)
|
|
{
|
|
return (g_tl_byteorder);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_SetByteOrder
|
|
|
|
Sets byte ordering, true is bigendian.
|
|
*****************************************************************************/
|
|
void TL_SetByteOrder(int flag)
|
|
{
|
|
g_tl_byteorder = flag;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_LongSwap
|
|
|
|
Swap according to set state.
|
|
*****************************************************************************/
|
|
long TL_LongSwap(long l)
|
|
{
|
|
if (!g_tl_byteorder)
|
|
return (l);
|
|
|
|
return (TL_BigLong(l));
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_ShortSwap
|
|
|
|
Swap according to set state.
|
|
*****************************************************************************/
|
|
short TL_ShortSwap(short s)
|
|
{
|
|
if (!g_tl_byteorder)
|
|
return (s);
|
|
|
|
return (TL_BigShort(s));
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_BigShort
|
|
|
|
Converts native short to big endian
|
|
*****************************************************************************/
|
|
short TL_BigShort(short l)
|
|
{
|
|
byte_t b1;
|
|
byte_t b2;
|
|
|
|
b1 = l&255;
|
|
b2 = (l>>8)&255;
|
|
|
|
return (b1<<8) + b2;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_LittleShort
|
|
|
|
Converts native short to little endian
|
|
*****************************************************************************/
|
|
short TL_LittleShort(short l)
|
|
{
|
|
return (l);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_BigLong
|
|
|
|
Converts native long to big endian
|
|
*****************************************************************************/
|
|
long TL_BigLong(long l)
|
|
{
|
|
byte_t b1;
|
|
byte_t b2;
|
|
byte_t b3;
|
|
byte_t b4;
|
|
|
|
b1 = (byte_t)(l&255);
|
|
b2 = (byte_t)((l>>8)&255);
|
|
b3 = (byte_t)((l>>16)&255);
|
|
b4 = (byte_t)((l>>24)&255);
|
|
|
|
return ((long)b1<<24) + ((long)b2<<16) + ((long)b3<<8) + b4;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_LittleLong
|
|
|
|
Converts native long to little endian
|
|
*****************************************************************************/
|
|
long TL_LittleLong(long l)
|
|
{
|
|
return (l);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_BigFloat
|
|
|
|
Converts native float to big endian
|
|
*****************************************************************************/
|
|
float TL_BigFloat(float f)
|
|
{
|
|
union
|
|
{
|
|
float f;
|
|
byte_t b[4];
|
|
} dat1,dat2;
|
|
|
|
dat1.f = f;
|
|
dat2.b[0] = dat1.b[3];
|
|
dat2.b[1] = dat1.b[2];
|
|
dat2.b[2] = dat1.b[1];
|
|
dat2.b[3] = dat1.b[0];
|
|
|
|
return (dat2.f);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_Exists
|
|
|
|
Returns TRUE if file exists.
|
|
*****************************************************************************/
|
|
bool TL_Exists(const char* filename)
|
|
{
|
|
FILE* test;
|
|
|
|
if (!filename || !filename[0])
|
|
return (false);
|
|
|
|
if ((test = fopen(filename,"rb")) == NULL)
|
|
return (false);
|
|
|
|
fclose(test);
|
|
|
|
return (true);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_FileTime
|
|
|
|
Returns a file's time and data word.
|
|
*****************************************************************************/
|
|
u32 TL_FileTime(char* filename)
|
|
{
|
|
struct _finddata_t finddata;
|
|
intptr_t h;
|
|
|
|
h = _findfirst(filename, &finddata);
|
|
if (h == -1)
|
|
return (0);
|
|
|
|
_findclose(h);
|
|
|
|
return (finddata.time_write);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_SortNames
|
|
|
|
*****************************************************************************/
|
|
int TL_SortNames(const void *a, const void *b)
|
|
{
|
|
return (strcmp(*((char **)a), *((char **)b)));
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_FindFiles
|
|
|
|
*****************************************************************************/
|
|
int TL_FindFiles(char* filemask, char*** filenames)
|
|
{
|
|
struct _finddata_t finddata;
|
|
intptr_t h;
|
|
char sourcepath[TL_MAXPATH];
|
|
int count;
|
|
int len;
|
|
char** names = NULL;
|
|
char* ptr;
|
|
|
|
h = _findfirst(filemask,&finddata);
|
|
if (h == -1)
|
|
return (0);
|
|
|
|
TL_strncpyz(sourcepath,filemask,TL_MAXPATH);
|
|
TL_StripFilename(sourcepath);
|
|
if (!sourcepath[0])
|
|
strcpy(sourcepath,".\\");
|
|
else
|
|
{
|
|
len = (int)strlen(sourcepath);
|
|
if (sourcepath[len-1] != '\\')
|
|
TL_strncatz(sourcepath,"\\",TL_MAXPATH);
|
|
}
|
|
|
|
count = 0;
|
|
do
|
|
{
|
|
if (finddata.attrib & _A_SUBDIR)
|
|
continue;
|
|
|
|
if (!count)
|
|
names = (char**)TL_Malloc(sizeof(char*));
|
|
else
|
|
names = (char**)TL_Realloc(names,(count+1)*sizeof(char*));
|
|
|
|
ptr = (char*)TL_Malloc(TL_MAXPATH);
|
|
|
|
names[count] = ptr;
|
|
TL_strncpyz(names[count],sourcepath,TL_MAXPATH);
|
|
TL_strncatz(names[count],finddata.name,TL_MAXPATH);
|
|
|
|
count++;
|
|
}
|
|
while (!_findnext(h,&finddata));
|
|
|
|
_findclose(h);
|
|
|
|
// ascending sort the names
|
|
qsort(names,count,sizeof(char*),TL_SortNames);
|
|
|
|
*filenames = names;
|
|
return (count);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_GetFileList
|
|
|
|
*****************************************************************************/
|
|
int TL_GetFileList(char* dirpath, char* pattern, tlfile_t*** filelist)
|
|
{
|
|
struct _finddata_t finddata;
|
|
char sourcepath[TL_MAXPATH];
|
|
char fullpath[TL_MAXPATH];
|
|
char* filename;
|
|
intptr_t h;
|
|
int filecount;
|
|
int finddirs;
|
|
int len;
|
|
|
|
filecount = 0;
|
|
|
|
strcpy(sourcepath,dirpath);
|
|
len = (int)strlen(sourcepath);
|
|
|
|
if (!len)
|
|
strcpy(sourcepath,".\\");
|
|
else if (sourcepath[len-1] != '\\')
|
|
{
|
|
sourcepath[len] = '\\';
|
|
sourcepath[len+1] = '\0';
|
|
}
|
|
|
|
strcpy(fullpath,sourcepath);
|
|
|
|
if (pattern[0] == '\\' && pattern[1] == '\0')
|
|
{
|
|
// find directories
|
|
finddirs = true;
|
|
strcat(fullpath,"*");
|
|
}
|
|
else
|
|
{
|
|
finddirs = false;
|
|
strcat(fullpath,pattern);
|
|
}
|
|
|
|
h = _findfirst(fullpath,&finddata);
|
|
if (h == -1)
|
|
return (0);
|
|
|
|
do
|
|
{
|
|
// dos attribute complexities i.e. _A_NORMAL is 0
|
|
if (finddirs)
|
|
{
|
|
// skip non dirs
|
|
if (!(finddata.attrib & _A_SUBDIR))
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// skip dirs
|
|
if (finddata.attrib & _A_SUBDIR)
|
|
continue;
|
|
}
|
|
|
|
if (!stricmp(finddata.name,"."))
|
|
continue;
|
|
|
|
if (!stricmp(finddata.name,".."))
|
|
continue;
|
|
|
|
if (!filecount)
|
|
*filelist = (tlfile_t**)TL_Malloc(sizeof(tlfile_t*));
|
|
else
|
|
*filelist = (tlfile_t**)TL_Realloc(*filelist,(filecount+1)*sizeof(tlfile_t*));
|
|
|
|
(*filelist)[filecount] = (tlfile_t*)TL_Malloc(sizeof(tlfile_t));
|
|
|
|
len = (int)strlen(sourcepath) + (int)strlen(finddata.name) + 1;
|
|
filename = (char*)TL_Malloc(len);
|
|
|
|
strcpy(filename,sourcepath);
|
|
strcat(filename,finddata.name);
|
|
|
|
(*filelist)[filecount]->filename = filename;
|
|
(*filelist)[filecount]->time_write = finddata.time_write;
|
|
|
|
filecount++;
|
|
}
|
|
while (!_findnext(h,&finddata));
|
|
|
|
_findclose(h);
|
|
|
|
return (filecount);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
_RecurseFileTree
|
|
|
|
*****************************************************************************/
|
|
void _RecurseFileTree(char* dirpath, int depth)
|
|
{
|
|
tlfile_t** filelist;
|
|
int numfiles;
|
|
int i;
|
|
int len;
|
|
|
|
// recurse from source directory
|
|
numfiles = TL_GetFileList(dirpath,"\\",&filelist);
|
|
if (!numfiles)
|
|
{
|
|
// add directory name to search tree
|
|
if (!g_tl_dircount)
|
|
g_tl_dirlist = (char**)TL_Malloc(sizeof(char*));
|
|
else
|
|
g_tl_dirlist = (char**)TL_Realloc(g_tl_dirlist,(g_tl_dircount+1)*sizeof(char*));
|
|
|
|
len = (int)strlen(dirpath);
|
|
g_tl_dirlist[g_tl_dircount] = (char*)TL_Malloc(len+1);
|
|
strcpy(g_tl_dirlist[g_tl_dircount],dirpath);
|
|
|
|
g_tl_dircount++;
|
|
return;
|
|
}
|
|
|
|
for (i=0; i<numfiles; i++)
|
|
{
|
|
// form new path name
|
|
_RecurseFileTree(filelist[i]->filename,depth+1);
|
|
}
|
|
|
|
g_tl_dirlist = (char**)TL_Realloc(g_tl_dirlist,(g_tl_dircount+1)*sizeof(char*));
|
|
|
|
len = (int)strlen(dirpath);
|
|
g_tl_dirlist[g_tl_dircount] = (char*)TL_Malloc(len+1);
|
|
strcpy(g_tl_dirlist[g_tl_dircount],dirpath);
|
|
|
|
g_tl_dircount++;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_BuildFileTree
|
|
|
|
*****************************************************************************/
|
|
int TL_BuildFileTree(char* dirpath, char*** dirlist)
|
|
{
|
|
g_tl_dircount = 0;
|
|
g_tl_dirlist = NULL;
|
|
|
|
_RecurseFileTree(dirpath,0);
|
|
|
|
*dirlist = g_tl_dirlist;
|
|
return (g_tl_dircount);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_FindFiles2
|
|
|
|
*****************************************************************************/
|
|
int TL_FindFiles2(char* filemask, bool recurse, tlfile_t*** filelist)
|
|
{
|
|
char dirpath[TL_MAXPATH];
|
|
char pattern[TL_MAXPATH];
|
|
char** dirlist;
|
|
tlfile_t*** templists;
|
|
tlfile_t** list;
|
|
int* numfiles;
|
|
int numoutfiles;
|
|
int count;
|
|
int numdirs;
|
|
int i;
|
|
int j;
|
|
int k;
|
|
|
|
// get path only
|
|
strcpy(dirpath,filemask);
|
|
TL_StripFilename(dirpath);
|
|
|
|
// get pattern only
|
|
TL_StripPath(filemask,pattern);
|
|
|
|
numoutfiles = 0;
|
|
|
|
if (recurse)
|
|
{
|
|
// get the tree
|
|
numdirs = TL_BuildFileTree(dirpath,&dirlist);
|
|
if (numdirs)
|
|
{
|
|
templists = (tlfile_t***)TL_Malloc(numdirs * sizeof(tlfile_t**));
|
|
numfiles = (int*)TL_Malloc(numdirs * sizeof(int));
|
|
|
|
// iterate each directory found
|
|
for (i=0; i<numdirs; i++)
|
|
numfiles[i] = TL_GetFileList(dirlist[i],pattern,&templists[i]);
|
|
|
|
// count all the files
|
|
numoutfiles = 0;
|
|
for (i=0; i<numdirs; i++)
|
|
numoutfiles += numfiles[i];
|
|
|
|
// allocate single list
|
|
if (numoutfiles)
|
|
{
|
|
*filelist = (tlfile_t**)TL_Malloc(numoutfiles*sizeof(tlfile_t*));
|
|
|
|
k = 0;
|
|
for (i=0; i<numdirs; i++)
|
|
{
|
|
count = numfiles[i];
|
|
list = templists[i];
|
|
for (j=0; j<count; j++,k++)
|
|
{
|
|
(*filelist)[k] = list[j];
|
|
}
|
|
}
|
|
}
|
|
|
|
// free the directory lists
|
|
for (i=0; i<numdirs; i++)
|
|
{
|
|
TL_Free(dirlist[i]);
|
|
|
|
if (numfiles[i])
|
|
TL_Free(templists[i]);
|
|
}
|
|
|
|
TL_Free(dirlist);
|
|
TL_Free(templists);
|
|
TL_Free(numfiles);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
numoutfiles = TL_GetFileList(dirpath,pattern,filelist);
|
|
}
|
|
|
|
return (numoutfiles);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_FreeFileList
|
|
|
|
*****************************************************************************/
|
|
void TL_FreeFileList(int count, tlfile_t** filelist)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<count; i++)
|
|
{
|
|
TL_Free(filelist[i]->filename);
|
|
TL_Free(filelist[i]);
|
|
}
|
|
|
|
if (count)
|
|
TL_Free(filelist);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_CPUCount
|
|
|
|
*****************************************************************************/
|
|
int TL_CPUCount(void)
|
|
{
|
|
int time;
|
|
|
|
time = clock();
|
|
|
|
return (time);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_CPUTime
|
|
|
|
*****************************************************************************/
|
|
double TL_CPUTime(int start, int stop)
|
|
{
|
|
double duration;
|
|
|
|
duration = (double)(stop - start)/CLOCKS_PER_SEC;
|
|
|
|
return (duration);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_CreatePath
|
|
|
|
*****************************************************************************/
|
|
void TL_CreatePath(const char* inPath)
|
|
{
|
|
char* ptr;
|
|
char dirPath[TL_MAXPATH];
|
|
|
|
// prime and skip to first seperator
|
|
strcpy(dirPath, inPath);
|
|
ptr = strchr(dirPath, '\\');
|
|
while (ptr)
|
|
{
|
|
ptr = strchr(ptr+1, '\\');
|
|
if (ptr)
|
|
{
|
|
*ptr = '\0';
|
|
mkdir(dirPath);
|
|
*ptr = '\\';
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_Warning
|
|
|
|
*****************************************************************************/
|
|
void TL_Warning(const char* format, ...)
|
|
{
|
|
char msg[4096];
|
|
va_list argptr;
|
|
|
|
if (g_tl_quiet)
|
|
return;
|
|
|
|
va_start(argptr, format);
|
|
vsprintf(msg, format, argptr);
|
|
va_end(argptr);
|
|
|
|
printf("WARNING: %s", msg);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
TL_printf
|
|
|
|
*****************************************************************************/
|
|
void TL_printf(const char* format, ...)
|
|
{
|
|
char msg[4096];
|
|
va_list argptr;
|
|
|
|
if (g_tl_quiet)
|
|
return;
|
|
|
|
va_start(argptr, format);
|
|
vsprintf(msg, format, argptr);
|
|
va_end(argptr);
|
|
|
|
printf(msg);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// TL_IsWildcardMatch
|
|
//
|
|
// See if a string matches a wildcard specification that uses * or ?
|
|
//-----------------------------------------------------------------------------
|
|
bool TL_IsWildcardMatch( const char *wildcardString, const char *stringToCheck, bool caseSensitive )
|
|
{
|
|
char wcChar;
|
|
char strChar;
|
|
|
|
// use the starMatchesZero variable to determine whether an asterisk
|
|
// matches zero or more characters ( TRUE ) or one or more characters
|
|
// ( FALSE )
|
|
bool starMatchesZero = true;
|
|
|
|
while ( ( strChar = *stringToCheck ) && ( wcChar = *wildcardString ) )
|
|
{
|
|
// we only want to advance the pointers if we successfully assigned
|
|
// both of our char variables, so we'll do it here rather than in the
|
|
// loop condition itself
|
|
*stringToCheck++;
|
|
*wildcardString++;
|
|
|
|
// if this isn't a case-sensitive match, make both chars uppercase
|
|
// ( thanks to David John Fielder ( Konan ) at http://innuendo.ev.ca
|
|
// for pointing out an error here in the original code )
|
|
if ( !caseSensitive )
|
|
{
|
|
wcChar = toupper( wcChar );
|
|
strChar = toupper( strChar );
|
|
}
|
|
|
|
// check the wcChar against our wildcard list
|
|
switch ( wcChar )
|
|
{
|
|
// an asterisk matches zero or more characters
|
|
case '*' :
|
|
// do a recursive call against the rest of the string,
|
|
// until we've either found a match or the string has
|
|
// ended
|
|
if ( starMatchesZero )
|
|
*stringToCheck--;
|
|
|
|
while ( *stringToCheck )
|
|
{
|
|
if ( TL_IsWildcardMatch( wildcardString, stringToCheck++, caseSensitive ) )
|
|
return true;
|
|
}
|
|
|
|
break;
|
|
|
|
// a question mark matches any single character
|
|
case '?' :
|
|
break;
|
|
|
|
// if we fell through, we want an exact match
|
|
default :
|
|
if ( wcChar != strChar )
|
|
return false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if we have any asterisks left at the end of the wildcard string, we can
|
|
// advance past them if starMatchesZero is TRUE ( so "blah*" will match "blah" )
|
|
while ( ( *wildcardString ) && ( starMatchesZero ) )
|
|
{
|
|
if ( *wildcardString == '*' )
|
|
wildcardString++;
|
|
else
|
|
break;
|
|
}
|
|
|
|
// if we got to the end but there's still stuff left in either of our strings,
|
|
// return false; otherwise, we have a match
|
|
if ( ( *stringToCheck ) || ( *wildcardString ) )
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// TL_CopyString
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
char *TL_CopyString( const char* pString )
|
|
{
|
|
int size = strlen( pString ) + 1;
|
|
char *pNewString = (char *)TL_Malloc( size );
|
|
memcpy( pNewString, pString, size );
|
|
|
|
return pNewString;
|
|
}
|
|
|