Implementing filemanager
Implementing and testing filemanager and upgrading epanet_output library to use it.
This commit is contained in:
@@ -21,7 +21,8 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|||||||
|
|
||||||
# configure file groups
|
# configure file groups
|
||||||
set(EPANET_OUT_SOURCES src/epanet_output.c
|
set(EPANET_OUT_SOURCES src/epanet_output.c
|
||||||
../util/errormanager.c)
|
../util/errormanager.c
|
||||||
|
../util/filemanager.c)
|
||||||
|
|
||||||
|
|
||||||
# the binary output file API
|
# the binary output file API
|
||||||
|
|||||||
@@ -40,18 +40,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "util/errormanager.h"
|
#include "util/errormanager.h"
|
||||||
|
#include "util/filemanager.h"
|
||||||
|
|
||||||
#include "epanet_output.h"
|
#include "epanet_output.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
|
|
||||||
|
|
||||||
// NOTE: These depend on machine data model and may change when porting
|
// NOTE: These depend on machine data model and may change when porting
|
||||||
// F_OFF Must be a 8 byte / 64 bit integer for large file support
|
|
||||||
#ifdef _WIN32 // Windows (32-bit and 64-bit)
|
|
||||||
#define F_OFF __int64
|
|
||||||
#else // Other platforms
|
|
||||||
#define F_OFF off_t
|
|
||||||
#endif
|
|
||||||
#define INT4 int // Must be a 4 byte / 32 bit integer type
|
#define INT4 int // Must be a 4 byte / 32 bit integer type
|
||||||
#define REAL4 float // Must be a 4 byte / 32 bit real type
|
#define REAL4 float // Must be a 4 byte / 32 bit real type
|
||||||
#define WORDSIZE 4 // Memory alignment 4 byte word size for both int and real
|
#define WORDSIZE 4 // Memory alignment 4 byte word size for both int and real
|
||||||
@@ -71,33 +66,28 @@
|
|||||||
|
|
||||||
// Typedefs for opaque pointer
|
// Typedefs for opaque pointer
|
||||||
typedef struct data_s {
|
typedef struct data_s {
|
||||||
char name[MAXFNAME+1]; // file path/name
|
|
||||||
FILE* file; // FILE structure pointer
|
|
||||||
INT4 nodeCount, tankCount, linkCount, pumpCount, valveCount, nPeriods;
|
INT4 nodeCount, tankCount, linkCount, pumpCount, valveCount, nPeriods;
|
||||||
F_OFF outputStartPos; // starting file position of output data
|
F_OFF outputStartPos; // starting file position of output data
|
||||||
F_OFF bytesPerPeriod; // bytes saved per simulation time period
|
F_OFF bytesPerPeriod; // bytes saved per simulation time period
|
||||||
|
|
||||||
error_handle_t* error_handle;
|
error_handle_t *error_handle;
|
||||||
|
file_handle_t *file_handle;
|
||||||
} data_t;
|
} data_t;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Local functions
|
// Local functions
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void errorLookup(int errcode, char* errmsg, int length);
|
void errorLookup(int errcode, char* errmsg, int length);
|
||||||
int validateFile(ENR_Handle);
|
int validateFile(ENR_Handle);
|
||||||
float getNodeValue(ENR_Handle, int, int, int);
|
float getNodeValue(ENR_Handle, int, int, int);
|
||||||
float getLinkValue(ENR_Handle, int, int, int);
|
float getLinkValue(ENR_Handle, int, int, int);
|
||||||
|
|
||||||
int _fopen(FILE **f, const char *name, const char *mode);
|
float *newFloatArray(int n);
|
||||||
int _fseek(FILE* stream, F_OFF offset, int whence);
|
int *newIntArray(int n);
|
||||||
F_OFF _ftell(FILE* stream);
|
char *newCharArray(int n);
|
||||||
|
|
||||||
float* newFloatArray(int n);
|
|
||||||
int* newIntArray(int n);
|
|
||||||
char* newCharArray(int n);
|
|
||||||
|
|
||||||
|
|
||||||
int EXPORT_OUT_API ENR_init(ENR_Handle* dp_handle)
|
int EXPORT_OUT_API ENR_init(ENR_Handle *dp_handle)
|
||||||
// Purpose: Initialized pointer for the opaque ENR_Handle.
|
// Purpose: Initialized pointer for the opaque ENR_Handle.
|
||||||
//
|
//
|
||||||
// Returns: Error code 0 on success, -1 on failure
|
// Returns: Error code 0 on success, -1 on failure
|
||||||
@@ -114,6 +104,7 @@ int EXPORT_OUT_API ENR_init(ENR_Handle* dp_handle)
|
|||||||
|
|
||||||
if (p_data != NULL){
|
if (p_data != NULL){
|
||||||
p_data->error_handle = create_error_manager(&errorLookup);
|
p_data->error_handle = create_error_manager(&errorLookup);
|
||||||
|
p_data->file_handle = create_file_manager();
|
||||||
*dp_handle = p_data;
|
*dp_handle = p_data;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -123,7 +114,7 @@ int EXPORT_OUT_API ENR_init(ENR_Handle* dp_handle)
|
|||||||
return errorcode;
|
return errorcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EXPORT_OUT_API ENR_close(ENR_Handle* p_handle)
|
int EXPORT_OUT_API ENR_close(ENR_Handle *p_handle)
|
||||||
/*------------------------------------------------------------------------
|
/*------------------------------------------------------------------------
|
||||||
** Input: *p_handle = pointer to ENR_Handle struct
|
** Input: *p_handle = pointer to ENR_Handle struct
|
||||||
**
|
**
|
||||||
@@ -143,13 +134,16 @@ int EXPORT_OUT_API ENR_close(ENR_Handle* p_handle)
|
|||||||
|
|
||||||
p_data = (data_t*)(*p_handle);
|
p_data = (data_t*)(*p_handle);
|
||||||
|
|
||||||
if (p_data == NULL || p_data->file == NULL)
|
if (p_data == NULL || p_data->file_handle == NULL)
|
||||||
errorcode = -1;
|
errorcode = -1;
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
close_file(p_data->file_handle);
|
||||||
|
|
||||||
delete_error_manager(p_data->error_handle);
|
delete_error_manager(p_data->error_handle);
|
||||||
fclose(p_data->file);
|
delete_file_manager(p_data->file_handle);
|
||||||
|
|
||||||
free(p_data);
|
free(p_data);
|
||||||
|
|
||||||
*p_handle = NULL;
|
*p_handle = NULL;
|
||||||
@@ -178,23 +172,22 @@ int EXPORT_OUT_API ENR_open(ENR_Handle p_handle, const char* path)
|
|||||||
if (p_data == NULL) return -1;
|
if (p_data == NULL) return -1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strncpy(p_data->name, path, MAXFNAME);
|
|
||||||
// Attempt to open binary output file for reading only
|
// Attempt to open binary output file for reading only
|
||||||
if ((_fopen(&(p_data->file), path, "rb")) != 0) errorcode = 434;
|
if ((open_file(p_data->file_handle, path, "rb")) != 0)
|
||||||
|
errorcode = 434;
|
||||||
|
|
||||||
// Perform checks to insure the file is valid
|
// Perform checks to insure the file is valid
|
||||||
else if ((err = validateFile(p_data)) != 0) errorcode = err;
|
else if ((err = validateFile(p_data)) != 0) errorcode = err;
|
||||||
|
|
||||||
// If a warning is encountered read file header
|
// If a warning is encountered read file header
|
||||||
if (errorcode < 400 ) {
|
if (errorcode < 400 ) {
|
||||||
|
|
||||||
// read network size
|
// read network size
|
||||||
fseek(p_data->file, 2*WORDSIZE, SEEK_SET);
|
seek_file(p_data->file_handle, 2*WORDSIZE, SEEK_SET);
|
||||||
fread(&(p_data->nodeCount), WORDSIZE, 1, p_data->file);
|
read_file(&(p_data->nodeCount), WORDSIZE, 1, p_data->file_handle);
|
||||||
fread(&(p_data->tankCount), WORDSIZE, 1, p_data->file);
|
read_file(&(p_data->tankCount), WORDSIZE, 1, p_data->file_handle);
|
||||||
fread(&(p_data->linkCount), WORDSIZE, 1, p_data->file);
|
read_file(&(p_data->linkCount), WORDSIZE, 1, p_data->file_handle);
|
||||||
fread(&(p_data->pumpCount), WORDSIZE, 1, p_data->file);
|
read_file(&(p_data->pumpCount), WORDSIZE, 1, p_data->file_handle);
|
||||||
fread(&(p_data->valveCount), WORDSIZE, 1, p_data->file);
|
read_file(&(p_data->valveCount), WORDSIZE, 1, p_data->file_handle);
|
||||||
|
|
||||||
// Compute positions and offsets for retrieving data
|
// Compute positions and offsets for retrieving data
|
||||||
// fixed portion of header + title section + filenames + chem names
|
// fixed portion of header + title section + filenames + chem names
|
||||||
@@ -240,8 +233,8 @@ int EXPORT_OUT_API ENR_getVersion(ENR_Handle p_handle, int* version)
|
|||||||
if (p_data == NULL) return -1;
|
if (p_data == NULL) return -1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fseek(p_data->file, 1*WORDSIZE, SEEK_SET);
|
seek_file(p_data->file_handle, 1*WORDSIZE, SEEK_SET);
|
||||||
if (fread(version, WORDSIZE, 1, p_data->file) != 1)
|
if (read_file(version, WORDSIZE, 1, p_data->file_handle) != 1)
|
||||||
errorcode = 436;
|
errorcode = 436;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,26 +312,26 @@ int EXPORT_OUT_API ENR_getUnits(ENR_Handle p_handle, ENR_Units code, int* unitFl
|
|||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case ENR_flowUnits:
|
case ENR_flowUnits:
|
||||||
_fseek(p_data->file, 9*WORDSIZE, SEEK_SET);
|
seek_file(p_data->file_handle, 9*WORDSIZE, SEEK_SET);
|
||||||
fread(unitFlag, WORDSIZE, 1, p_data->file);
|
read_file(unitFlag, WORDSIZE, 1, p_data->file_handle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENR_pressUnits:
|
case ENR_pressUnits:
|
||||||
_fseek(p_data->file, 10*WORDSIZE, SEEK_SET);
|
seek_file(p_data->file_handle, 10*WORDSIZE, SEEK_SET);
|
||||||
fread(unitFlag, WORDSIZE, 1, p_data->file);
|
read_file(unitFlag, WORDSIZE, 1, p_data->file_handle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENR_qualUnits:
|
case ENR_qualUnits:
|
||||||
offset = 7*WORDSIZE;
|
offset = 7*WORDSIZE;
|
||||||
_fseek(p_data->file, offset, SEEK_SET);
|
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||||
fread(unitFlag, WORDSIZE, 1, p_data->file);
|
read_file(unitFlag, WORDSIZE, 1, p_data->file_handle);
|
||||||
|
|
||||||
if (*unitFlag == 0) *unitFlag = ENR_NONE;
|
if (*unitFlag == 0) *unitFlag = ENR_NONE;
|
||||||
|
|
||||||
else if (*unitFlag == 1) {
|
else if (*unitFlag == 1) {
|
||||||
offset = 15*WORDSIZE + 3*MAXMSG_P1 + 2*(MAXFNAME+1) + MAXID_P1;
|
offset = 15*WORDSIZE + 3*MAXMSG_P1 + 2*(MAXFNAME+1) + MAXID_P1;
|
||||||
_fseek(p_data->file, offset, SEEK_SET);
|
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||||
fread(temp, MAXID_P1, 1, p_data->file);
|
read_file(temp, MAXID_P1, 1, p_data->file_handle);
|
||||||
|
|
||||||
if (!strcmp(temp, "mg/L")) *unitFlag = ENR_MGL;
|
if (!strcmp(temp, "mg/L")) *unitFlag = ENR_MGL;
|
||||||
else *unitFlag = ENR_UGL;
|
else *unitFlag = ENR_UGL;
|
||||||
@@ -379,18 +372,18 @@ int EXPORT_OUT_API ENR_getTimes(ENR_Handle p_handle, ENR_Time code, int* time)
|
|||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case ENR_reportStart:
|
case ENR_reportStart:
|
||||||
fseek(p_data->file, 12*WORDSIZE, SEEK_SET);
|
seek_file(p_data->file_handle, 12*WORDSIZE, SEEK_SET);
|
||||||
fread(time, WORDSIZE, 1, p_data->file);
|
read_file(time, WORDSIZE, 1, p_data->file_handle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENR_reportStep:
|
case ENR_reportStep:
|
||||||
fseek(p_data->file, 13*WORDSIZE, SEEK_SET);
|
seek_file(p_data->file_handle, 13*WORDSIZE, SEEK_SET);
|
||||||
fread(time, WORDSIZE, 1, p_data->file);
|
read_file(time, WORDSIZE, 1, p_data->file_handle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENR_simDuration:
|
case ENR_simDuration:
|
||||||
fseek(p_data->file, 14*WORDSIZE, SEEK_SET);
|
seek_file(p_data->file_handle, 14*WORDSIZE, SEEK_SET);
|
||||||
fread(time, WORDSIZE, 1, p_data->file);
|
read_file(time, WORDSIZE, 1, p_data->file_handle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENR_numPeriods:
|
case ENR_numPeriods:
|
||||||
@@ -405,7 +398,6 @@ int EXPORT_OUT_API ENR_getTimes(ENR_Handle p_handle, ENR_Time code, int* time)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int EXPORT_OUT_API ENR_getChemData(ENR_Handle p_handle, char** name, int* length)
|
int EXPORT_OUT_API ENR_getChemData(ENR_Handle p_handle, char** name, int* length)
|
||||||
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -459,8 +451,8 @@ int EXPORT_OUT_API ENR_getElementName(ENR_Handle p_handle, ENR_ElementType type,
|
|||||||
|
|
||||||
if (!errorcode)
|
if (!errorcode)
|
||||||
{
|
{
|
||||||
_fseek(p_data->file, offset, SEEK_SET);
|
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||||
fread(temp, 1, MAXID_P1, p_data->file);
|
read_file(temp, 1, MAXID_P1, p_data->file_handle);
|
||||||
|
|
||||||
*name = temp;
|
*name = temp;
|
||||||
*length = MAXID_P1;
|
*length = MAXID_P1;
|
||||||
@@ -505,9 +497,9 @@ int EXPORT_OUT_API ENR_getEnergyUsage(ENR_Handle p_handle, int pumpIndex,
|
|||||||
offset += (pumpIndex - 1)*(WORDSIZE + 6*WORDSIZE);
|
offset += (pumpIndex - 1)*(WORDSIZE + 6*WORDSIZE);
|
||||||
|
|
||||||
// Power summary is 1 int and 6 floats for each pump
|
// Power summary is 1 int and 6 floats for each pump
|
||||||
_fseek(p_data->file, offset, SEEK_SET);
|
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||||
fread(linkIndex, WORDSIZE, 1, p_data->file);
|
read_file(linkIndex, WORDSIZE, 1, p_data->file_handle);
|
||||||
fread(temp, WORDSIZE, 6, p_data->file);
|
read_file(temp, WORDSIZE, 6, p_data->file_handle);
|
||||||
|
|
||||||
*outValues = temp;
|
*outValues = temp;
|
||||||
*length = NENERGYRESULTS;
|
*length = NENERGYRESULTS;
|
||||||
@@ -541,8 +533,8 @@ int EXPORT_OUT_API ENR_getNetReacts(ENR_Handle p_handle, float** outValues, int*
|
|||||||
// Reaction summary is 4 floats located right before epilogue.
|
// Reaction summary is 4 floats located right before epilogue.
|
||||||
// This offset is relative to the end of the file.
|
// This offset is relative to the end of the file.
|
||||||
offset = - 3*WORDSIZE - 4*WORDSIZE;
|
offset = - 3*WORDSIZE - 4*WORDSIZE;
|
||||||
_fseek(p_data->file, offset, SEEK_END);
|
seek_file(p_data->file_handle, offset, SEEK_END);
|
||||||
fread(temp, WORDSIZE, 4, p_data->file);
|
read_file(temp, WORDSIZE, 4, p_data->file_handle);
|
||||||
|
|
||||||
*outValues = temp;
|
*outValues = temp;
|
||||||
*length = NREACTRESULTS;
|
*length = NREACTRESULTS;
|
||||||
@@ -670,8 +662,8 @@ int EXPORT_OUT_API ENR_getNodeAttribute(ENR_Handle p_handle, int periodIndex,
|
|||||||
// add offset for node and attribute
|
// add offset for node and attribute
|
||||||
offset += ((attr - 1)*p_data->nodeCount)*WORDSIZE;
|
offset += ((attr - 1)*p_data->nodeCount)*WORDSIZE;
|
||||||
|
|
||||||
_fseek(p_data->file, offset, SEEK_SET);
|
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||||
fread(temp, WORDSIZE, p_data->nodeCount, p_data->file);
|
read_file(temp, WORDSIZE, p_data->nodeCount, p_data->file_handle);
|
||||||
|
|
||||||
*outValueArray = temp;
|
*outValueArray = temp;
|
||||||
*length = p_data->nodeCount;
|
*length = p_data->nodeCount;
|
||||||
@@ -720,8 +712,8 @@ int EXPORT_OUT_API ENR_getLinkAttribute(ENR_Handle p_handle, int periodIndex,
|
|||||||
// add offset for link and attribute
|
// add offset for link and attribute
|
||||||
offset += ((attr - 1)*p_data->linkCount)*WORDSIZE;
|
offset += ((attr - 1)*p_data->linkCount)*WORDSIZE;
|
||||||
|
|
||||||
_fseek(p_data->file, offset, SEEK_SET);
|
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||||
fread(temp, WORDSIZE, p_data->linkCount, p_data->file);
|
read_file(temp, WORDSIZE, p_data->linkCount, p_data->file_handle);
|
||||||
|
|
||||||
*outValueArray = temp;
|
*outValueArray = temp;
|
||||||
*length = p_data->linkCount;
|
*length = p_data->linkCount;
|
||||||
@@ -852,16 +844,16 @@ int validateFile(ENR_Handle p_handle)
|
|||||||
p_data = (data_t*)p_handle;
|
p_data = (data_t*)p_handle;
|
||||||
|
|
||||||
// Read magic number from beginning of file
|
// Read magic number from beginning of file
|
||||||
fseek(p_data->file, 0L, SEEK_SET);
|
seek_file(p_data->file_handle, 0L, SEEK_SET);
|
||||||
fread(&magic1, WORDSIZE, 1, p_data->file);
|
read_file(&magic1, WORDSIZE, 1, p_data->file_handle);
|
||||||
|
|
||||||
// Fast forward to end and read file epilogue
|
// Fast forward to end and read file epilogue
|
||||||
fseek(p_data->file, -3*WORDSIZE, SEEK_END);
|
seek_file(p_data->file_handle, -3*WORDSIZE, SEEK_END);
|
||||||
fread(&(p_data->nPeriods), WORDSIZE, 1, p_data->file);
|
read_file(&(p_data->nPeriods), WORDSIZE, 1, p_data->file_handle);
|
||||||
fread(&hydcode, WORDSIZE, 1, p_data->file);
|
read_file(&hydcode, WORDSIZE, 1, p_data->file_handle);
|
||||||
fread(&magic2, WORDSIZE, 1, p_data->file);
|
read_file(&magic2, WORDSIZE, 1, p_data->file_handle);
|
||||||
|
|
||||||
filepos = _ftell(p_data->file);
|
filepos = tell_file(p_data->file_handle);
|
||||||
|
|
||||||
// Is the file an EPANET binary file?
|
// Is the file an EPANET binary file?
|
||||||
if (magic1 != magic2) errorcode = 435;
|
if (magic1 != magic2) errorcode = 435;
|
||||||
@@ -891,8 +883,8 @@ float getNodeValue(ENR_Handle p_handle, int periodIndex, int nodeIndex,
|
|||||||
// add byte position for attribute and node
|
// add byte position for attribute and node
|
||||||
offset += ((attr - 1)*p_data->nodeCount + (nodeIndex - 1))*WORDSIZE;
|
offset += ((attr - 1)*p_data->nodeCount + (nodeIndex - 1))*WORDSIZE;
|
||||||
|
|
||||||
_fseek(p_data->file, offset, SEEK_SET);
|
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||||
fread(&y, WORDSIZE, 1, p_data->file);
|
read_file(&y, WORDSIZE, 1, p_data->file_handle);
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
@@ -915,56 +907,12 @@ float getLinkValue(ENR_Handle p_handle, int periodIndex, int linkIndex,
|
|||||||
// add byte position for attribute and link
|
// add byte position for attribute and link
|
||||||
offset += ((attr - 1)*p_data->linkCount + (linkIndex - 1))*WORDSIZE;
|
offset += ((attr - 1)*p_data->linkCount + (linkIndex - 1))*WORDSIZE;
|
||||||
|
|
||||||
_fseek(p_data->file, offset, SEEK_SET);
|
seek_file(p_data->file_handle, offset, SEEK_SET);
|
||||||
fread(&y, WORDSIZE, 1, p_data->file);
|
read_file(&y, WORDSIZE, 1, p_data->file_handle);
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fopen(FILE **f, const char *name, const char *mode) {
|
|
||||||
//
|
|
||||||
// Purpose: Substitute for fopen_s on platforms where it doesn't exist
|
|
||||||
// Note: fopen_s is part of C++11 standard
|
|
||||||
//
|
|
||||||
int ret = 0;
|
|
||||||
#ifdef _WIN32
|
|
||||||
ret = (int)fopen_s(f, name, mode);
|
|
||||||
#else
|
|
||||||
*f = fopen(name, mode);
|
|
||||||
if (!*f)
|
|
||||||
ret = -1;
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _fseek(FILE* stream, F_OFF offset, int whence)
|
|
||||||
//
|
|
||||||
// Purpose: Selects platform fseek() for large file support
|
|
||||||
//
|
|
||||||
{
|
|
||||||
#ifdef _WIN32 // Windows (32-bit and 64-bit)
|
|
||||||
#define FSEEK64 _fseeki64
|
|
||||||
#else // Other platforms
|
|
||||||
#define FSEEK64 fseeko
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return FSEEK64(stream, offset, whence);
|
|
||||||
}
|
|
||||||
|
|
||||||
F_OFF _ftell(FILE* stream)
|
|
||||||
//
|
|
||||||
// Purpose: Selects platform ftell() for large file support
|
|
||||||
//
|
|
||||||
{
|
|
||||||
#ifdef _WIN32 // Windows (32-bit and 64-bit)
|
|
||||||
#define FTELL64 _ftelli64
|
|
||||||
#else // Other platforms
|
|
||||||
#define FTELL64 ftello
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return FTELL64(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
float* newFloatArray(int n)
|
float* newFloatArray(int n)
|
||||||
//
|
//
|
||||||
// Warning: Caller must free memory allocated by this function.
|
// Warning: Caller must free memory allocated by this function.
|
||||||
|
|||||||
@@ -1,49 +1,91 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
// MSVC ONLY
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define _CRTDBG_MAP_ALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#else
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "filemanager.h"
|
#include "filemanager.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct file_s {
|
||||||
|
char filename[FILE_MAXNAME + 1];
|
||||||
|
FILE *file;
|
||||||
|
char mode[FILE_MAXMODE + 1];
|
||||||
|
} file_handle_t;
|
||||||
|
|
||||||
|
|
||||||
// local (private) functions
|
// local (private) functions
|
||||||
|
int _fopen(FILE **f, const char *name, const char *mode);
|
||||||
int _get_temp_filename(char *tempname);
|
int _get_temp_filename(char *tempname);
|
||||||
|
|
||||||
|
|
||||||
file_handle_t *create_file_manager(const char *filename, const char *file_mode) {
|
file_handle_t *create_file_manager() {
|
||||||
|
|
||||||
file_handle_t *file_handle;
|
file_handle_t *file_handle;
|
||||||
file_handle = (file_handle_t*)calloc(1, sizeof(file_handle_t));
|
file_handle = (file_handle_t*)calloc(1, sizeof(file_handle_t));
|
||||||
|
|
||||||
|
return file_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete_file_manager(file_handle_t *file_handle) {
|
||||||
|
free(file_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int open_file(file_handle_t *file_handle, const char *filename, const char *file_mode) {
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
if (filename == NULL)
|
if (filename == NULL)
|
||||||
_get_temp_filename(file_handle->filename);
|
_get_temp_filename(file_handle->filename);
|
||||||
else
|
else
|
||||||
strncpy(file_handle->filename, filename, FILE_MAXNAME);
|
strncpy(file_handle->filename, filename, FILE_MAXNAME);
|
||||||
|
|
||||||
file_handle->file = NULL;
|
if (file_mode == NULL)
|
||||||
strncpy(file_handle->mode, file_mode, FILE_MAXMODE);
|
|
||||||
|
|
||||||
return file_handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
int delete_file_manager(file_handle_t *file_handle) {
|
|
||||||
free(file_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int open_file(file_handle_t *file_handle) {
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
if ((file_handle->file = fopen(file_handle->filename, file_handle->mode)) == NULL)
|
|
||||||
error = -1;
|
error = -1;
|
||||||
|
else {
|
||||||
|
strncpy(file_handle->mode, file_mode, FILE_MAXMODE);
|
||||||
|
error = _fopen(&(file_handle->file), file_handle->filename, file_handle->mode);
|
||||||
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *get_file(file_handle_t *file_handle) {
|
int seek_file(file_handle_t *file_handle, F_OFF offset, int whence)
|
||||||
return file_handle->file;
|
{
|
||||||
|
#ifdef _WIN32 // Windows (32-bit and 64-bit)
|
||||||
|
#define FSEEK64 _fseeki64
|
||||||
|
#else // Other platforms
|
||||||
|
#define FSEEK64 fseeko
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return FSEEK64(file_handle->file, offset, whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
F_OFF tell_file(file_handle_t *file_handle)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32 // Windows (32-bit and 64-bit)
|
||||||
|
#define FTELL64 _ftelli64
|
||||||
|
#else // Other platforms
|
||||||
|
#define FTELL64 ftello
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return FTELL64(file_handle->file);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t read_file(void *ptr, size_t size, size_t nmemb, file_handle_t *file_handle)
|
||||||
|
{
|
||||||
|
return fread(ptr, size, nmemb, file_handle->file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int close_file(file_handle_t *file_handle) {
|
int close_file(file_handle_t *file_handle) {
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
@@ -59,14 +101,30 @@ int remove_file(file_handle_t *file_handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int _get_temp_filename(char *tempname) {
|
int _fopen(FILE **f, const char *name, const char *mode) {
|
||||||
int error = 0
|
//
|
||||||
|
// Purpose: Substitute for fopen_s on platforms where it doesn't exist
|
||||||
|
// Note: fopen_s is part of C++11 standard
|
||||||
|
//
|
||||||
|
int ret = 0;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char* name = NULL;
|
ret = (int)fopen_s(f, name, mode);
|
||||||
|
#else
|
||||||
|
*f = fopen(name, mode);
|
||||||
|
if (!*f)
|
||||||
|
ret = -1;
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _get_temp_filename(char *tempname) {
|
||||||
|
int error = 0;
|
||||||
|
#ifdef _WIN32
|
||||||
|
char *name = NULL;
|
||||||
|
|
||||||
// --- use Windows _tempnam function to get a pointer to an
|
// --- use Windows _tempnam function to get a pointer to an
|
||||||
// unused file name that begins with "en"
|
// unused file name that begins with "en"
|
||||||
if ((name = _tempnam(NULL, "en") == NULL) {
|
if ((name = _tempnam(name, "en")) == NULL) {
|
||||||
error = -1;
|
error = -1;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,14 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
// F_OFF Must be a 8 byte / 64 bit integer for large file support
|
||||||
|
#ifdef _WIN32 // Windows (32-bit and 64-bit)
|
||||||
|
#define F_OFF __int64
|
||||||
|
#else // Other platforms
|
||||||
|
#define F_OFF off_t
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FILE_MAXNAME 259
|
#define FILE_MAXNAME 259
|
||||||
#define FILE_MAXMODE 3
|
#define FILE_MAXMODE 3
|
||||||
|
|
||||||
@@ -17,21 +25,22 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef struct file_s {
|
typedef struct file_s file_handle_t;
|
||||||
char filename[FILE_MAXNAME + 1],
|
|
||||||
FILE *file;
|
|
||||||
char mode[FILE_MAXMODE + 1];
|
|
||||||
} file_handle_t;
|
|
||||||
|
|
||||||
|
|
||||||
file_handle_t *create_file_manager(const char *filename, const char *file_mode);
|
file_handle_t *create_file_manager();
|
||||||
|
|
||||||
int delete_file_manager(file_handle_t *file_handle);
|
void delete_file_manager(file_handle_t *file_handle);
|
||||||
|
|
||||||
|
|
||||||
int open_file(file_handle_t *file_handle);
|
int open_file(file_handle_t *file_handle, const char *filename, const char *file_mode);
|
||||||
|
|
||||||
|
int seek_file(file_handle_t *file_handle, F_OFF offset, int whence);
|
||||||
|
|
||||||
|
F_OFF tell_file(file_handle_t *file_handle);
|
||||||
|
|
||||||
|
size_t read_file(void *ptr, size_t size, size_t nmemb, file_handle_t *file_handle);
|
||||||
|
|
||||||
FILE *get_file(file_handle_t *file_handle);
|
|
||||||
|
|
||||||
int close_file(file_handle_t *file_handle);
|
int close_file(file_handle_t *file_handle);
|
||||||
|
|
||||||
|
|||||||
@@ -15,3 +15,9 @@ set (test_source
|
|||||||
add_executable(test_errormanager ${test_source})
|
add_executable(test_errormanager ${test_source})
|
||||||
target_include_directories(test_errormanager PUBLIC ../../src/)
|
target_include_directories(test_errormanager PUBLIC ../../src/)
|
||||||
target_link_libraries(test_errormanager ${Boost_LIBRARIES})
|
target_link_libraries(test_errormanager ${Boost_LIBRARIES})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(test_filemanager ./test_filemanager.cpp ../../src/util/filemanager.c)
|
||||||
|
target_include_directories(test_filemanager PUBLIC ../../src/)
|
||||||
|
target_link_libraries(test_filemanager ${Boost_LIBRARIES})
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#define BOOST_TEST_MODULE errormanager
|
#define BOOST_TEST_MODULE errormanager
|
||||||
//#define BOOST_TEST_DYN_LINK
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#include "util/errormanager.h"
|
#include "util/errormanager.h"
|
||||||
|
|||||||
@@ -5,3 +5,62 @@
|
|||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#include "util/filemanager.h"
|
#include "util/filemanager.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DATA_PATH_OUTPUT "./example1.out"
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(test_filemanager)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE (test_create_destroy)
|
||||||
|
{
|
||||||
|
file_handle_t *file_handle = NULL;
|
||||||
|
|
||||||
|
file_handle = create_file_manager();
|
||||||
|
BOOST_CHECK(file_handle != NULL);
|
||||||
|
|
||||||
|
delete_file_manager(file_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_open_close)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
file_handle_t *file_handle = NULL;
|
||||||
|
|
||||||
|
file_handle = create_file_manager();
|
||||||
|
BOOST_CHECK(file_handle != NULL);
|
||||||
|
|
||||||
|
error = open_file(file_handle, DATA_PATH_OUTPUT, "rb");
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
|
||||||
|
error = close_file(file_handle);
|
||||||
|
BOOST_REQUIRE(error == 0);
|
||||||
|
|
||||||
|
delete_file_manager(file_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Fixture{
|
||||||
|
Fixture() {
|
||||||
|
error = 0;
|
||||||
|
file_handle = NULL;
|
||||||
|
|
||||||
|
file_handle = create_file_manager();
|
||||||
|
open_file(file_handle, DATA_PATH_OUTPUT, "rb");
|
||||||
|
}
|
||||||
|
~Fixture() {
|
||||||
|
close_file(file_handle);
|
||||||
|
delete_file_manager(file_handle);
|
||||||
|
}
|
||||||
|
int error;
|
||||||
|
file_handle_t *file_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_CASE(test_get_file, Fixture)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
|
||||||
|
//file = get_file(file_handle);
|
||||||
|
//BOOST_CHECK(file != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|||||||
Reference in New Issue
Block a user