/*=========================================================================== * * File: DL_File.CPP * Author: Dave Humphrey (uesp@m0use.net) * Created On: Monday, May 07, 2001 * * Implementation for file related routines for Dave's Library of common * code. * *=========================================================================*/ /* Include Files */ #include "dl_file.h" #include <direct.h> #include <errno.h> //#include <limits.h> //#include <sys\stat.h> //#include <io.h> #include <ctype.h> #ifndef _MSC_VER #include <dir.h> #endif /*=========================================================================== * * Begin Local Variable Definitions * *=========================================================================*/ DEFINE_FILE(); /*=========================================================================== * End of Local Variable Definitions *=========================================================================*/ /*========================================================================= * * Function - boolean ChangeDirectory (pPath); * * Returns TRUE if the specified path is a valid directory. Does this * by attempting to change paths. If successful the current path is * changed to the given directory. Otherwise the current path is * unchanged and FALSE is returned. ASSERTs on NULL input. Is * currently valid in the following systems: * WIN32 - Uses the _chdir() function * MSDOS - Uses the chdir() function * ASSERTs if run under any other system. * *=======================================================================*/ boolean ChangeDirectory (const char* pPath) { DEFINE_FUNCTION("ChangeDirectory()"); int Result; /* Make sure the given path is valid */ ASSERT(pPath != NULL); /* Call the correct function according to the current system */ #if defined(__BCPLUSPLUS__) Result = chdir(pPath); /* Change active drives if required */ if (Result == 0 && pPath[1] == ':') { Result = _chdrive(tolower(pPath[0]) - 'a' + 1); } #elif defined(_WIN32) Result = _chdir(pPath); #elif defined(__MSDOS__) Result = chdir(pPath); /* Change active drives if required */ if (Result == 0 && pPath[1] == ':') { Result = _chdrive(tolower(pPath[0]) - 'a' + 1); } #else ASSERT(FALSE); #endif if (Result != 0) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Directory '%s' is not valid!", pPath); return (FALSE); } return(TRUE); } /*========================================================================= * End of Function ChangeDirectory() *=======================================================================*/ /*=========================================================================== * * Function - char* ChangeExtension (pDestFilename, pSourceFilename, * pNewExtension, MaxStringLength); * * Copies the source filename to the destination, changing the file's * extension. The destination filename will be, at most, MaxStringLength * bytes in length. The new extension can include the leading '.' * character or not. A pointer to the destination string is returned. * The function ASSERTs if passed a bad pointer. * *=========================================================================*/ char* ChangeExtension (char* pDestFilename, const char* pSourceFilename, const char* pNewExtension, const size_t MaxStringLength) { DEFINE_FUNCTION("ChangeExtension()"); size_t DestLength; /* Ensure valid input */ ASSERT(pDestFilename != NULL && pSourceFilename != NULL && pNewExtension != NULL); /* Create the new filename without an extension */ strnncpy(pDestFilename, pSourceFilename, MaxStringLength); RemoveExtension(pDestFilename); DestLength = strlen(pDestFilename); /* Ensure the '.' extension character is present */ if (*pNewExtension != '.' && DestLength < MaxStringLength) { chrcat(pDestFilename, '.'); DestLength++; } /* Add the new extension to the destination filename */ strncat(pDestFilename, pNewExtension, MaxStringLength - DestLength); return (pDestFilename); } /*=========================================================================== * End of Function ChangeExtension() *=========================================================================*/ /*=========================================================================== * * Function - boolean CompareExtension (pFilename, pExtension); * * Compares the extension of the given filename with the given extension * and returns TRUE if they match (case insensitive). The '.' extension * character is not included. ASSERTs if passed invalid string pointers. * *=========================================================================*/ boolean CompareExtension (const char* pFilename, const char* pExtension) { DEFINE_FUNCTION("CompareExtension()"); char* pFileExt; int Result; /* Ensure valid input */ ASSERT(pFilename != NULL && pExtension != NULL); /* Attempt to find the file's extension */ pFileExt = FindExtension(pFilename); if (pFileExt != NULL) { Result = stricmp(pFileExt, pExtension); if (Result == 0) return (TRUE); } /* No extension found */ return (FALSE); } /*=========================================================================== * End of Function CompareExtension() *=========================================================================*/ /*========================================================================= * * Function - boolean CopyOneFile (pInputFile, pOutputFile); * * Copies the given input file to the output file. Returns FALSE on any * error. Overwrites the destination file if it exists. ASSERTs if * given invalid file strings. Changed the buffer from a stack variable * to a dynamic because of problems with 16-bit compiles under Borland. * *=======================================================================*/ boolean CopyOneFile (const char* pInputFile, const char* pOutputFile) { DEFINE_FUNCTION("CopyOneFile()"); FILE* pInputHandle = NULL; FILE* pOutputHandle = NULL; byte* Buffer; size_t ReadSize; size_t WriteSize; boolean ReturnValue = TRUE; /* Ensure valid input */ ASSERT(pInputFile != NULL && pOutputFile != NULL); /* Attempt to open input file */ pInputHandle = OpenFile(pInputFile, "rb"); if (pInputHandle == NULL) return (FALSE); /* Attempt to open output file */ pOutputHandle = OpenFile(pOutputFile, "wb"); if (pOutputHandle == NULL) { fclose(pInputHandle); return (FALSE); } /* Allocate the transfer buffer */ Buffer = (byte *) CreateString(COPYFILE_BUFFERSIZE); /* Read and write file in sections until finished */ do { /* Input data from source file and output to destination */ ReadSize = fread(Buffer, 1, COPYFILE_BUFFERSIZE, pInputHandle); WriteSize = fwrite(Buffer, 1, ReadSize, pOutputHandle); /* Ensure both the input and output was successful */ if (WriteSize != ReadSize || ferror(pInputHandle) || ferror(pOutputHandle)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Failed to copy file '%s' to '%s'!", pInputFile, pOutputFile); ReturnValue = FALSE; break; } } while (ReadSize == COPYFILE_BUFFERSIZE); /* Close files */ DestroyPointer(Buffer); fclose (pInputHandle); fclose (pOutputHandle); return (ReturnValue); } /*========================================================================= * End of Function CopyOneFile() *=======================================================================*/ /*========================================================================= * * Function - char* CreatePath (pNewPath, pString, MaxStringLength); * * Creates a path from the given string. Copies up to MaxStringLength * bytes into the destination string and ensures that the given path ends * in the current LocalePathChar character. ASSERTs on invalid input. * Returns a pointer to the new string. * *=======================================================================*/ char* CreatePath (char* pNewPath, const char* pString, const size_t MaxStringLength) { DEFINE_FUNCTION("CreatePath()"); /* Ensure all input is valid */ ASSERT(pNewPath != NULL && pString != NULL); /* Copy the given string into the new path */ strnncpy (pNewPath, pString, MaxStringLength); /* Ensure the path ends with a path character */ if ((size_t)strlen(pNewPath) < MaxStringLength) TerminatePath(pNewPath); return (pNewPath); } /*========================================================================= * End of Function CreatePath() *=======================================================================*/ /*========================================================================= * * Function - char* ExtractFilename (pFilename, pPath, MaxStringLength); * * Copies just the filename from the given path into the given file string * (up to MaxStringLength bytes). ASSERTs if passed a bad pointer. Returns * a pointer to the file string. * *=======================================================================*/ char* ExtractFilename (char* pFilename, const char* pPath, const size_t MaxStringLength) { DEFINE_FUNCTION("ExtractFilename()"); /* Ensure valid input */ ASSERT(pFilename != NULL && pPath != NULL); /* Find the start of the filename in the path string */ pPath = FindFilename(pPath); /* Check to ensure a filename was found in the path */ if (pPath == NULL) *pFilename = NULL_CHAR; else strnncpy (pFilename, pPath, MaxStringLength); return (pFilename); } /*========================================================================= * End of Function ExtractFilename() *=======================================================================*/ /*========================================================================= * * Function - char* ExtractPath (pPath, pString, MaxStringLength); * * Copies just the path from the given string and copies into the * specified path (at most MaxStringLength bytes). Returns a pointer * to the new path string. Ensures the path ends in the current * LocalePathChar character. ASSERTs if passed a bad pointer. * Assumes the string has the format: * drive:\\path1\\path2\\filename * drive:\\filename * drive:filename * Both the drive and filename are optional. * *=======================================================================*/ char* ExtractPath (char* pPath, const char* pString, const size_t MaxStringLength) { DEFINE_FUNCTION("ExtractPath()"); char* pFilePtr; /* Ensure all the input is valid */ ASSERT(pPath != NULL && pString != NULL); /* Copy the string into the new path */ strnncpy (pPath, pString, MaxStringLength); /* Remove any filename from the new path string, if any */ pFilePtr = FindFilename(pPath); *pFilePtr = NULL_CHAR; /* Ensure the path terminates properly, if possible */ if ((size_t) strlen(pPath) < MaxStringLength) TerminatePath(pPath); return (pPath); } /*========================================================================= * End of Function ExtractPath() *=======================================================================*/ /*========================================================================= * * Function - boolean FileExists (pFilename); * * Returns TRUE if the specified file exists and can be opened for * reading. ASSERTs if passed a bad pointer. * *=======================================================================*/ boolean FileExists (const char* pFilename) { DEFINE_FUNCTION("FileExists()"); FILE* pFileHandle; /* Ensure valid input */ ASSERT(pFilename != NULL); /* Attempt to open file for reading */ pFileHandle = fopen(pFilename, "r"); if (pFileHandle == NULL) return(FALSE); /* File was opened and therefore exists, close and return success */ fclose(pFileHandle); return(TRUE); } /*========================================================================= * End of Function FileExists() *=======================================================================*/ /*=========================================================================== * * Function - char* FindExtension (pFilename); * * Returns a pointer to the first character in the file extension, just * after the '.' character. Returns NULL if the file has no extension. * ASSERTs if given an invalid string pointer. Searches for the first * '.' character from the end of the string before a path seperator * character (LocalePathChar) or a ':'. * *=========================================================================*/ char* FindExtension (const char* pFilename) { DEFINE_FUNCTION("FindExtension()"); size_t StringIndex; /* Ensure valid input */ ASSERT(pFilename != NULL); /* Find the end of the filename */ StringIndex = strlen(pFilename); /* Find the last '.' character before the path/drive starts */ while (pFilename[StringIndex] != LocalePathChar && pFilename[StringIndex] != ':' && StringIndex != 0) { StringIndex--; /* Check for the extension marker charaacter */ if (pFilename[StringIndex] == '.') { return (char *)(pFilename + StringIndex + 1); } } /* No extension found */ return (NULL); } /*=========================================================================== * End of Function FindExtension() *=========================================================================*/ /*========================================================================= * * Function - char* FindFilename (pPath); * * Returns a pointer to the first character in the filename in the given * complete path. ASSERTs if given an invalid pointer. Returns an * empty string if the given path contains no filename. Uses the current * LocalePathChar and the drive character ':'. * *=======================================================================*/ char* FindFilename (const char* pPath) { DEFINE_FUNCTION("FindFilename()"); size_t StringIndex; /* Ensure the input is valid */ ASSERT(pPath != NULL); /* Start at the end of the given path */ StringIndex = strlen(pPath); while (StringIndex != 0) { StringIndex--; if (pPath[StringIndex] == LocalePathChar || pPath[StringIndex] == ':') { StringIndex++; break; } } return (char *)(pPath + StringIndex); } /*========================================================================= * End of Function FindFilename() *=======================================================================*/ /*=========================================================================== * * Function - long GetFileSize (pFilename); * * Returns the size of the give filename. Returns 0 on any error and * sets the appropiate error code. ASSERTs if given a bad file string pointer. * *=========================================================================*/ long GetFileSize (const char* pFilename) { //DEFINE_FUNCTION("GetFileSize(char*)"); long FileSize; boolean Result; Result = GetFileSize(FileSize, pFilename); if (!Result) return (0); return (FileSize); } /*=========================================================================== * End of Function GetFileSize() *=========================================================================*/ /*=========================================================================== * * Function - long GetFileSize (pFileHandle); * * Returns the size of the give file stream. Returns 0 on any error and * sets the appropiate error code. ASSERTs if given a bad file stream pointer. * The current file position remains unchanged. * *=========================================================================*/ long GetFileSize (FILE* pFileHandle) { //DEFINE_FUNCTION("GetFileSize(FILE*)"); long FileSize; boolean Result; Result = GetFileSize(FileSize, pFileHandle); if (!Result) return (0); return (FileSize); } /*=========================================================================== * End of Function GetFileSize() *=========================================================================*/ /*=========================================================================== * * Function - boolean GetFileSize (FileSize, pFilename); * * Attempts to retrieve the size in bytes of the given filename. Returns * FALSE on any error (setting the appropiate error), or TRUE on success. * ASSERTs if given an invalid file string pointer. * *=========================================================================*/ boolean GetFileSize (long& FileSize, const char* pFilename) { DEFINE_FUNCTION("GetFileSize(long&, char*)"); FILE* pFileHandle; boolean Result; /* Ensure valid input */ ASSERT(pFilename != NULL); /* Attempt to open file for binary input */ pFileHandle = fopen(pFilename, "rb"); if (pFileHandle == NULL) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Could not open the file '%s'!", pFilename); return (FALSE); } Result = GetFileSize(FileSize, pFileHandle); fclose (pFileHandle); return (Result); } /*=========================================================================== * End of Function GetFileSize() *=========================================================================*/ /*=========================================================================== * * Function - boolean GetFileSize (FileSize, pFileHandle); * * Attempts to retrieve the number of bytes in the given valid file * stream. The file position of the stream is unchanged. Returns * TRUE on success, or FALSE on any error, setting the appropiate error. * ASSERTs if given an invalid stream pointer. Files opened in text mode * may not report the file size correctly. * *=========================================================================*/ boolean GetFileSize (long& FileSize, FILE* pFileHandle) { DEFINE_FUNCTION("GetFileSize(long&, FILE*)"); long PrevFilePos; int Result; /* Ensure valid input */ ASSERT(pFileHandle != NULL); /* Save the current file position */ PrevFilePos = ftell(pFileHandle); if (PrevFilePos < 0) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Could not retrieve current position in file!"); return (FALSE); } /* Attempt to move to the end of the file */ Result = fseek(pFileHandle, 0, SEEK_END); if (Result < 0) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Could not move file position to end of file!"); return (FALSE); } /* Get the size of the file in bytes */ FileSize = ftell(pFileHandle); if (FileSize < 0) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Could not retrieve current position in file!"); return (FALSE); } Result = fseek(pFileHandle, PrevFilePos, SEEK_SET); if (Result < 0) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Could not move file position to previous location!"); return (FALSE); } return (TRUE); } /*=========================================================================== * End of Function GetFileSize() *=========================================================================*/ /*=========================================================================== * * Function - boolean HasExtension (pFilename); * * Returns TRUE if the given filename has an extension. ASSERTs if given * an invalid string pointer. * *=========================================================================*/ boolean HasExtension (const char* pFilename) { DEFINE_FUNCTION("HasExtension()"); /* Ensure valid input */ ASSERT(pFilename != NULL); if (FindExtension(pFilename) == NULL) return (FALSE); return (TRUE); } /*=========================================================================== * End of Function HasExtension() *=========================================================================*/ /*=========================================================================== * * Function - boolean HasPath (pFilename); * * Returns TRUE if the given filename contains a path. ASSERTs if given an * invalid string pointer. Uses the current LocalePathChar character and the * drive character ':'. * *=========================================================================*/ boolean HasPath (const char* pFilename) { DEFINE_FUNCTION("HasPath()"); /* Ensure valid input */ ASSERT(pFilename != NULL); /* Look for any drive/path characters in filename */ while (*pFilename != NULL_CHAR) { if (*pFilename == LocalePathChar || *pFilename == ':') return (TRUE); pFilename++; } return (FALSE); } /*=========================================================================== * End of Function HasPath() *=========================================================================*/ /*========================================================================= * * Function - boolean IsDirectory (pPath); * * Returns TRUE if the specified path is a valid but does not change * change the current directory. ASSERTs if the input path pointer is * invalid. Sets the appropiate error on failure. * *=======================================================================*/ boolean IsDirectory(const char* pPath) { DEFINE_FUNCTION("IsDirectory()"); char InitialPath[_MAX_PATH+1]; char* pResult; int Result; /* Ensure valid input */ ASSERT(pPath != NULL); /* Save the initial directory */ pResult = getcwd(InitialPath, _MAX_PATH); if (pResult == NULL) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Failed to retrieve the current directory!"); return (FALSE); } /* Attempt to change directories */ Result = chdir(pPath); if (Result != 0) return(FALSE); /* Restore the initial path and return success */ chdir(InitialPath); return(TRUE); } /*========================================================================= * End of Function IsDirectory() *=======================================================================*/ /*======================================================================== * * Function - boolean IsFileWriteable (pFilename); * * Returns TRUE if the given file can be written to. ASSERTs if * input string is invalid. * *======================================================================*/ boolean IsFileWriteable (const char* pFilename) { DEFINE_FUNCTION("IsFileWriteable()"); FILE* pFileHandle; /* Ensure valid input */ ASSERT(pFilename != NULL); /* Attempt to open the file for appending */ pFileHandle = fopen (pFilename, "ab"); if (pFileHandle == NULL) return (FALSE); /* Close the now open file and return success */ fclose (pFileHandle); return (TRUE); } /*======================================================================== * End of Function IsFileWriteable() *======================================================================*/ /*========================================================================= * * Function - boolean IsWildCard (pFilename); * * Returns TRUE if the given string has any '*' or '?' wildcard * characters in it. ASSERTs if the given string is invalid. * *=======================================================================*/ boolean IsWildCard (const char* pFilename) { DEFINE_FUNCTION("IsWildCard()"); /* Ensure valid input */ ASSERT(pFilename != NULL); /* Search entire string for a wildcard character */ while (*pFilename != NULL_CHAR) { if (*pFilename == '*' || *pFilename == '?') return (TRUE); pFilename++; } /* No wildcard characters found */ return (FALSE); } /*========================================================================= * End of Function IsWildcard() *=======================================================================*/ /*=========================================================================== * * Function - FILE* OpenFile (pFilename, pMode); * * Wrapper function for opening a file with fopen(). Records error and * SystemLog information automatically. Returns NULL on any error. * ASSERTs if the filename or mode string is invalid. * *=========================================================================*/ FILE* OpenFile (const char* pFilename, const char* pMode) { DEFINE_FUNCTION("OpenFile(char*, char*)"); FILE* pFileHandle = NULL; /* Ensure valid input */ ASSERT(pFilename != NULL && pMode != NULL); /* Attempt to open file in desired mode */ if (*pFilename != NULL_CHAR && *pMode != NULL_CHAR) { pFileHandle = fopen(pFilename, pMode); } /* Check for error conditions and output status */ if (pFileHandle == NULL) ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Failed to open the file '%s' (mode was '%s')!", pFilename, pMode); else SystemLog.Printf ("Opened file '%s' in mode '%s'...", pFilename, pMode); return (pFileHandle); } /*=========================================================================== * End of Function OpenFile() *=========================================================================*/ /*=========================================================================== * * Function - boolean OpenFile (ppFileHandle, pFilename, pMode); * * Attempts to open a file using fopen(). Returns TRUE on success, and * FALSE on error, setting the appropiate error. ASSERTs if any input * string pointer is invalid. * *=========================================================================*/ boolean OpenFile (FILE** ppFileHandle, const char* pFilename, const char* pMode) { DEFINE_FUNCTION("OpenFile(FILE**, char*, char*)"); /* Ensure valid input */ ASSERT(ppFileHandle != NULL); *ppFileHandle = OpenFile(pFilename, pMode); if (*ppFileHandle == NULL) return (FALSE); return (TRUE); } /*=========================================================================== * End of Function OpenFile() *=========================================================================*/ /*=========================================================================== * * Function - boolean ReadFile (ppBuffer, BytesRead, pFilename, TextMode); * * Attempts to read the entire file into a new string buffer. * On any error FALSE is returned and the appropiate error code set. * On success, the ppBuffer points to the newly allocated string * containing the file data, and BytesRead is the size of the string. * ASSERTs if tanyhe input is invalid. Ensure that any valid * returned pointer is at one point unallocated with delete. If the * TextMode flag is TRUE (FILE_TEXT), the file is read in text mode. * If FALSE (FILE_BINARY), the file is read in binary mode. Note that * on some systems, the two modes are identical. * *=========================================================================*/ boolean ReadFile (char** ppBuffer, size_t& BytesRead, const char* pFilename, const boolean TextMode) { DEFINE_FUNCTION("ReadFile()"); FILE* pFileHandle; long FileSize; size_t BufferSize; boolean Result; boolean ReturnValue = TRUE; /* Ensure valid input */ ASSERT(pFilename != NULL && ppBuffer != NULL); BytesRead = 0; *ppBuffer = NULL; /* Attempt to open the file for input */ pFileHandle = OpenFile(pFilename, TextMode ? "rt" : "rb"); if (pFileHandle == NULL) return (FALSE); /* Attempt to get the file size in bytes */ Result = GetFileSize(FileSize, pFileHandle); BufferSize = (size_t) FileSize; /* If an error occured getting the file size, do nothing */ if (!Result) { ReturnValue = FALSE; } /* For systems with long/int having different bit sizes */ else if (FileSize != (long) BufferSize) { ErrorHandler.AddError(ERR_MEM, "Cannot read the file '%s' as it's size exceeds the maximum allocation size!", pFilename); ReturnValue = FALSE; } /* Allocate input buffer and read data from file */ else { *ppBuffer = CreateString(BufferSize); BytesRead = fread(*ppBuffer, sizeof(char), BufferSize, pFileHandle); /* Ensure the input was entirely successfull */ if (ferror(pFileHandle)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Could not read the entire file '%s' (%u of %u bytes read)!", pFilename, BytesRead, BufferSize); DestroyPointer(*ppBuffer); ReturnValue = FALSE; } } fclose (pFileHandle); return (ReturnValue); } /*=========================================================================== * End of Function ReadFile() *=========================================================================*/ /*=========================================================================== * * Function - boolean ReadFileBuffer (ppBuffer, BytesRead, pFilename, MaxSize, TextMode); * * Attempts to read the entire, or part of, a file into an existing string * buffer. On any error FALSE is returned and the appropiate error code set. * On success, at most MaxSize bytes of the file is read into the ppBuffer, * BytesRead is the number of bytes read. ASSERTs if tanyhe input is invalid. * If the TextMode flag is TRUE (FILE_TEXT), the file is read in text mode. * If FALSE (FILE_BINARY), the file is read in binary mode. Note that * on some systems, the two modes are identical. The buffer should be * at least one byte bigger in text mode to allow for the '\0' terminating8 * byte. * *=========================================================================*/ boolean ReadFileBuffer (char** ppBuffer, size_t& BytesRead, const char* pFilename, const size_t MaxInputSize, const boolean TextMode) { DEFINE_FUNCTION("ReadFileBuffer()"); FILE* pFileHandle; long FileSize; size_t BufferSize; boolean Result; boolean ReturnValue = TRUE; /* Ensure valid input */ ASSERT(pFilename != NULL && ppBuffer != NULL && *ppBuffer != NULL); BytesRead = 0; /* Attempt to open the file for input */ pFileHandle = OpenFile(pFilename, TextMode ? "rt" : "rb"); if (pFileHandle == NULL) return (FALSE); /* Attempt to get the file size in bytes */ Result = GetFileSize(FileSize, pFileHandle); BufferSize = (size_t) FileSize; /* If an error occured getting the file size, do nothing */ if (!Result) { ReturnValue = FALSE; } /* For systems with long/int having different bit sizes */ else if (FileSize != (long) BufferSize) { ErrorHandler.AddError(ERR_MEM, "Cannot read the file '%s' as it's size exceeds the maximum allocation size!", pFilename); ReturnValue = FALSE; } /* Read data from file */ else { if (BufferSize > MaxInputSize) BufferSize = MaxInputSize; BytesRead = fread(*ppBuffer, sizeof(char), BufferSize, pFileHandle); /* Ensure the input was entirely successfull */ if (ferror(pFileHandle)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Could not read the file '%s' (%u of %u bytes read)!", pFilename, BytesRead, BufferSize); ReturnValue = FALSE; } /* NULL terminate if in text mode */ if (TextMode) (*ppBuffer)[BufferSize] = NULL_CHAR; } fclose (pFileHandle); return (ReturnValue); } /*=========================================================================== * End of Function ReadFileBuffer() *=========================================================================*/ /*========================================================================= * * Function - int ReadLine (pFileHandle, pString, MaxStringLength); * * Reads up to MaxStringLength characters or to the first Linefeed * from the given file into the given string. If string is NULL, * characters are merely read and not stored in string. Returns: * READLINE_OK : Success * READLINE_MSL : If the maximum string length was reached * READLINE_EOF : End-of-file was reached * READLINE_ERROR : An error was encountered. Sets the appropiate error. * ASSERTs if the input file handle is invalid. The CR character is not * included at the end of the string. MaxStringLength must be greater * than 0. * *=======================================================================*/ int ReadLine (FILE* pFileHandle, char* pString, const size_t MaxStringLength) { DEFINE_FUNCTION("ReadLine()"); int ReturnValue = READLINE_OK; int InputChar; size_t StringLength = 0; /* Ignore any invalid file handle input */ ASSERT(pFileHandle != NULL); ASSERT(MaxStringLength != 0); /* Check if at the eof already */ if (feof(pFileHandle)) { ErrorHandler.AddError(ERR_READFILE, "Could not read line, already at the end of the file!"); return (READLINE_ERROR); } /* Main input loop (infinite) */ do { /* Read in next character from file */ InputChar = fgetc(pFileHandle); /* Check for EOF or Error conditions */ if (InputChar == EOF) { if (!feof(pFileHandle)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Failed to read line from file!"); ReturnValue = READLINE_ERROR; } else ReturnValue = READLINE_EOF; break; } /* Check for end of line */ else if (InputChar == LF_CHAR) { break; } /* Add character to string buffer */ else if (pString != NULL) { pString[StringLength] = (char) InputChar; StringLength++; /* Ensure string buffer does not exceed its maximum length */ if (StringLength >= MaxStringLength) { SystemLog.Printf ("ReadLine() - Maximum string length %u reached!", MaxStringLength); ReturnValue = READLINE_MSL; break; } } } while (TRUE); /* Loop is exited using break */ /* Ensure the string is NULL terminated */ if (pString != NULL) pString[StringLength] = NULL_CHAR; return (ReturnValue); } /*========================================================================= * End of Function ReadLine() *=======================================================================*/ /*========================================================================= * * Function - boolean read_int (pFileHandle, Value); * * Reads an integer from the specified file. Returns FALSE on any error * and sets the appropiate code in ErrorHandler. The size of an integer * depends on the platform compiled under. In DOS it is usually 16 bit, * in Windows it is 32 bit, etc... ASSERTs if the input handle is invalid. * *=======================================================================*/ boolean read_int (FILE* pFileHandle, int& Value) { DEFINE_FUNCTION("read_int()"); size_t InputSize; /* Make sure the file handle is valid */ ASSERT(pFileHandle != NULL); /* Read in the integer value */ InputSize = fread(&Value, 1, sizeof(int), pFileHandle); /* Check for any read error */ if (InputSize != sizeof(int)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Error reading binary integer value (read only %u of %u bytes)!", InputSize, sizeof(int)); return (FALSE); } return (TRUE); } /*========================================================================= * End of Function read_int() *=======================================================================*/ /*========================================================================= * * Function - boolean read_long (pFileHandle, Value); * * Reads a long integer from the specified file. Returns FALSE on any error * and sets the appropiate code in ErrorHandler. The size of a long may * depend on the platform compiled under, though it is usually 32 bits. * ASSERTs if the input handle is invalid. * *=======================================================================*/ boolean read_long (FILE* pFileHandle, long& Value) { DEFINE_FUNCTION("read_long()"); size_t InputSize; /* Ensure valid input */ ASSERT(pFileHandle != NULL); /* Read the value */ InputSize = fread (&Value, 1, sizeof(long), pFileHandle); /* Ensure the value was correctly read */ if (InputSize != sizeof(long)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Error reading binary long integer value (read only %u of %u bytes)!", InputSize, sizeof(long)); return (FALSE); } return (TRUE); } /*========================================================================= * End of Function read_long() *=======================================================================*/ /*========================================================================= * * Function - boolean read_short (pFileHandle, Value); * * Reads a short integer from the specified file. Returns FALSE on any error * and sets the appropiate code in ErrorHandler. The size of a short may * depend on the platform compiled under, though it is usually 16 bits. * ASSERTs if the input handle is invalid. * *=======================================================================*/ boolean read_short (FILE* pFileHandle, short& Value) { DEFINE_FUNCTION("read_short()"); size_t InputSize; /* Ensure valid input */ ASSERT(pFileHandle != NULL); /* Read in the integer value */ InputSize = fread(&Value, 1, sizeof(short), pFileHandle); /* Check for any read error */ if (InputSize != sizeof(short)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Error reading binary short integer value (read only %u of %u bytes)!", InputSize, sizeof(short)); return (FALSE); } return (TRUE); } /*========================================================================= * End of Function read_short() *=======================================================================*/ /*========================================================================= * * Function - long read_motlong (pFileHandle, Value); * * Reads a long integer from the specified file using the Motorola byte * order (as opposed to the usual Intel byte order). Returns FALSE on * any error and sets the appropiate code with ErrorHandler. A long integer * is usually 32 bit but may depend on the platform compiled under. * *=======================================================================*/ boolean read_motlong (FILE* pFileHandle, long& Value) { DEFINE_FUNCTION("read_motlong()"); unsigned char InputData[sizeof(long)]; size_t InputSize; /* Ensure valid input */ ASSERT(pFileHandle != NULL); /* Read in the integer value */ InputSize = fread(&InputData, 1, sizeof(long), pFileHandle); /* Check for any read error */ if (InputSize != sizeof(long)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Error reading binary motorola long value (read only %u of %u bytes)!", InputSize, sizeof(long)); return (FALSE); } /* Compute the proper long integer value */ Value = (long) (((unsigned long)InputData[3]) + (((unsigned long)InputData[2])<<8) + (((unsigned long)InputData[1])<<16) + (((unsigned long)InputData[0])<<24)); return (TRUE); } /*========================================================================= * End of Function read_motlong() *=======================================================================*/ /*=========================================================================== * * Function - char* RemoveExtension (pFilename); * * Removes the extension from the given filename. Returns a pointer to * the modified file string. ASSERTs if passed a bad pointer. * *=========================================================================*/ char* RemoveExtension (char* pFilename) { //DEFINE_FUNCTION("RemoveExtension()"); char* pExtPtr; /* Attempt to find the start of the file extension */ pExtPtr = FindExtension(pFilename); /* Terminate the file string at the '.' character */ if (pExtPtr != NULL) pExtPtr[-1] = NULL_CHAR; return (pFilename); } /*=========================================================================== * End of Function RemoveExtension() *=========================================================================*/ /*=========================================================================== * * Function - char* TerminatePath (char* pPath); * * Ensures the given path string terminates in the current LocalePathChar * character. Returns a pointer to the given string. ASSERTs if the * input string is invalid. Assumes that the string has been allocated * to allow an additional character to be added to it. * *=========================================================================*/ char* TerminatePath (char* pPath) { DEFINE_FUNCTION("TerminatePath()"); size_t PathLength; /* Ensure the input path is valid */ ASSERT(pPath != NULL); PathLength = strlen(pPath); /* Ensure the string ends in the current path character */ if (PathLength == 0 || pPath[PathLength-1] != LocalePathChar) { pPath[PathLength] = LocalePathChar; pPath[PathLength+1] = NULL_CHAR; } return (pPath); } /*=========================================================================== * End of Function TerminatePath() *=========================================================================*/ /*=========================================================================== * * Function - boolean WriteFile (pBuffer, Size, pFilename, TextMode); * * Outputs Size bytes from the string pBuffer to the given filename. * Returns TRUE on success or FALSE on any error, setting the appropiate * error with ErrorHandler. If TextMode is TRUE (FILE_TEXT), the file * is created in text mode, if FALSE (FILE_BINARY), the file is created * in binary mode, the default. ASSERTs if passed any invalid pointers. * The file is overwritten if it currently exists. * *=========================================================================*/ boolean WriteFile (const char* pBuffer, const size_t Size, const char* pFilename, const boolean TextMode) { DEFINE_FUNCTION("WriteFile()"); FILE* pFileHandle; size_t OutputBytes; boolean ReturnValue = TRUE; /* Ensure valid input */ ASSERT(pBuffer != NULL && pFilename != NULL); /* Attempt to open file for output */ pFileHandle = OpenFile(pFilename, TextMode ? "wt" : "wb"); if (pFileHandle == NULL) return (FALSE); /* Attempt to output string buffer to file */ OutputBytes = fwrite(pBuffer, sizeof(char), Size, pFileHandle); if (ferror(pFileHandle)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Failed to write to the file '%s' (only %u of %u bytes output)!", pFilename, OutputBytes, Size); ReturnValue = FALSE; } fclose (pFileHandle); return (ReturnValue); } /*=========================================================================== * End of Function WriteFile() *=========================================================================*/ /*========================================================================= * * Function - boolean write_short (pFileHandle, OutputValue); * * Writes a short integer to a file. Returns FALSE on any error. * The size of a short integer may depend on the system compiled in, * but usually it is 16 bits. ASSERTs if passed an invalid file * handle. * *=======================================================================*/ boolean write_short (FILE* pFileHandle, const short OutputValue) { DEFINE_FUNCTION("write_short()"); size_t OutputSize; /* Ensure valid input */ ASSERT(pFileHandle != NULL); /* Output the data */ OutputSize = fwrite(&OutputValue, 1, sizeof(short), pFileHandle); /* Ensure the data was properly output */ if (OutputSize != sizeof(short)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Error writing binary short integer to file (%u of %u bytes output)!", OutputSize, sizeof(short)); return (FALSE); } return (TRUE); } /*========================================================================= * End of Function write_short() *=======================================================================*/ /*========================================================================= * * Function - boolean write_int (pFileHandle, OutputValue); * * Writes an integer to a file. Returns FALSE on any error and sets the * appropiate error with ErrorHandler. The size of an integer depends * on the system compiled under, though usually it is 16 of 32 bits. * ASSERTs if given an invalid file handle. * *=======================================================================*/ boolean write_int (FILE* pFileHandle, const int OutputValue) { DEFINE_FUNCTION("write_int()"); size_t OutputSize; /* Ensure valid input */ ASSERT(pFileHandle != NULL); /* Output the data */ OutputSize = fwrite(&OutputValue, 1, sizeof(int), pFileHandle); /* Ensure the data was properly output */ if (OutputSize != sizeof(int)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Error writing binary integer to file (%u of %u bytes output)!", OutputSize, sizeof(int)); return (FALSE); } return (TRUE); } /*========================================================================= * End of Function write_int() *=======================================================================*/ /*========================================================================= * * Function - boolean write_long (pFileHandle, OutputValue); * * Writes a long integer to a file. Returns FALSE on any error, setting * the appropiate error code with the ErrorHandler. ASSERTs if given * an invalid file handle. Long integers are usually 32 bits in size, * but may depend on the system compiled under. * *=======================================================================*/ boolean write_long (FILE* pFileHandle, const long OutputValue) { DEFINE_FUNCTION("write_long()"); size_t OutputSize; /* Ensure valid input */ ASSERT(pFileHandle != NULL); /* Output the data */ OutputSize = fwrite(&OutputValue, 1, sizeof(long), pFileHandle); /* Ensure the data was properly output */ if (OutputSize != sizeof(long)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Error writing binary long integer to file (%u of %u bytes output)!", OutputSize, sizeof(long)); return (FALSE); } return (TRUE); } /*========================================================================= * End of Function write_long() *=======================================================================*/ /*========================================================================= * * Function - boolean write_motlong (pFileHandle, OutputValue); * * Writes a long integer to a file using the Motorola byte order (as * opposed to the usual Intel byte order). Returns FALSE on any error * and sets the appropiate error code with the ErrorHandler. ASSERTs * if given an invalid file handle. Long integers are usually 32 bits * in size, but may depend on the system compiled under. * *=======================================================================*/ boolean write_motlong (FILE* pFileHandle, const long OutputValue) { DEFINE_FUNCTION("write_motlong()"); unsigned char OutputData[sizeof(long)]; size_t OutputSize; /* Ensure valid input */ ASSERT(pFileHandle != NULL); /* Create the output buffer */ OutputData[0] = (unsigned char) ((OutputValue >> 24) & 0xFF); OutputData[1] = (unsigned char) ((OutputValue >> 16) & 0xFF); OutputData[2] = (unsigned char) ((OutputValue >> 8) & 0xFF); OutputData[3] = (unsigned char) (OutputValue & 0xFF); /* Output the data */ OutputSize = fwrite (OutputData, 1, sizeof(long), pFileHandle); /* Ensure the data was properly output */ if (OutputSize != sizeof(long)) { ErrorHandler.AddError(ERR_SYSTEM, (errcode_t)errno, "Error writing binary motorola long integer to file (%u of %u bytes output)!", OutputSize, sizeof(long)); return (FALSE); } return (TRUE); } /*========================================================================= * End of Function write_motlong() *=======================================================================*/