Initial source commit
This commit is contained in:
commit
f1384c11ee
335 changed files with 52715 additions and 0 deletions
73
minorGems/io/file/Directory.h
Normal file
73
minorGems/io/file/Directory.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2003-January-23 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
*
|
||||
* 2003-November-10 Jason Rohrer
|
||||
* Added makeDirectory function.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "minorGems/common.h"
|
||||
#include "minorGems/io/file/File.h"
|
||||
|
||||
|
||||
|
||||
#ifndef DIRECTORY_INCLUDED
|
||||
#define DIRECTORY_INCLUDED
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class of static directory functions.
|
||||
*
|
||||
* This class exists because most directory operations are
|
||||
* platform-dependent, and a large body of existing code
|
||||
* depends on a platform-independent File.h.
|
||||
*
|
||||
* @author Jason Rohrer.
|
||||
*/
|
||||
class Directory {
|
||||
|
||||
public:
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Removes a directory.
|
||||
*
|
||||
* The directory must be empty for this call to succeed.
|
||||
*
|
||||
* @param inFile the file representing the directory.
|
||||
* Must be destroyed by caller.
|
||||
*
|
||||
* @return true if the directory is removed successfully, or
|
||||
* false otherwise (for example, if the directory is not empy).
|
||||
*/
|
||||
static char removeDirectory( File *inFile );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Makes a directory.
|
||||
*
|
||||
* @param inFile the file representing the directory.
|
||||
* Must be destroyed by caller.
|
||||
*
|
||||
* @return true if the directory is removed successfully, or
|
||||
* false otherwise (for example, if the directory is not empy).
|
||||
*/
|
||||
static char makeDirectory( File *inFile );
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
994
minorGems/io/file/File.h
Normal file
994
minorGems/io/file/File.h
Normal file
|
@ -0,0 +1,994 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-February-11 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-February-25 Jason Rohrer
|
||||
* Fixed file name bugs in length and existence functions.
|
||||
*
|
||||
* 2001-May-11 Jason Rohrer
|
||||
* Added a missing include.
|
||||
*
|
||||
* 2001-November-3 Jason Rohrer
|
||||
* Added a function for checking if a file is a directory.
|
||||
* Added a function for getting the child files of a directory.
|
||||
* Added a function for getting a pathless file name.
|
||||
*
|
||||
* 2001-November-13 Jason Rohrer
|
||||
* Made name length parameter optional in constructor.
|
||||
* Made return length parameter optional in name getting functions.
|
||||
*
|
||||
* 2001-November-17 Jason Rohrer
|
||||
* Added a functions for removing a file and for copying a file.
|
||||
*
|
||||
* 2002-March-11 Jason Rohrer
|
||||
* Added destruction comment to getFullFileName().
|
||||
*
|
||||
* 2002-March-13 Jason Rohrer
|
||||
* Changed mName to be \0-terminated to fix interaction bugs with Path.
|
||||
* Fixed a missing delete.
|
||||
* Added a function for creating a directory.
|
||||
*
|
||||
* 2002-March-31 Jason Rohrer
|
||||
* Fixed some bad syntax.
|
||||
*
|
||||
* 2002-April-6 Jason Rohrer
|
||||
* Replaced use of strdup.
|
||||
*
|
||||
* 2002-April-8 Jason Rohrer
|
||||
* Fixed fopen bug.
|
||||
*
|
||||
* 2002-April-11 Jason Rohrer
|
||||
* Fixed a memory leak.
|
||||
* Fixed a casting error.
|
||||
*
|
||||
* 2002-June-28 Jason Rohrer
|
||||
* Added a function for copying a file class.
|
||||
*
|
||||
* 2002-August-3 Jason Rohrer
|
||||
* Added a function for getting the parent file.
|
||||
*
|
||||
* 2002-August-5 Jason Rohrer
|
||||
* Used an unused error variable.
|
||||
*
|
||||
* 2002-September-11 Jason Rohrer
|
||||
* Added return value to remove.
|
||||
*
|
||||
* 2003-January-27 Jason Rohrer
|
||||
* Added a function for reading file contents.
|
||||
*
|
||||
* 2003-February-3 Jason Rohrer
|
||||
* Added a function for writing a string to a file.
|
||||
*
|
||||
* 2003-March-13 Jason Rohrer
|
||||
* Added a function for getting a child file from a directory.
|
||||
*
|
||||
* 2003-June-2 Jason Rohrer
|
||||
* Fixed parent directory behavior when current file is root directory.
|
||||
* Fixed a bug in getting child files of root directory.
|
||||
*
|
||||
* 2003-November-6 Jason Rohrer
|
||||
* Added function for getting last modification time.
|
||||
*
|
||||
* 2003-November-10 Jason Rohrer
|
||||
* Changed to use platform-dependent makeDirectory function.
|
||||
*
|
||||
* 2004-January-4 Jason Rohrer
|
||||
* Added recursive child file functions.
|
||||
*
|
||||
* 2005-August-29 Jason Rohrer
|
||||
* Fixed an uninitialized variable warning.
|
||||
*
|
||||
* 2010-March-6 Jason Rohrer
|
||||
* Added versions of writeToFile readFileContents for binary data.
|
||||
*
|
||||
* 2010-April-23 Jason Rohrer
|
||||
* Fixed a string length bug when line ends are Windows.
|
||||
*
|
||||
* 2010-May-14 Jason Rohrer
|
||||
* String parameters as const to fix warnings.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#ifndef FILE_CLASS_INCLUDED
|
||||
#define FILE_CLASS_INCLUDED
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
#include "Path.h"
|
||||
|
||||
#include "minorGems/util/SimpleVector.h"
|
||||
#include "minorGems/util/stringUtils.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* File interface. Provides access to information about a
|
||||
* file.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class File {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a file.
|
||||
*
|
||||
* @param inPath the path for this file.
|
||||
* Is destroyed when this class is destroyed.
|
||||
* Pass in NULL to specify
|
||||
* no path (the current working directory).
|
||||
* @param inName the name of the file to open.
|
||||
* Must be destroyed by caller if not const.
|
||||
* Copied internally.
|
||||
* @param inNameLength length of the name in chars,
|
||||
* or -1 to use the c-string length of inName
|
||||
* (assuming that inName is \0-terminated).
|
||||
* Defaults to -1.
|
||||
*/
|
||||
File( Path *inPath, const char *inName, int inNameLength = -1 );
|
||||
|
||||
|
||||
~File();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets whether this file is a directory.
|
||||
*
|
||||
* @return true iff this file is a directory.
|
||||
*/
|
||||
char isDirectory();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Makes a directory in the location of this file.
|
||||
*
|
||||
* Can only succeed if exists() is false.
|
||||
*
|
||||
* @return true iff directory creation succeeded.
|
||||
*/
|
||||
char makeDirectory();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the files contained in this file if it is a directory.
|
||||
*
|
||||
* @param outNumFiles pointer to where the number of
|
||||
* files will be returned.
|
||||
*
|
||||
* @return an array of files, or NULL if this
|
||||
* file is not a directory, is an empty directory, or doesn't exist.
|
||||
* Must be destroyed by caller if non-NULL.
|
||||
*/
|
||||
File **getChildFiles( int *outNumFiles );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the files contained in this file if it is a directory and
|
||||
* recursively in subdirectories of this file.
|
||||
*
|
||||
* @param inDepthLimit the maximum subdirectory depth to recurse into.
|
||||
* If inDepthLimit is 0, then only child files in this directory
|
||||
* will be returned.
|
||||
* @param outNumFiles pointer to where the number of
|
||||
* files will be returned.
|
||||
*
|
||||
* @return an array of files, or NULL if this
|
||||
* file is not a directory, is an empty directory (or a directory
|
||||
* containing empty subdirectories), or doesn't exist.
|
||||
* Must be destroyed by caller if non-NULL.
|
||||
*/
|
||||
File **getChildFilesRecursive( int inDepthLimit, int *outNumFiles );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets a child of this directory.
|
||||
*
|
||||
* @param inChildFileName the name of the child file.
|
||||
* Must be destroyed by caller if non-const.
|
||||
*
|
||||
* @return the child file (even if it does not exist), or NULL if
|
||||
* this file is not a directory.
|
||||
* Must be destroyed by caller if non-NULL.
|
||||
*/
|
||||
File *getChildFile( const char *inChildFileName );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parent directory of this file.
|
||||
*
|
||||
* @return the parent directory of this file.
|
||||
* Must be destroyed by caller.
|
||||
*/
|
||||
File *getParentDirectory();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the length of this file.
|
||||
*
|
||||
* @return the length of this file in bytes. Returns
|
||||
* 0 if the file does not exist.
|
||||
*/
|
||||
long getLength();
|
||||
|
||||
|
||||
/**
|
||||
* Gets whether a file exists.
|
||||
*
|
||||
* @return true if the file exists.
|
||||
*/
|
||||
char exists();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the last modification time of this file.
|
||||
*
|
||||
* @return the modification time in seconds based on the
|
||||
* system clock. Returns 0 if the file does not exist.
|
||||
*/
|
||||
unsigned long getModificationTime();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Removes this file from the disk, if it exists.
|
||||
*
|
||||
* @return true iff the remove succeeded, false if the removal
|
||||
* fails or the file does not exist.
|
||||
*/
|
||||
char remove();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Copies this file object (does not copy the file described by
|
||||
* this object).
|
||||
*
|
||||
* @return a deep copy of this file object.
|
||||
*/
|
||||
File *copy();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Copies the contents of this file into another file.
|
||||
*
|
||||
* @param inDestination the file to copy this file into.
|
||||
* If it exists, it will be overwritten.
|
||||
* If it does not exist, it will be created.
|
||||
* Must be destroyed by caller.
|
||||
* @param inBlockSize the block size to use when copying.
|
||||
* Defaults to blocks of 5000 bytes.
|
||||
*/
|
||||
void copy( File *inDestination, long inBlockSize = 5000 );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the full-path file name sufficient
|
||||
* to access this file from the current working
|
||||
* directory.
|
||||
*
|
||||
* @param outLength pointer to where the name length, in
|
||||
* characters, will be returned. Set to NULL to ignore
|
||||
* the output length. Defaults to NULL.
|
||||
*
|
||||
* @return the full path file name for this file,
|
||||
* in platform-specific form. Must be destroyed by caller.
|
||||
* The returned string is '\0' terminated, but this
|
||||
* extra character is not included in the length.
|
||||
* Must be destroyed by caller.
|
||||
*/
|
||||
char *getFullFileName( int *outLength = NULL );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the pathless name of this file.
|
||||
*
|
||||
* @param outLength pointer to where the name length, in
|
||||
* characters, will be returned. Set to NULL to ignore
|
||||
* the output length. Defaults to NULL.
|
||||
*
|
||||
* @return the name of this file. Must be destroyed by caller.
|
||||
*/
|
||||
char *getFileName( int *outLength = NULL );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reads the contents of this file.
|
||||
*
|
||||
* @return a \0-terminated string containing the file contents,
|
||||
* or NULL if reading the file into memory failed.
|
||||
* Must be destroyed by caller.
|
||||
*/
|
||||
char *readFileContents();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reads the contents of this file.
|
||||
*
|
||||
* @param outLength pointer to where the return array length should
|
||||
* be returned.
|
||||
* @param inTextMode true to open the file as text, false as binary.
|
||||
* Defaults to false.
|
||||
*
|
||||
* @return an array containing the binary file contents,
|
||||
* or NULL if reading the file into memory failed.
|
||||
* Must be destroyed by caller.
|
||||
*/
|
||||
unsigned char *readFileContents( int *outLength,
|
||||
char inTextMode = false );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Writes a string to this file.
|
||||
*
|
||||
* @param inString the \0-terminated string to write.
|
||||
* Must be destroyed by caller if non-const.
|
||||
*
|
||||
* @return true if the file was written to successfully, or
|
||||
* false otherwise.
|
||||
*/
|
||||
char writeToFile( const char *inString );
|
||||
|
||||
|
||||
/**
|
||||
* Writes a binary data to this file.
|
||||
*
|
||||
* @param inData the data to write.
|
||||
* Must be destroyed by caller if non-const.
|
||||
* @param inLength length of inData.
|
||||
*
|
||||
* @return true if the file was written to successfully, or
|
||||
* false otherwise.
|
||||
*/
|
||||
char writeToFile( unsigned char *inData, int inLength );
|
||||
|
||||
|
||||
|
||||
private:
|
||||
Path *mPath;
|
||||
char *mName;
|
||||
int mNameLength;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the files contained in this file if it is a directory and
|
||||
* recursively in subdirectories of this file.
|
||||
*
|
||||
* @param inDepthLimit the maximum subdirectory depth to recurse into.
|
||||
* If inDepthLimit is 0, then only child files in this directory
|
||||
* will be returned.
|
||||
* @param inResultVector vector to add the discovered files to.
|
||||
* Must be destroyed by caller.
|
||||
*/
|
||||
void getChildFilesRecursive( int inDepthLimit,
|
||||
SimpleVector<File *> *inResultVector );
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline File::File( Path *inPath, const char *inName, int inNameLength )
|
||||
: mPath( inPath ), mNameLength( inNameLength ) {
|
||||
|
||||
if( inNameLength == -1 ) {
|
||||
inNameLength = strlen( inName );
|
||||
mNameLength = inNameLength;
|
||||
}
|
||||
|
||||
// copy name internally
|
||||
mName = stringDuplicate( inName );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline File::~File() {
|
||||
delete [] mName;
|
||||
|
||||
if( mPath != NULL ) {
|
||||
delete mPath;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline long File::getLength() {
|
||||
struct stat fileInfo;
|
||||
|
||||
// get full file name
|
||||
int length;
|
||||
char *stringName = getFullFileName( &length );
|
||||
|
||||
int statError = stat( stringName, &fileInfo );
|
||||
|
||||
delete [] stringName;
|
||||
|
||||
if( statError == 0 ) {
|
||||
return fileInfo.st_size;
|
||||
}
|
||||
else {
|
||||
// file does not exist
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char File::isDirectory() {
|
||||
struct stat fileInfo;
|
||||
|
||||
// get full file name
|
||||
int length;
|
||||
char *stringName = getFullFileName( &length );
|
||||
|
||||
int statError = stat( stringName, &fileInfo );
|
||||
|
||||
delete [] stringName;
|
||||
|
||||
if( statError == -1 ) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return S_ISDIR( fileInfo.st_mode );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline File **File::getChildFiles( int *outNumFiles ) {
|
||||
|
||||
int length;
|
||||
char *stringName = getFullFileName( &length );
|
||||
|
||||
DIR *directory = opendir( stringName );
|
||||
|
||||
if( directory != NULL ) {
|
||||
|
||||
SimpleVector< File* > *fileVector = new SimpleVector< File* >();
|
||||
|
||||
struct dirent *entry = readdir( directory );
|
||||
|
||||
if( entry == NULL ) {
|
||||
delete fileVector;
|
||||
|
||||
closedir( directory );
|
||||
|
||||
delete [] stringName;
|
||||
|
||||
*outNumFiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
while( entry != NULL ) {
|
||||
// skip parentdir and thisdir files, if they occur
|
||||
if( strcmp( entry->d_name, "." ) &&
|
||||
strcmp( entry->d_name, ".." ) ) {
|
||||
|
||||
Path *newPath;
|
||||
|
||||
if( mPath != NULL ) {
|
||||
newPath = mPath->append( mName );
|
||||
}
|
||||
else {
|
||||
|
||||
if( Path::isRoot( mName ) ) {
|
||||
// use name as a string path
|
||||
newPath = new Path( mName );
|
||||
}
|
||||
else {
|
||||
char **folderPathArray = new char*[1];
|
||||
folderPathArray[0] = mName;
|
||||
|
||||
// a non-absolute path to this directory's contents
|
||||
int numSteps = 1;
|
||||
char absolute = false;
|
||||
newPath =
|
||||
new Path( folderPathArray, numSteps,
|
||||
absolute );
|
||||
|
||||
delete [] folderPathArray;
|
||||
}
|
||||
}
|
||||
|
||||
// safe to pass d_name in directly because it is copied
|
||||
// internally by the constructor
|
||||
|
||||
fileVector->push_back(
|
||||
new File( newPath,
|
||||
entry->d_name,
|
||||
strlen( entry->d_name ) ) );
|
||||
}
|
||||
|
||||
entry = readdir( directory );
|
||||
}
|
||||
|
||||
// now we have a vector full of this directory's files
|
||||
int vectorSize = fileVector->size();
|
||||
|
||||
*outNumFiles = vectorSize;
|
||||
|
||||
if( vectorSize == 0 ) {
|
||||
delete fileVector;
|
||||
|
||||
closedir( directory );
|
||||
|
||||
delete [] stringName;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
File **returnFiles = new File *[vectorSize];
|
||||
for( int i=0; i<vectorSize; i++ ) {
|
||||
returnFiles[i] = *( fileVector->getElement( i ) );
|
||||
}
|
||||
|
||||
delete fileVector;
|
||||
|
||||
closedir( directory );
|
||||
|
||||
delete [] stringName;
|
||||
|
||||
return returnFiles;
|
||||
}
|
||||
}
|
||||
else {
|
||||
delete [] stringName;
|
||||
|
||||
*outNumFiles = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline File **File::getChildFilesRecursive( int inDepthLimit,
|
||||
int *outNumFiles ) {
|
||||
|
||||
// create a vector for results
|
||||
SimpleVector<File *> *resultVector = new SimpleVector<File *>();
|
||||
|
||||
// call the recursive function
|
||||
getChildFilesRecursive( inDepthLimit, resultVector );
|
||||
|
||||
|
||||
// extract results from vector
|
||||
File **resultArray = NULL;
|
||||
|
||||
int numResults = resultVector->size();
|
||||
|
||||
if( numResults > 0 ) {
|
||||
resultArray = resultVector->getElementArray();
|
||||
}
|
||||
|
||||
delete resultVector;
|
||||
|
||||
|
||||
|
||||
*outNumFiles = numResults;
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void File::getChildFilesRecursive(
|
||||
int inDepthLimit,
|
||||
SimpleVector<File *> *inResultVector ) {
|
||||
|
||||
// get our child files
|
||||
int numChildren;
|
||||
File **childFiles = getChildFiles( &numChildren );
|
||||
|
||||
if( childFiles != NULL ) {
|
||||
|
||||
// for each child, add it to vector and
|
||||
// recurse into it if it is a directory
|
||||
|
||||
for( int i=0; i<numChildren; i++ ) {
|
||||
|
||||
File *child = childFiles[i];
|
||||
|
||||
// add it to results vector
|
||||
inResultVector->push_back( child );
|
||||
|
||||
if( child->isDirectory() ) {
|
||||
// skip recursion if we have hit our depth limit
|
||||
if( inDepthLimit > 0 ) {
|
||||
// recurse into this subdirectory
|
||||
child->getChildFilesRecursive( inDepthLimit - 1,
|
||||
inResultVector );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete [] childFiles;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline File *File::getChildFile( const char *inChildFileName ) {
|
||||
// make sure we are a directory
|
||||
if( !isDirectory() ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get a path to this directory
|
||||
Path *newPath;
|
||||
|
||||
if( mPath != NULL ) {
|
||||
newPath = mPath->append( mName );
|
||||
}
|
||||
else {
|
||||
|
||||
char **folderPathArray = new char*[1];
|
||||
folderPathArray[0] = mName;
|
||||
|
||||
// a non-absolute path to this directory's contents
|
||||
int numSteps = 1;
|
||||
char absolute = false;
|
||||
newPath =
|
||||
new Path( folderPathArray, numSteps,
|
||||
absolute );
|
||||
|
||||
delete [] folderPathArray;
|
||||
}
|
||||
|
||||
return new File( newPath, inChildFileName );
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline File *File::getParentDirectory() {
|
||||
|
||||
if( mPath != NULL ) {
|
||||
|
||||
char *parentName;
|
||||
|
||||
Path *parentPath;
|
||||
|
||||
if( strcmp( mName, ".." ) == 0 ) {
|
||||
// already a parent dir reference
|
||||
// append one more parent dir reference with parentName below
|
||||
parentPath = mPath->append( ".." );
|
||||
|
||||
parentName = stringDuplicate( ".." );
|
||||
}
|
||||
else {
|
||||
// not a parent dir reference, so we can truncate
|
||||
parentPath = mPath->truncate();
|
||||
|
||||
parentName = mPath->getLastStep();
|
||||
}
|
||||
|
||||
File *parentFile = new File( parentPath, parentName );
|
||||
|
||||
delete [] parentName;
|
||||
|
||||
return parentFile;
|
||||
}
|
||||
else {
|
||||
if( Path::isRoot( mName ) ) {
|
||||
// we are already at the root
|
||||
return new File( NULL, mName );
|
||||
}
|
||||
else {
|
||||
// append parent dir symbol to path
|
||||
char **parentPathSteps = new char*[1];
|
||||
parentPathSteps[0] = mName;
|
||||
|
||||
Path *parentPath = new Path( parentPathSteps, 1, false );
|
||||
|
||||
const char *parentName = "..";
|
||||
|
||||
File *parentFile = new File( parentPath, parentName );
|
||||
|
||||
delete [] parentPathSteps;
|
||||
|
||||
return parentFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char File::exists() {
|
||||
struct stat fileInfo;
|
||||
|
||||
// get full file name
|
||||
int length;
|
||||
char *stringName = getFullFileName( &length );
|
||||
|
||||
int statError = stat( stringName, &fileInfo );
|
||||
|
||||
delete [] stringName;
|
||||
|
||||
if( statError == 0 ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// file does not exist
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline unsigned long File::getModificationTime() {
|
||||
struct stat fileInfo;
|
||||
|
||||
// get full file name
|
||||
int length;
|
||||
char *stringName = getFullFileName( &length );
|
||||
|
||||
int statError = stat( stringName, &fileInfo );
|
||||
|
||||
delete [] stringName;
|
||||
|
||||
if( statError == 0 ) {
|
||||
return fileInfo.st_mtime;
|
||||
}
|
||||
else {
|
||||
// file does not exist
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char File::remove() {
|
||||
char returnVal = false;
|
||||
|
||||
if( exists() ) {
|
||||
char *stringName = getFullFileName();
|
||||
|
||||
int error = ::remove( stringName );
|
||||
|
||||
if( error == 0 ) {
|
||||
returnVal = true;
|
||||
}
|
||||
|
||||
delete [] stringName;
|
||||
}
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline File *File::copy() {
|
||||
Path *pathCopy = NULL;
|
||||
|
||||
if( mPath != NULL ) {
|
||||
pathCopy = mPath->copy();
|
||||
}
|
||||
|
||||
return new File( pathCopy, mName );
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void File::copy( File *inDestination, long inBlockSize ) {
|
||||
char *thisFileName = getFullFileName();
|
||||
char *destinationFileName = inDestination->getFullFileName();
|
||||
|
||||
FILE *thisFile = fopen( thisFileName, "rb" );
|
||||
FILE *destinationFile = fopen( destinationFileName, "wb" );
|
||||
|
||||
long length = getLength();
|
||||
|
||||
long bytesCopied = 0;
|
||||
|
||||
char *buffer = new char[ inBlockSize ];
|
||||
|
||||
while( bytesCopied < length ) {
|
||||
|
||||
long bytesToCopy = inBlockSize;
|
||||
|
||||
// end of file case
|
||||
if( length - bytesCopied < bytesToCopy ) {
|
||||
bytesToCopy = length - bytesCopied;
|
||||
}
|
||||
|
||||
fread( buffer, 1, bytesToCopy, thisFile );
|
||||
fwrite( buffer, 1, bytesToCopy, destinationFile );
|
||||
|
||||
bytesCopied += bytesToCopy;
|
||||
}
|
||||
|
||||
fclose( thisFile );
|
||||
fclose( destinationFile );
|
||||
|
||||
delete [] buffer;
|
||||
delete [] thisFileName;
|
||||
delete [] destinationFileName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char *File::getFileName( int *outLength ) {
|
||||
char *returnName = stringDuplicate( mName );
|
||||
|
||||
if( outLength != NULL ) {
|
||||
*outLength = mNameLength;
|
||||
}
|
||||
|
||||
return returnName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char *File::getFullFileName( int *outLength ) {
|
||||
int length = mNameLength;
|
||||
|
||||
int pathLength = 0;
|
||||
char *path = NULL;
|
||||
if( mPath != NULL ) {
|
||||
path = mPath->getPathString( &pathLength );
|
||||
|
||||
length += pathLength;
|
||||
}
|
||||
|
||||
// extra character for '\0' termination
|
||||
char *returnString = new char[ length + 1 ];
|
||||
|
||||
if( path != NULL ) {
|
||||
memcpy( returnString, path, pathLength );
|
||||
memcpy( &( returnString[pathLength] ), mName, mNameLength );
|
||||
|
||||
delete [] path;
|
||||
}
|
||||
else {
|
||||
// no path, so copy the name directly in
|
||||
memcpy( returnString, mName, mNameLength );
|
||||
}
|
||||
|
||||
// terminate the string
|
||||
returnString[ length ] = '\0';
|
||||
|
||||
|
||||
if( outLength != NULL ) {
|
||||
*outLength = length;
|
||||
}
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "minorGems/io/file/FileInputStream.h"
|
||||
#include "minorGems/io/file/FileOutputStream.h"
|
||||
|
||||
|
||||
|
||||
inline char *File::readFileContents() {
|
||||
|
||||
int length;
|
||||
// text mode!
|
||||
unsigned char *data = readFileContents( &length, true );
|
||||
|
||||
if( data == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *dataString = new char[ length + 1 ];
|
||||
|
||||
memcpy( dataString, data, length );
|
||||
dataString[ length ] = '\0';
|
||||
|
||||
delete [] data;
|
||||
return dataString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline unsigned char *File::readFileContents( int *outLength,
|
||||
char inTextMode ) {
|
||||
|
||||
if( exists() ) {
|
||||
int length = getLength();
|
||||
|
||||
unsigned char *returnData = new unsigned char[ length ];
|
||||
|
||||
if( returnData != NULL ) {
|
||||
FileInputStream *input = new FileInputStream( this, inTextMode );
|
||||
int numRead = input->read( returnData, length );
|
||||
|
||||
delete input;
|
||||
|
||||
// in text mode, read length might not equal binary file length,
|
||||
// due to line end conversion
|
||||
if( numRead == length ||
|
||||
( inTextMode && numRead >= 0 ) ) {
|
||||
*outLength = numRead;
|
||||
return returnData;
|
||||
}
|
||||
else {
|
||||
delete [] returnData;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// failed to allocate this much memory
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char File::writeToFile( const char *inString ) {
|
||||
return writeToFile( (unsigned char *)inString, strlen( inString ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char File::writeToFile( unsigned char *inData, int inLength ) {
|
||||
FileOutputStream *output = new FileOutputStream( this );
|
||||
|
||||
long numWritten = output->write( inData, inLength );
|
||||
|
||||
delete output;
|
||||
|
||||
if( inLength == numWritten ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "Directory.h"
|
||||
|
||||
|
||||
|
||||
inline char File::makeDirectory() {
|
||||
if( exists() ) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return Directory::makeDirectory( this );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
183
minorGems/io/file/FileInputStream.h
Normal file
183
minorGems/io/file/FileInputStream.h
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-February-11 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-April-12 Jason Rohrer
|
||||
* Changed so that File is not destroyed when this stream is destroyed.
|
||||
*
|
||||
* 2001-April-29 Jason Rohrer
|
||||
* Fixed a bug in the use of fread
|
||||
* (num elements and element size swapped).
|
||||
* Fixed a memory leak in the error message handling.
|
||||
*
|
||||
* 2006-November-23 Jason Rohrer
|
||||
* Fixed a memory leak in error message handling.
|
||||
*
|
||||
* 2010-April-22 Jason Rohrer
|
||||
* Added support for text mode.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#ifndef FILE_INPUT_STREAM_CLASS_INCLUDED
|
||||
#define FILE_INPUT_STREAM_CLASS_INCLUDED
|
||||
|
||||
#include "minorGems/io/InputStream.h"
|
||||
#include "File.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* File implementation of an InputStream.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class FileInputStream : public InputStream {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs an input stream.
|
||||
*
|
||||
* @param inFile the file to open for reading.
|
||||
* If the file does not exist, all calls to read will fail.
|
||||
* inFile is NOT destroyed when this class is destroyed.
|
||||
* @param inTextMode true to open the file as text, false as binary.
|
||||
* Defaults to false.
|
||||
*/
|
||||
FileInputStream( File *inFile, char inTextMode = false );
|
||||
|
||||
|
||||
/**
|
||||
* Destroys this stream and closes the file.
|
||||
*/
|
||||
~FileInputStream();
|
||||
|
||||
|
||||
/**
|
||||
* Gets the file attached to this stream.
|
||||
*
|
||||
* @return the file used by this stream.
|
||||
* Should not be modified or destroyed by caller until after
|
||||
* this class is destroyed.
|
||||
*/
|
||||
File *getFile();
|
||||
|
||||
|
||||
// implementst InputStream interface
|
||||
virtual long read( unsigned char *inBuffer, long inNumBytes );
|
||||
|
||||
private:
|
||||
File *mFile;
|
||||
|
||||
FILE *mUnderlyingFile;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
inline FileInputStream::FileInputStream( File *inFile, char inTextMode )
|
||||
: mFile( inFile ) {
|
||||
|
||||
int fileNameLength;
|
||||
|
||||
char *fileName = mFile->getFullFileName( &fileNameLength );
|
||||
|
||||
if( inTextMode ) {
|
||||
mUnderlyingFile = fopen( fileName, "r" );
|
||||
}
|
||||
else {
|
||||
mUnderlyingFile = fopen( fileName, "rb" );
|
||||
}
|
||||
|
||||
|
||||
if( mUnderlyingFile == NULL ) {
|
||||
// file open failed.
|
||||
|
||||
char *stringBuffer = new char[ fileNameLength + 50 ];
|
||||
sprintf( stringBuffer, "Opening file %s failed.", fileName );
|
||||
setNewLastError( stringBuffer );
|
||||
}
|
||||
|
||||
delete [] fileName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline FileInputStream::~FileInputStream() {
|
||||
if( mUnderlyingFile != NULL ) {
|
||||
fclose( mUnderlyingFile );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline File *FileInputStream::getFile() {
|
||||
return mFile;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline long FileInputStream::read(
|
||||
unsigned char *inBuffer, long inNumBytes ) {
|
||||
|
||||
if( mUnderlyingFile != NULL ) {
|
||||
|
||||
long numRead = fread( inBuffer, 1, inNumBytes, mUnderlyingFile );
|
||||
|
||||
if( numRead < inNumBytes ) {
|
||||
|
||||
int fileNameLength;
|
||||
char *fileName = mFile->getFullFileName( &fileNameLength );
|
||||
|
||||
if( feof( mUnderlyingFile ) ) {
|
||||
// we reached the end of the file.
|
||||
char *stringBuffer = new char[ fileNameLength + 50 ];
|
||||
sprintf( stringBuffer, "Reached end of file %s on read.",
|
||||
fileName );
|
||||
setNewLastError( stringBuffer );
|
||||
|
||||
delete [] fileName;
|
||||
}
|
||||
else {
|
||||
// some other kind of error occured
|
||||
char *stringBuffer = new char[ fileNameLength + 50 ];
|
||||
sprintf( stringBuffer, "Reading from file %s failed.",
|
||||
fileName );
|
||||
setNewLastError( stringBuffer );
|
||||
|
||||
delete [] fileName;
|
||||
|
||||
if( numRead == 0 ) {
|
||||
// a complete read failure
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return numRead;
|
||||
}
|
||||
else {
|
||||
// file was not opened properly
|
||||
|
||||
int fileNameLength;
|
||||
char *fileName = mFile->getFullFileName( &fileNameLength );
|
||||
char *stringBuffer = new char[ fileNameLength + 50 ];
|
||||
sprintf( stringBuffer,
|
||||
"File %s was not opened properly before reading.",
|
||||
fileName );
|
||||
delete [] fileName;
|
||||
|
||||
setNewLastError( stringBuffer );
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
175
minorGems/io/file/FileOutputStream.h
Normal file
175
minorGems/io/file/FileOutputStream.h
Normal file
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-February-11 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-April-12 Jason Rohrer
|
||||
* Changed so that File is not destroyed when this stream is destroyed.
|
||||
*
|
||||
* 2001-April-29 Jason Rohrer
|
||||
* Fixed a bug in the use of fwrite
|
||||
* (num elements and element size swapped).
|
||||
* Fixed a memory leak in the error message handling.
|
||||
*
|
||||
* 2006-August-22 Jason Rohrer
|
||||
* Fixed include order bug.
|
||||
*
|
||||
* 2010-April-6 Jason Rohrer
|
||||
* Fixed memory leak.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
#include "File.h"
|
||||
|
||||
|
||||
#ifndef FILE_OUTPUT_STREAM_CLASS_INCLUDED
|
||||
#define FILE_OUTPUT_STREAM_CLASS_INCLUDED
|
||||
|
||||
#include "minorGems/io/OutputStream.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* File implementation of an OutputStream.
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class FileOutputStream : public OutputStream {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs an output stream.
|
||||
*
|
||||
* @param inFile the file to open for writing.
|
||||
* If the file does not exist, it will be created.
|
||||
* inFile is NOT destroyed when this class is destroyed.
|
||||
* @param inAppend set to true to append to file. If
|
||||
* file does not exist, file is still created. Defaults
|
||||
* to false.
|
||||
*/
|
||||
FileOutputStream( File *inFile, char inAppend = false );
|
||||
|
||||
|
||||
/**
|
||||
* Destroys this stream and closes the file.
|
||||
*/
|
||||
~FileOutputStream();
|
||||
|
||||
|
||||
/**
|
||||
* Gets the file attached to this stream.
|
||||
*
|
||||
* @return the file used by this stream.
|
||||
* Should not be modified or destroyed by caller until after
|
||||
* this class is destroyed.
|
||||
*/
|
||||
File *getFile();
|
||||
|
||||
|
||||
// implementst OutputStream interface
|
||||
virtual long write( unsigned char *inBuffer, long inNumBytes );
|
||||
|
||||
private:
|
||||
File *mFile;
|
||||
|
||||
FILE *mUnderlyingFile;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
inline FileOutputStream::FileOutputStream( File *inFile,
|
||||
char inAppend )
|
||||
: mFile( inFile ) {
|
||||
|
||||
int fileNameLength;
|
||||
|
||||
char *fileName = mFile->getFullFileName( &fileNameLength );
|
||||
|
||||
if( inAppend ) {
|
||||
mUnderlyingFile = fopen( fileName, "ab" );
|
||||
}
|
||||
else {
|
||||
mUnderlyingFile = fopen( fileName, "wb" );
|
||||
}
|
||||
|
||||
if( mUnderlyingFile == NULL ) {
|
||||
// file open failed.
|
||||
|
||||
char *stringBuffer = new char[ fileNameLength + 50 ];
|
||||
sprintf( stringBuffer, "Opening file %s failed.", fileName );
|
||||
setNewLastError( stringBuffer );
|
||||
}
|
||||
|
||||
delete [] fileName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline FileOutputStream::~FileOutputStream() {
|
||||
if( mUnderlyingFile != NULL ) {
|
||||
fclose( mUnderlyingFile );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline File *FileOutputStream::getFile() {
|
||||
return mFile;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline long FileOutputStream::write(
|
||||
unsigned char *inBuffer, long inNumBytes ) {
|
||||
|
||||
if( mUnderlyingFile != NULL ) {
|
||||
|
||||
long numWritten =
|
||||
fwrite( inBuffer, 1, inNumBytes, mUnderlyingFile );
|
||||
|
||||
if( numWritten < inNumBytes ) {
|
||||
int fileNameLength;
|
||||
char *fileName = mFile->getFullFileName( &fileNameLength );
|
||||
|
||||
// some other kind of error occured
|
||||
char *stringBuffer = new char[ fileNameLength + 50 ];
|
||||
sprintf( stringBuffer, "Writing to file %s failed.",
|
||||
fileName );
|
||||
setNewLastError( stringBuffer );
|
||||
|
||||
delete [] fileName;
|
||||
|
||||
if( numWritten == 0 ) {
|
||||
// a complete write failure
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return numWritten;
|
||||
}
|
||||
else {
|
||||
// file was not opened properly
|
||||
|
||||
int fileNameLength;
|
||||
char *fileName = mFile->getFullFileName( &fileNameLength );
|
||||
char *stringBuffer = new char[ fileNameLength + 50 ];
|
||||
sprintf( stringBuffer,
|
||||
"File %s was not opened properly before writing.",
|
||||
fileName );
|
||||
|
||||
delete [] fileName;
|
||||
|
||||
setNewLastError( stringBuffer );
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
615
minorGems/io/file/Path.h
Normal file
615
minorGems/io/file/Path.h
Normal file
|
@ -0,0 +1,615 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-February-12 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-May-11 Jason Rohrer
|
||||
* Added a version of getPathString that
|
||||
* returns a '\0' terminated string.
|
||||
*
|
||||
* 2001-September-21 Jason Rohrer
|
||||
* Added a missing include.
|
||||
*
|
||||
* 2001-September-23 Jason Rohrer
|
||||
* Added a copy function.
|
||||
* Made some comments more explicit.
|
||||
* Changed the constructor to allow for const path step strings.
|
||||
*
|
||||
* 2001-November-3 Jason Rohrer
|
||||
* Added a function for appending a string to a path.
|
||||
* Changed the interface to the main constructor.
|
||||
*
|
||||
* 2002-March-29 Jason Rohrer
|
||||
* Added Fortify inclusion.
|
||||
*
|
||||
* 2002-April-11 Jason Rohrer
|
||||
* Fixed a variable scoping bug.
|
||||
*
|
||||
* 2002-July-2 Jason Rohrer
|
||||
* Fixed a major memory leak in copy().
|
||||
*
|
||||
* 2002-August-1 Jason Rohrer
|
||||
* Added support for path truncation.
|
||||
* Added support for parsing platform-dependent path strings.
|
||||
*
|
||||
* 2003-May-29 Jason Rohrer
|
||||
* Fixed a bug when an extra delimeters are at the end of the path.
|
||||
* Fixed a bug when string path consists only of root.
|
||||
*
|
||||
* 2003-June-2 Jason Rohrer
|
||||
* Fixed a bug in absolute path detection.
|
||||
* Added platform-specific functions for root and absolute path detection.
|
||||
* Fixed a memory bug when string path contains root only.
|
||||
* Fixed a path step bug when path is root.
|
||||
* Fixed bugs in truncate and append when non-default root string is used.
|
||||
*
|
||||
* 2005-August-29 Jason Rohrer
|
||||
* Fixed an uninitialized variable warning.
|
||||
*
|
||||
* 2010-May-14 Jason Rohrer
|
||||
* String parameters as const to fix warnings.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
#ifndef PATH_CLASS_INCLUDED
|
||||
#define PATH_CLASS_INCLUDED
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
#include "minorGems/util/stringUtils.h"
|
||||
|
||||
|
||||
|
||||
#ifdef FORTIFY
|
||||
#include "minorGems/util/development/fortify/fortify.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Platform-independent file path interface. Contains
|
||||
* all of path except for file name. Thus, appending
|
||||
* a file name to the path will produce a complete file path.
|
||||
*
|
||||
* E.g., on Linux, file path:
|
||||
* temp/files/
|
||||
* file name:
|
||||
* test.txt
|
||||
* full path:
|
||||
* temp/files/test.txt
|
||||
*
|
||||
* @author Jason Rohrer
|
||||
*/
|
||||
class Path {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a path.
|
||||
*
|
||||
* @param inPathSteps an array of c-strings representing
|
||||
* each step in the path, with no delimeters.
|
||||
* For example, { "temp", "files" } to represent
|
||||
* the linux path temp/files.
|
||||
* Must be destroyed by caller since copied internally.
|
||||
* @param inNumSteps the number of strings in the path.
|
||||
* @param inAbsolute set to true to make this an absolute
|
||||
* path. For example, in Linux, an absolute path
|
||||
* is one that starts with '/', as in /usr/include/.
|
||||
* The effects of inAbsolute vary by platform.
|
||||
* @param inRootString the root string for this path if it
|
||||
* is absolute, or NULL to specify a default root.
|
||||
* Defaults to NULL.
|
||||
* Must be destroyed by caller if non-NULL.
|
||||
*/
|
||||
Path( char **inPathSteps, int inNumSteps, char inAbsolute,
|
||||
char *inRootString = NULL );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a path by parsing a platform-dependent path string.
|
||||
*
|
||||
* @param inPathSteps a \0-terminated string representing the path.
|
||||
* Must be destroyed by caller.
|
||||
*/
|
||||
Path( const char *inPathString );
|
||||
|
||||
|
||||
|
||||
~Path();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a complete, platform-dependent string path.
|
||||
*
|
||||
* @param outLength pointer to where the path length, in
|
||||
* characters, will be returned.
|
||||
*
|
||||
* @return a new char array containing the path. Note
|
||||
* that the string is not terminated by '\0'. Must
|
||||
* be destroyed by the caller.
|
||||
*/
|
||||
char *getPathString( int *outLength );
|
||||
|
||||
|
||||
/**
|
||||
* Returns a complete, platform-dependent string path, terminated
|
||||
* bye '\0'.
|
||||
*
|
||||
* @return a new char array containing the path. Note
|
||||
* that the string IS terminated by '\0'. Must
|
||||
* be destroyed by the caller.
|
||||
*/
|
||||
char *getPathStringTerminated();
|
||||
|
||||
|
||||
/**
|
||||
* Gets the platform-specific path delimeter.
|
||||
*
|
||||
* Note that this function is implemented separately for
|
||||
* each supported platform.
|
||||
*
|
||||
* @return the path delimeter.
|
||||
*/
|
||||
static char getDelimeter();
|
||||
|
||||
|
||||
/**
|
||||
* Gets start characters for an absolute path.
|
||||
*
|
||||
* Note that this function is implemented separately for
|
||||
* each supported platform.
|
||||
*
|
||||
* @param outLength pointer to where the string length, in
|
||||
* characters, will be returned.
|
||||
*
|
||||
* @return the absolute path start string characters. For
|
||||
* example, on Linux, this would be the string "/".
|
||||
* Must be destroyed by the caller.
|
||||
*/
|
||||
static char *getAbsoluteRoot( int *outLength );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets whether a path string is absolute.
|
||||
*
|
||||
* Note that this function is implemented separately for
|
||||
* each supported platform.
|
||||
*
|
||||
* @param inPathString the string to check.
|
||||
* Must be destroyed by caller if non-const.
|
||||
*
|
||||
* @return true if the string is absolute, or false otherwise.
|
||||
*/
|
||||
static char isAbsolute( const char *inPathString );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Extracts the root string from a path string.
|
||||
*
|
||||
*
|
||||
* @param inPathString the string to check.
|
||||
* Must be destroyed by caller if non-const.
|
||||
*
|
||||
* @return the root string, or NULL if inPathString is not
|
||||
* absolute. Must be destroyed by caller if non-NULL.
|
||||
*/
|
||||
static char *extractRoot( const char *inPathString );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets whether a path string is a root path.
|
||||
*
|
||||
* Note that this function is implemented separately for
|
||||
* each supported platform. For example, on Unix, only "/"
|
||||
* is the root path, while on Windows, both "c:\" and "d:\" might
|
||||
* be root paths.
|
||||
*
|
||||
* @param inPathString the string to check.
|
||||
* Must be destroyed by caller if non-const.
|
||||
*
|
||||
* @return true if the string is a root string, or false otherwise.
|
||||
*/
|
||||
static char isRoot( const char *inPathString );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets start string for an absolute path.
|
||||
*
|
||||
* @return the absolute path start string in \0-terminated form.
|
||||
* Must be destroyed by the caller.
|
||||
*/
|
||||
static char *getAbsoluteRootString();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Copies this path.
|
||||
*
|
||||
* @return a new path that is a deep copy of this path.
|
||||
*/
|
||||
Path *copy();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new path by appending an additional
|
||||
* step onto this path.
|
||||
*
|
||||
* @param inStepString the step to add to this path.
|
||||
* Must be destroyed by caller if non-const.
|
||||
*
|
||||
* @return a new path with the extra step.
|
||||
* Must be destroyed by caller.
|
||||
*/
|
||||
Path *append( const char *inStepString );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new path by removing the last step from this path.
|
||||
*
|
||||
* @return a new path, or NULL if there is only one step in this path.
|
||||
* Must be destroyed by caller.
|
||||
*/
|
||||
Path *truncate();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the last step in this path.
|
||||
*
|
||||
* @return the last step. Must be destroyed by caller.
|
||||
*/
|
||||
char *getLastStep();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
char **mPathSteps;
|
||||
int mNumSteps;
|
||||
int *mStepLength;
|
||||
char mAbsolute;
|
||||
|
||||
// the root string of this path, if it is absolute
|
||||
char *mRootString;
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline Path::Path( char **inPathSteps, int inNumSteps,
|
||||
char inAbsolute, char *inRootString )
|
||||
: mNumSteps( inNumSteps ), mAbsolute( inAbsolute ),
|
||||
mRootString( NULL ) {
|
||||
|
||||
if( inRootString != NULL ) {
|
||||
mRootString = stringDuplicate( inRootString );
|
||||
}
|
||||
|
||||
// copy the path steps
|
||||
|
||||
mPathSteps = new char*[ mNumSteps ];
|
||||
mStepLength = new int[ mNumSteps ];
|
||||
|
||||
for( int i=0; i<mNumSteps; i++ ) {
|
||||
int stepLength = strlen( inPathSteps[i] );
|
||||
|
||||
mPathSteps[i] = new char[ stepLength + 1 ];
|
||||
memcpy( mPathSteps[i], inPathSteps[i], stepLength + 1 );
|
||||
|
||||
mStepLength[i] = stepLength;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Path::Path( const char *inPathString ) {
|
||||
mAbsolute = isAbsolute( inPathString );
|
||||
|
||||
|
||||
char *pathStringCopy = stringDuplicate( inPathString );
|
||||
|
||||
char delimeter = getDelimeter();
|
||||
|
||||
char *delimString = new char[ 2 ];
|
||||
delimString[0] = delimeter;
|
||||
delimString[1] = '\0';
|
||||
|
||||
|
||||
char *pathRootSkipped;
|
||||
|
||||
if( !mAbsolute ) {
|
||||
mRootString = NULL;
|
||||
pathRootSkipped = pathStringCopy;
|
||||
}
|
||||
else {
|
||||
// root occurs at start of path string
|
||||
|
||||
mRootString = extractRoot( inPathString );
|
||||
pathRootSkipped = &( pathStringCopy[ strlen( mRootString ) ] );
|
||||
}
|
||||
|
||||
|
||||
// remove any trailing delimeters, if they exist
|
||||
while( pathRootSkipped[ strlen( pathRootSkipped ) - 1 ] == delimeter ) {
|
||||
pathRootSkipped[ strlen( pathRootSkipped ) - 1 ] = '\0';
|
||||
}
|
||||
|
||||
char *currentDelimPointer = strstr( pathRootSkipped, delimString );
|
||||
|
||||
if( currentDelimPointer != NULL ) {
|
||||
|
||||
// first, count the delimeters
|
||||
|
||||
int delimCount = 0;
|
||||
while( currentDelimPointer != NULL ) {
|
||||
if( strlen( currentDelimPointer ) > 1 ) {
|
||||
// don't count tail end delimeters
|
||||
delimCount++;
|
||||
}
|
||||
currentDelimPointer = strstr( &( currentDelimPointer[1] ),
|
||||
delimString );
|
||||
}
|
||||
|
||||
|
||||
// no delimeter at end of path
|
||||
mNumSteps = delimCount + 1;
|
||||
|
||||
mPathSteps = new char*[ mNumSteps ];
|
||||
mStepLength = new int[ mNumSteps ];
|
||||
|
||||
|
||||
// now extract the chars between delimeters as path steps
|
||||
currentDelimPointer = strstr( pathRootSkipped, delimString );
|
||||
|
||||
int stepIndex = 0;
|
||||
|
||||
currentDelimPointer[0] = '\0';
|
||||
|
||||
mPathSteps[ stepIndex ] = stringDuplicate( pathRootSkipped );
|
||||
mStepLength[ stepIndex ] = strlen( mPathSteps[ stepIndex ] );
|
||||
stepIndex++;
|
||||
|
||||
while( currentDelimPointer != NULL ) {
|
||||
|
||||
char *nextDelimPointer = strstr( &( currentDelimPointer[1] ),
|
||||
delimString );
|
||||
|
||||
if( nextDelimPointer != NULL ) {
|
||||
nextDelimPointer[0] = '\0';
|
||||
}
|
||||
|
||||
mPathSteps[ stepIndex ] =
|
||||
stringDuplicate( &( currentDelimPointer[1] ) );
|
||||
mStepLength[ stepIndex ] = strlen( mPathSteps[ stepIndex ] );
|
||||
|
||||
stepIndex++;
|
||||
|
||||
currentDelimPointer = nextDelimPointer;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// no delimeters
|
||||
|
||||
if( strlen( pathRootSkipped ) > 0 ) {
|
||||
mNumSteps = 1;
|
||||
mPathSteps = new char*[1];
|
||||
mPathSteps[0] = stringDuplicate( pathRootSkipped );
|
||||
|
||||
mStepLength = new int[1];
|
||||
|
||||
mStepLength[0] = strlen( mPathSteps[0] );
|
||||
}
|
||||
else {
|
||||
// path with root only
|
||||
mNumSteps = 0;
|
||||
mPathSteps = new char*[0];
|
||||
mStepLength = new int[0];
|
||||
}
|
||||
}
|
||||
|
||||
delete [] delimString;
|
||||
|
||||
delete [] pathStringCopy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Path::~Path() {
|
||||
// delete each step
|
||||
for( int i=0; i<mNumSteps; i++ ) {
|
||||
delete [] mPathSteps[i];
|
||||
}
|
||||
delete [] mPathSteps;
|
||||
|
||||
delete [] mStepLength;
|
||||
|
||||
if( mRootString != NULL ) {
|
||||
delete [] mRootString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char *Path::getPathString( int *outLength ) {
|
||||
int length = 0;
|
||||
// length = sum( length each step string + 1 )
|
||||
// ( + 1 is for the delimeter that occurs after each step string )
|
||||
int i;
|
||||
for( i=0; i<mNumSteps; i++ ) {
|
||||
length += mStepLength[i] + 1;
|
||||
}
|
||||
// if absolute, we need to add in the length of the root
|
||||
char *rootString = NULL;
|
||||
int rootLength = 0;
|
||||
if( mAbsolute ) {
|
||||
if( mRootString != NULL ) {
|
||||
rootString = stringDuplicate( mRootString );
|
||||
rootLength = strlen( mRootString );
|
||||
}
|
||||
else {
|
||||
rootString = getAbsoluteRoot( &rootLength );
|
||||
}
|
||||
length += rootLength;
|
||||
}
|
||||
|
||||
char *returnString = new char[ length ];
|
||||
int index = 0;
|
||||
|
||||
if( rootString != NULL ) {
|
||||
// write root into string
|
||||
memcpy( &( returnString[index] ), rootString, rootLength );
|
||||
index += rootLength;
|
||||
|
||||
delete [] rootString;
|
||||
}
|
||||
|
||||
char delimeter = getDelimeter();
|
||||
|
||||
// write each step into the string
|
||||
for( i=0; i<mNumSteps; i++ ) {
|
||||
memcpy( &( returnString[index] ), mPathSteps[i], mStepLength[i] );
|
||||
index += mStepLength[i];
|
||||
returnString[ index ] = delimeter;
|
||||
index++;
|
||||
}
|
||||
|
||||
*outLength = length;
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char *Path::getPathStringTerminated() {
|
||||
int length;
|
||||
|
||||
char *pathString = getPathString( &length );
|
||||
|
||||
char *delimitedPathString = new char[ length + 1 ];
|
||||
memcpy( delimitedPathString, pathString, length );
|
||||
|
||||
delimitedPathString[ length ] = '\0';
|
||||
|
||||
|
||||
delete [] pathString;
|
||||
|
||||
return delimitedPathString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Path *Path::copy() {
|
||||
|
||||
// the steps will be copied internally
|
||||
return new Path( mPathSteps, mNumSteps, mAbsolute, mRootString );
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Path *Path::append( const char *inStepString ) {
|
||||
char **newPathSteps = new char*[ mNumSteps + 1 ];
|
||||
|
||||
// shallow copy, since the strings themselves
|
||||
// are copied in the Path constructor below
|
||||
for( int i=0; i<mNumSteps; i++ ) {
|
||||
newPathSteps[i] = mPathSteps[i];
|
||||
}
|
||||
|
||||
// append final step
|
||||
newPathSteps[ mNumSteps ] = (char*)inStepString;
|
||||
|
||||
Path *newPath = new Path( newPathSteps, mNumSteps + 1, mAbsolute,
|
||||
mRootString );
|
||||
|
||||
// shallow delete, because of shallow copy above
|
||||
delete [] newPathSteps;
|
||||
|
||||
|
||||
return newPath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Path *Path::truncate() {
|
||||
|
||||
if( mNumSteps < 2 && !mAbsolute ) {
|
||||
return NULL;
|
||||
}
|
||||
else if( mNumSteps < 1 ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char **newPathSteps = new char*[ mNumSteps ];
|
||||
|
||||
// shallow copy, since the strings themselves
|
||||
// are copied in the Path constructor below
|
||||
for( int i=0; i<mNumSteps-1; i++ ) {
|
||||
newPathSteps[i] = mPathSteps[i];
|
||||
}
|
||||
|
||||
Path *newPath = new Path( newPathSteps, mNumSteps - 1, mAbsolute,
|
||||
mRootString );
|
||||
|
||||
// shallow delete, because of shallow copy above
|
||||
delete [] newPathSteps;
|
||||
|
||||
|
||||
return newPath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char *Path::getLastStep() {
|
||||
if( mNumSteps >= 1 ) {
|
||||
return stringDuplicate( mPathSteps[ mNumSteps - 1 ] );
|
||||
}
|
||||
else {
|
||||
if( mAbsolute ) {
|
||||
if( mRootString != NULL ) {
|
||||
return stringDuplicate( mRootString );
|
||||
}
|
||||
else {
|
||||
return getAbsoluteRootString();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no path steps and not absolute...
|
||||
return stringDuplicate( "" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline char *Path::getAbsoluteRootString() {
|
||||
int rootLength;
|
||||
char *root = getAbsoluteRoot( &rootLength );
|
||||
|
||||
char *rootString = new char[ rootLength + 1 ];
|
||||
strncpy( rootString, root, rootLength );
|
||||
// strncopy won't add termination if length limit reached
|
||||
rootString[ rootLength ] = '\0';
|
||||
|
||||
delete [] root;
|
||||
return rootString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
138
minorGems/io/file/UniversalFileIO.h
Normal file
138
minorGems/io/file/UniversalFileIO.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
// Jason Rohrer
|
||||
// UniversalFileIO.h
|
||||
|
||||
/**
|
||||
*
|
||||
* Object that handles universal file reading and writing
|
||||
* Writes files as big endian, even on little endian machines
|
||||
*
|
||||
* Assumes that longs and floats are 32-bits
|
||||
*
|
||||
* Created 1-12-99
|
||||
* Mods:
|
||||
* Jason Rohrer 1-30-2000 Fixed fwrite functions to work on little endian machines
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef UNIVERSAL_FILE_IO_INCLUDED
|
||||
#define UNIVERSAL_FILE_IO_INCLUDED
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
class UniversalFileIO {
|
||||
|
||||
public:
|
||||
|
||||
UniversalFileIO();
|
||||
|
||||
long freadLong( FILE *f );
|
||||
float freadFloat( FILE *f );
|
||||
|
||||
void fwriteLong( FILE *f, long x );
|
||||
void fwriteFloat( FILE *f, float x );
|
||||
|
||||
private:
|
||||
|
||||
char machineBigEndian;
|
||||
|
||||
char bytesInLong;
|
||||
char bytesInFloat;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline UniversalFileIO::UniversalFileIO()
|
||||
: machineBigEndian( true ),
|
||||
bytesInLong( 4 ), bytesInFloat( 4 )
|
||||
{
|
||||
|
||||
// test whether machine is big endian
|
||||
long test = 1;
|
||||
char testChopped = (*(char*)&test);
|
||||
if( testChopped == 1 ) machineBigEndian = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline long UniversalFileIO::freadLong( FILE *f ) {
|
||||
if( machineBigEndian ) {
|
||||
long returnVal;
|
||||
fread((void *)&returnVal, sizeof(long), 1, f);
|
||||
return returnVal;
|
||||
}
|
||||
else {
|
||||
unsigned char *buffer = new unsigned char[bytesInLong];
|
||||
|
||||
fread((void *)buffer, sizeof(char), bytesInLong, f);
|
||||
|
||||
// now put the bytes into a long
|
||||
long returnVal = (long)( buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3] );
|
||||
|
||||
delete [] buffer;
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
}
|
||||
|
||||
inline float UniversalFileIO::freadFloat( FILE *f ) {
|
||||
if( machineBigEndian ) {
|
||||
float returnVal;
|
||||
fread( (void *)&returnVal, sizeof(float), 1, f );
|
||||
return returnVal;
|
||||
}
|
||||
else {
|
||||
unsigned char *buffer = new unsigned char[bytesInFloat];
|
||||
|
||||
fread( (void *)buffer, sizeof(char), bytesInFloat, f );
|
||||
|
||||
// now put the bytes into a long
|
||||
long temp = (long)(buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]);
|
||||
|
||||
delete [] buffer;
|
||||
|
||||
return *((float *) &temp); // convert long into a float
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void UniversalFileIO::fwriteLong( FILE *f, long x ) {
|
||||
if( machineBigEndian ) {
|
||||
fwrite( (void *)&x, sizeof(long), 1, f );
|
||||
}
|
||||
else {
|
||||
unsigned char *buffer = new unsigned char[bytesInLong];
|
||||
|
||||
buffer[0] = (unsigned char)(x >> 24); // put bytes from long into char buffer
|
||||
buffer[1] = (unsigned char)(x >> 16);
|
||||
buffer[2] = (unsigned char)(x >> 8);
|
||||
buffer[3] = (unsigned char)(x);
|
||||
|
||||
fwrite( (void *)buffer, sizeof(char), bytesInLong, f );
|
||||
}
|
||||
}
|
||||
|
||||
inline void UniversalFileIO::fwriteFloat( FILE *f, float x ) {
|
||||
if( machineBigEndian ) {
|
||||
fwrite( (void *)&x, sizeof(float), 1, f );
|
||||
}
|
||||
else {
|
||||
unsigned char *buffer = new unsigned char[bytesInFloat];
|
||||
|
||||
long temp = *((long*)&x); // convert float into long so that bit-wise ops can be performed
|
||||
|
||||
buffer[0] = (unsigned char)(temp >> 24); // put bytes from float into char buffer
|
||||
buffer[1] = (unsigned char)(temp >> 16);
|
||||
buffer[2] = (unsigned char)(temp >> 8);
|
||||
buffer[3] = (unsigned char)(temp);
|
||||
|
||||
fwrite( (void *)buffer, sizeof(char), bytesInFloat, f );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
77
minorGems/io/file/linux/PathLinux.cpp
Normal file
77
minorGems/io/file/linux/PathLinux.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-February-12 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-August-1 Jason Rohrer
|
||||
* Added missing length return value.
|
||||
*
|
||||
* 2003-June-2 Jason Rohrer
|
||||
* Added support for new path checking functions.
|
||||
*
|
||||
* 2010-May-18 Jason Rohrer
|
||||
* String parameters as const to fix warnings.
|
||||
*/
|
||||
|
||||
#include "minorGems/io/file/Path.h"
|
||||
#include "minorGems/util/stringUtils.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Linux-specific path implementation. May be compatible
|
||||
* with other posix-complient systems.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
char Path::getDelimeter() {
|
||||
return '/';
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *Path::getAbsoluteRoot( int *outLength ) {
|
||||
char *returnString = new char[1];
|
||||
returnString[0] = '/';
|
||||
|
||||
*outLength = 1;
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char Path::isAbsolute( const char *inPathString ) {
|
||||
if( inPathString[0] == '/' ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *Path::extractRoot( const char *inPathString ) {
|
||||
if( isAbsolute( inPathString ) ){
|
||||
return stringDuplicate( "/" );
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char Path::isRoot( const char *inPathString ) {
|
||||
if( strcmp( inPathString, "/" ) == 0 ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
73
minorGems/io/file/test/testChildFiles.cpp
Normal file
73
minorGems/io/file/test/testChildFiles.cpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2004-January-4 Jason Rohrer
|
||||
* Created.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* A test program for the various child file functions in File.h
|
||||
*
|
||||
* @author Jason Rohrer.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "minorGems/io/file/File.h"
|
||||
|
||||
|
||||
|
||||
int main( int inNumArgs, char **inArgs ) {
|
||||
|
||||
char *fileName = "linux";
|
||||
|
||||
if( inNumArgs > 1 ) {
|
||||
fileName = inArgs[1];
|
||||
}
|
||||
|
||||
File *testFile = new File( NULL, fileName );
|
||||
|
||||
int numChildren;
|
||||
|
||||
File **childFiles = testFile->getChildFiles( &numChildren );
|
||||
|
||||
|
||||
printf( "child files:\n" );
|
||||
for( int i=0; i<numChildren; i++ ) {
|
||||
|
||||
char *fullName = childFiles[i]->getFullFileName();
|
||||
|
||||
printf( " %s\n", fullName );
|
||||
|
||||
delete [] fullName;
|
||||
|
||||
delete childFiles[i];
|
||||
}
|
||||
|
||||
delete [] childFiles;
|
||||
|
||||
|
||||
|
||||
childFiles = testFile->getChildFilesRecursive( 10, &numChildren );
|
||||
|
||||
|
||||
printf( "recursive child files:\n" );
|
||||
for( int i=0; i<numChildren; i++ ) {
|
||||
|
||||
char *fullName = childFiles[i]->getFullFileName();
|
||||
|
||||
printf( " %s\n", fullName );
|
||||
|
||||
delete [] fullName;
|
||||
|
||||
delete childFiles[i];
|
||||
}
|
||||
|
||||
delete [] childFiles;
|
||||
|
||||
|
||||
delete testFile;
|
||||
|
||||
return 0;
|
||||
}
|
39
minorGems/io/file/test/testPath.cpp
Normal file
39
minorGems/io/file/test/testPath.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2002-August-1 Jason Rohrer
|
||||
* Created.
|
||||
*/
|
||||
|
||||
|
||||
#include "Path.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
char *pathString = "/test/this/thing";
|
||||
|
||||
printf( "using path string = %s\n", pathString );
|
||||
|
||||
printf( "Constructing path.\n" );
|
||||
Path *path = new Path( pathString );
|
||||
|
||||
|
||||
printf( "Extracting path string.\n" );
|
||||
char *extractedPathString = path->getPathStringTerminated();
|
||||
|
||||
printf( "extracted path string = %s\n", extractedPathString );
|
||||
|
||||
|
||||
|
||||
delete [] extractedPathString;
|
||||
|
||||
delete path;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
39
minorGems/io/file/testPath.cpp
Normal file
39
minorGems/io/file/testPath.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2002-August-1 Jason Rohrer
|
||||
* Created.
|
||||
*/
|
||||
|
||||
|
||||
#include "Path.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
char *pathString = "/test/this/thing";
|
||||
|
||||
printf( "using path string = %s\n", pathString );
|
||||
|
||||
printf( "Constructing path.\n" );
|
||||
Path *path = new Path( pathString );
|
||||
|
||||
|
||||
printf( "Extracting path string.\n" );
|
||||
char *extractedPathString = path->getPathStringTerminated();
|
||||
|
||||
printf( "extracted path string = %s\n", extractedPathString );
|
||||
|
||||
|
||||
|
||||
delete [] extractedPathString;
|
||||
|
||||
delete path;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
51
minorGems/io/file/unix/DirectoryUnix.cpp
Normal file
51
minorGems/io/file/unix/DirectoryUnix.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2003-January-23 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2003-November-10 Jason Rohrer
|
||||
* Added makeDirectory function.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "minorGems/io/file/Directory.h"
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
|
||||
char Directory::removeDirectory( File *inFile ) {
|
||||
char *fileName = inFile->getFullFileName();
|
||||
|
||||
int result = rmdir( fileName );
|
||||
|
||||
delete [] fileName;
|
||||
|
||||
if( result == 0 ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char Directory::makeDirectory( File *inFile ) {
|
||||
char *stringName = inFile->getFullFileName();
|
||||
|
||||
int result = mkdir( stringName, 0xFFFF );
|
||||
|
||||
delete [] stringName;
|
||||
|
||||
if( 0 == result ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
53
minorGems/io/file/win32/DirectoryWin32.cpp
Normal file
53
minorGems/io/file/win32/DirectoryWin32.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2003-January-23 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2003-November-10 Jason Rohrer
|
||||
* Added makeDirectory function.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "minorGems/io/file/Directory.h"
|
||||
|
||||
|
||||
|
||||
#include <direct.h>
|
||||
|
||||
|
||||
|
||||
char Directory::removeDirectory( File *inFile ) {
|
||||
char *fileName = inFile->getFullFileName();
|
||||
|
||||
int result = _rmdir( fileName );
|
||||
|
||||
delete [] fileName;
|
||||
|
||||
if( result == 0 ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char Directory::makeDirectory( File *inFile ) {
|
||||
char *stringName = inFile->getFullFileName();
|
||||
|
||||
int result = mkdir( stringName );
|
||||
|
||||
delete [] stringName;
|
||||
|
||||
if( 0 == result ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
95
minorGems/io/file/win32/PathWin32.cpp
Normal file
95
minorGems/io/file/win32/PathWin32.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2001-February-12 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2001-March-4 Jason Rohrer
|
||||
* Fixed delimeter constants.
|
||||
*
|
||||
* 2001-August-1 Jason Rohrer
|
||||
* Added missing length return value.
|
||||
*
|
||||
* 2003-June-2 Jason Rohrer
|
||||
* Added support for new path checking functions.
|
||||
*
|
||||
* 2010-May-14 Jason Rohrer
|
||||
* String parameters as const to fix warnings.
|
||||
*/
|
||||
|
||||
#include "minorGems/io/file/Path.h"
|
||||
#include "minorGems/util/stringUtils.h"
|
||||
|
||||
|
||||
/*
|
||||
* Windows-specific path implementation.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
char Path::getDelimeter() {
|
||||
return '\\';
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *Path::getAbsoluteRoot( int *outLength) {
|
||||
// C:\ is the only root we can generically return
|
||||
|
||||
char *returnString = new char[3];
|
||||
|
||||
returnString[0] = 'C';
|
||||
returnString[1] = ':';
|
||||
returnString[2] = '\\';
|
||||
|
||||
*outLength = 3;
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char Path::isAbsolute( const char *inPathString ) {
|
||||
// ignore first character, which will be drive letter
|
||||
if( inPathString[1] == ':' && inPathString[2] == '\\' ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *Path::extractRoot( const char *inPathString ) {
|
||||
if( isAbsolute( inPathString ) ){
|
||||
// copy path, then trim to only three characters
|
||||
|
||||
char *pathCopy = stringDuplicate( inPathString );
|
||||
pathCopy[ 3 ] = '\0';
|
||||
|
||||
char *trimmedCopy = stringDuplicate( pathCopy );
|
||||
delete [] pathCopy;
|
||||
|
||||
return trimmedCopy;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char Path::isRoot( const char *inPathString ) {
|
||||
// must be of form "c:\"
|
||||
if( strlen( inPathString ) == 3 &&
|
||||
inPathString[1] == ':' &&
|
||||
inPathString[2] == '\\' ) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
159
minorGems/io/file/win32/dirent.cpp
Normal file
159
minorGems/io/file/win32/dirent.cpp
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2002-April-7 Jason Rohrer
|
||||
* Added a mkdir wrapper for CodeWarrior.
|
||||
*
|
||||
* 2002-April-11 Jason Rohrer
|
||||
* Changed type of mode parameter to work with Visual C++.
|
||||
* Added missing include.
|
||||
*
|
||||
* 2002-July-22 Jason Rohrer
|
||||
* Commented out mkdir replacement function to work with new MSL.
|
||||
*
|
||||
* 2002-October-13 Jason Rohrer
|
||||
* Re-added mkdir wrapper function, since both CW4 and VC++ need it.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Implementation of POSIX directory browsing functions and types for Win32.
|
||||
|
||||
Kevlin Henney (mailto:kevlin@acm.org), March 1997.
|
||||
|
||||
Copyright Kevlin Henney, 1997. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided
|
||||
that this copyright and permissions notice appear in all copies and
|
||||
derivatives, and that no charge may be made for the software and its
|
||||
documentation except to cover cost of distribution.
|
||||
|
||||
This software is supplied "as is" without express or implied warranty.
|
||||
|
||||
But that said, if there are any problems please get in touch.
|
||||
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <io.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <direct.h>
|
||||
|
||||
|
||||
struct DIR
|
||||
{
|
||||
long handle; /* -1 for failed rewind */
|
||||
struct _finddata_t info;
|
||||
struct dirent result; /* d_name null iff first time */
|
||||
char *name; /* NTBS */
|
||||
};
|
||||
|
||||
DIR *opendir(const char *name)
|
||||
{
|
||||
DIR *dir = 0;
|
||||
|
||||
if(name && name[0])
|
||||
{
|
||||
size_t base_length = strlen(name);
|
||||
const char *all = /* the root directory is a special case... */
|
||||
strchr("/\\", name[base_length - 1]) ? "*" : "/*";
|
||||
|
||||
if((dir = (DIR *) malloc(sizeof *dir)) != 0 &&
|
||||
(dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0)
|
||||
{
|
||||
strcat(strcpy(dir->name, name), all);
|
||||
|
||||
if((dir->handle = _findfirst(dir->name, &dir->info)) != -1)
|
||||
{
|
||||
dir->result.d_name = 0;
|
||||
}
|
||||
else /* rollback */
|
||||
{
|
||||
free(dir->name);
|
||||
free(dir);
|
||||
dir = 0;
|
||||
}
|
||||
}
|
||||
else /* rollback */
|
||||
{
|
||||
free(dir);
|
||||
dir = 0;
|
||||
errno = ENOMEM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = EINVAL;
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
int closedir(DIR *dir)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
if(dir)
|
||||
{
|
||||
if(dir->handle != -1)
|
||||
{
|
||||
result = _findclose(dir->handle);
|
||||
}
|
||||
|
||||
free(dir->name);
|
||||
free(dir);
|
||||
}
|
||||
|
||||
if(result == -1) /* map all errors to EBADF */
|
||||
{
|
||||
errno = EBADF;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct dirent *readdir(DIR *dir)
|
||||
{
|
||||
struct dirent *result = 0;
|
||||
|
||||
if(dir && dir->handle != -1)
|
||||
{
|
||||
if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
|
||||
{
|
||||
result = &dir->result;
|
||||
result->d_name = dir->info.name;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = EBADF;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void rewinddir(DIR *dir)
|
||||
{
|
||||
if(dir && dir->handle != -1)
|
||||
{
|
||||
_findclose(dir->handle);
|
||||
dir->handle = _findfirst(dir->name, &dir->info);
|
||||
dir->result.d_name = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = EBADF;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mkdir( const char *pathname, unsigned int mode ) {
|
||||
return mkdir( pathname );
|
||||
}
|
77
minorGems/io/file/win32/dirent.h
Normal file
77
minorGems/io/file/win32/dirent.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2002-April-7 Jason Rohrer
|
||||
* Added a mkdir wrapper for CodeWarrior.
|
||||
*
|
||||
* 2002-April-11 Jason Rohrer
|
||||
* Changed type of mode parameter to work with Visual C++.
|
||||
* Added missing macros.
|
||||
*
|
||||
* 2002-July-22 Jason Rohrer
|
||||
* Commented out mkdir replacement function to work with new MSL.
|
||||
*
|
||||
* 2002-October-13 Jason Rohrer
|
||||
* Re-added mkdir wrapper function, since both CW4 and VC++ need it.
|
||||
*/
|
||||
|
||||
#include "minorGems/common.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Declaration of POSIX directory browsing functions and types for Win32.
|
||||
|
||||
Kevlin Henney (mailto:kevlin@acm.org), March 1997.
|
||||
|
||||
Copyright Kevlin Henney, 1997. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided
|
||||
that this copyright and permissions notice appear in all copies and
|
||||
derivatives, and that no charge may be made for the software and its
|
||||
documentation except to cover cost of distribution.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DIRENT_INCLUDED
|
||||
#define DIRENT_INCLUDED
|
||||
|
||||
typedef struct DIR DIR;
|
||||
|
||||
struct dirent
|
||||
{
|
||||
char *d_name;
|
||||
};
|
||||
|
||||
DIR *opendir(const char *);
|
||||
int closedir(DIR *);
|
||||
struct dirent *readdir(DIR *);
|
||||
void rewinddir(DIR *);
|
||||
|
||||
|
||||
|
||||
#include <sys/stat.h>
|
||||
/**
|
||||
* The Metrowerks Standard Library seems
|
||||
* to have only a 1-parameter mkdir command in sys/stat.h.
|
||||
*/
|
||||
int mkdir( const char *pathname, unsigned int mode );
|
||||
|
||||
|
||||
// make sure our needed macros are defined
|
||||
// S_IFMT and S_IFDIR seem to be defined everywhere
|
||||
|
||||
#ifndef __S_ISTYPE
|
||||
#define __S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask))
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(mode) __S_ISTYPE((mode), S_IFDIR)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue