You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1322 lines
28 KiB
1322 lines
28 KiB
#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; |
|
} |
|
|
|
|