added amb618 - binary file i/o

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401802
This commit is contained in:
David Anderson 2007-12-16 23:11:00 +00:00
parent cf023a0b7d
commit abb763d1e1
2 changed files with 303 additions and 13 deletions

View File

@ -640,6 +640,197 @@ static cell_t sm_LogToOpenFileEx(IPluginContext *pContext, const cell_t *params)
return 1;
}
static cell_t sm_ReadFile(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
FILE *pFile;
size_t read = 0;
if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
}
if (params[4] != 1 && params[4] != 2 && params[4] != 4)
{
return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]);
}
cell_t *data;
pContext->LocalToPhysAddr(params[2], &data);
if (params[4] == 4)
{
read = fread(data, sizeof(cell_t), params[3], pFile);
}
else if (params[4] == 2)
{
int16_t val;
for (cell_t i = 0; i < params[3]; i++)
{
if (fread(&val, sizeof(int16_t), 1, pFile) != 1)
{
break;
}
data[read++] = val;
}
}
else if (params[4] == 1)
{
int8_t val;
for (cell_t i = 0; i < params[3]; i++)
{
if (fread(&val, sizeof(int8_t), 1, pFile) != 1)
{
break;
}
data[read++] = val;
}
}
if (read != (size_t)params[3] && ferror(pFile) != 0)
{
return -1;
}
return read;
}
static cell_t sm_ReadFileString(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
FILE *pFile;
cell_t num_read = 0;
if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
}
char *buffer;
pContext->LocalToString(params[2], &buffer);
char val;
while (1)
{
/* If we're in stop mode, break as soon as the buffer is full. */
if (params[4] && (params[3] == 0 || num_read >= params[3] - 1))
{
break;
}
if (fread(&val, sizeof(val), 1, pFile) != 1)
{
if (ferror(pFile))
{
return -1;
}
break;
}
if (val == '\0')
{
break;
}
if (params[3] > 0 && num_read < params[3] - 1)
{
buffer[num_read++] = val;
}
}
if (params[3] > 0)
{
buffer[num_read] = '\0';
}
return num_read;
}
static cell_t sm_WriteFile(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
FILE *pFile;
size_t read = 0;
if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
}
cell_t *data;
pContext->LocalToPhysAddr(params[2], &data);
if (params[4] != 1 && params[4] != 2 && params[4] != 4)
{
return pContext->ThrowNativeError("Invalid size specifier (%d is not 1, 2, or 4)", params[4]);
}
/* :NOTE: This really isn't compatible with big endian but we will never have to worry about that. */
if (params[4] == 4)
{
if (fwrite(data, sizeof(cell_t), params[3], pFile) != (size_t)params[3])
{
return 0;
}
}
else if (params[4] == 2)
{
for (cell_t i = 0; i < params[3]; i++)
{
if (fwrite(&data[i], sizeof(int16_t), 1, pFile) != 1)
{
return 0;
}
}
}
else if (params[4] == 1)
{
for (cell_t i = 0; i < params[3]; i++)
{
if (fwrite(&data[i], sizeof(int8_t), 1, pFile) != 1)
{
return 0;
}
}
}
return 1;
}
static cell_t sm_WriteFileString(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
FILE *pFile;
if ((herr=g_HandleSys.ReadHandle(hndl, g_FileType, &sec, (void **)&pFile))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr);
}
char *buffer;
pContext->LocalToString(params[2], &buffer);
size_t len = strlen(buffer);
if (params[3])
{
len++;
}
return (fwrite(buffer, sizeof(char), len, pFile) == len) ? 1 : 0;
}
REGISTER_NATIVES(filesystem)
{
{"OpenDirectory", sm_OpenDirectory},
@ -664,5 +855,9 @@ REGISTER_NATIVES(filesystem)
{"GetFileTime", sm_GetFileTime},
{"LogToOpenFile", sm_LogToOpenFile},
{"LogToOpenFileEx", sm_LogToOpenFileEx},
{"ReadFile", sm_ReadFile},
{"ReadFileString", sm_ReadFileString},
{"WriteFile", sm_WriteFile},
{"WriteFileString", sm_WriteFileString},
{NULL, NULL},
};

View File

@ -158,6 +158,112 @@ native bool:DeleteFile(const String:path[]);
*/
native bool:ReadFileLine(Handle:hndl, String:buffer[], maxlength);
/**
* Reads binary data from a file.
*
* @param hndl Handle to the file.
* @param items Array to store each item read.
* @param num_items Number of items to read into the array.
* @param size Size of each element, in bytes, to be read.
* Valid sizes are 1, 2, or 4.
* @return Number of elements read, or -1 on error.
*/
native ReadFile(Handle:hndl, items[], num_items, size);
/**
* Reads a UTF8 or ANSI string from a file.
*
* @param hndl Handle to the file.
* @param buffer Buffer to store the string.
* @param max_size Maximum size of the string buffer.
* @param stop If true, reading will stop once max_size-1 bytes have
* been read. If false, reading will stop once a NUL
* terminator is reached. The buffer will simply be
* terminated in either case, the difference is in how
* the far the file position is changed.
* @return Number of characters written to the buffer, or -1
* if an error was encountered.
* @error Invalid Handle, or read_count > max_size.
*/
native ReadFileString(Handle:hndl, String:buffer[], max_size, read_count=-1);
/**
* Writes binary data to a file.
*
* @param hndl Handle to the file.
* @param items Array of items to write. The data is read directly.
* That is, in 1 or 2-byte mode, the lower byte(s) in
* each cell are used directly, rather than performing
* any casts from a 4-byte number to a smaller number.
* @param num_items Number of items in the array.
* @param size Size of each item in the array in bytes.
* Valid sizes are 1, 2, or 4.
* @return True on success, false on error.
*/
native bool:WriteFile(Handle:hndl, const items[], num_items, size);
/**
* Writes a binary string to a file.
*
* @param hndl Handle to th efile.
* @param buffer String to write.
* @param term True to append NUL terminator, false otherwise.
* @return True on success, false on error.
*/
native bool:WriteFileString(Handle:hndl, const String:buffer[], bool:term);
/**
* Writes a line of text to a text file. A newline is automatically appended.
*
* @param hndl Handle to the file.
* @param format Formatting rules.
* @param ... Variable number of format parameters.
* @return True on success, false otherwise.
*/
native bool:WriteFileLine(Handle:hndl, const String:format[], any:...);
/**
* Reads a single binary cell from a file.
*
* @param hndl Handle to the file.
* @param data Variable to store the data read.
* @param size Size of the data to read in bytes. Valid
* sizes are 1, 2, or 4 bytes.
* @return Number of elements read (max 1), or -1 on error.
*/
stock ReadFileCell(Handle:hndl, &data, size)
{
new array[1], ret;
if ((ret = ReadFile(hndl, array, 1, size)) == 1)
{
data = array[0];
}
return ret;
}
/**
* Writes a single binary cell to a file.
*
* @param hndl Handle to the file.
* @param data Cell to write to the file.
* @param size Size of the data to read in bytes. Valid
* sizes are 1, 2, or 4 bytes. If the size
* is less than 4 bytes, the data is truncated
* rather than casted. That is, only the lower
* bits will be read.
* @return True on success, false on error.
*/
stock bool:WriteFileCell(Handle:hndl, data, size)
{
new array[1];
array[0] = data;
return WriteFile(hndl, array, 1, size);
}
/**
* Tests if the end of file has been reached.
*
@ -171,10 +277,10 @@ native bool:IsEndOfFile(Handle:file);
*
* @param file Handle to the file.
* @param position Position relative to what is specified in whence.
* @param whence Look at the SEEK_* definitions.
* @param where SEEK_ constant value of where to see from.
* @return True on success, false otherwise.
*/
native bool:FileSeek(Handle:file, position, whence);
native bool:FileSeek(Handle:file, position, where);
/**
* Get current position in the file.
@ -235,17 +341,6 @@ native FlushFile(Handle:file);
*/
native bool:RemoveDir(const String:path[]);
/**
* Writes a line of text in a file.
* @note This native will append the newline character.
*
* @param hndl Handle to the file.
* @param format Formatting rules.
* @param ... Variable number of format parameters.
* @return True on success, false otherwise.
*/
native bool:WriteFileLine(Handle:hndl, const String:format[], any:...);
/**
* Returns a file timestamp as a unix timestamp.
*