Add an array operations to CDataPack (#1219)

This commit is contained in:
Deathreus 2020-05-08 18:23:48 -04:00 committed by GitHub
parent bc89e54f6d
commit 13621a1274
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 291 additions and 1 deletions

View File

@ -123,6 +123,28 @@ void CDataPack::PackString(const char *string)
elements.insert(position++, val);
}
void CDataPack::PackCellArray(cell_t const *vals, cell_t count)
{
InternalPack val;
val.type = CDataPackType::CellArray;
val.pData.aval = new cell_t [count + 1];
memcpy(&val.pData.aval[1], vals, sizeof(cell_t) * (count + 1));
val.pData.aval[0] = count;
elements.insert(position++, val);
}
void CDataPack::PackFloatArray(cell_t const *vals, cell_t count)
{
InternalPack val;
val.type = CDataPackType::FloatArray;
val.pData.aval = new cell_t [count + 1];
memcpy(&val.pData.aval[1], vals, sizeof(cell_t) * (count + 1));
val.pData.aval[0] = count;
elements.insert(position++, val);
}
void CDataPack::Reset() const
{
position = 0;
@ -188,6 +210,46 @@ const char *CDataPack::ReadString(size_t *len) const
return val.chars();
}
cell_t *CDataPack::ReadCellArray(cell_t *size) const
{
if (!IsReadable() || elements[position].type != CDataPackType::CellArray)
{
if(size)
*size = 0;
return nullptr;
}
cell_t *val = elements[position].pData.aval;
cell_t *ptr = &(val[1]);
++position;
if (size)
*size = val[0];
return ptr;
}
cell_t *CDataPack::ReadFloatArray(cell_t *size) const
{
if (!IsReadable() || elements[position].type != CDataPackType::FloatArray)
{
if(size)
*size = 0;
return nullptr;
}
cell_t *val = elements[position].pData.aval;
cell_t *ptr = &(val[1]);
++position;
if (size)
*size = val[0];
return ptr;
}
void *CDataPack::ReadMemory(size_t *size) const
{
void *ptr = nullptr;
@ -239,6 +301,13 @@ bool CDataPack::RemoveItem(size_t pos)
delete elements[pos].pData.sval;
break;
}
case CDataPackType::CellArray:
case CDataPackType::FloatArray:
{
delete elements[pos].pData.aval;
break;
}
}
elements.remove(pos);

View File

@ -43,7 +43,9 @@ enum CDataPackType {
Cell,
Float,
String,
Function
Function,
CellArray,
FloatArray,
};
class CDataPack
@ -90,6 +92,21 @@ public: // Originally IDataReader
*/
float ReadFloat() const;
/**
* @brief Reads an array of values from the data stream.
*
* @param len The size of the array stored at this position to return.
* @return A cell array read from the current position.
*/
cell_t *ReadCellArray(cell_t *len) const;
/**
* @brief Reads an array of values from the data stream.
*
* @param len The size of the array stored at this position to return.
* @return A cell array read from the current position.
*/
cell_t *ReadFloatArray(cell_t *len) const;
/**
* @brief Returns whether or not a specified number of bytes from the current stream
* position to the end can be read.
@ -150,6 +167,21 @@ public: // Originally IDataPack
*/
void PackString(const char *string);
/**
* @brief Packs an array of cells into the data stream.
*
* @param vals Cells to write.
* @param count Number of cells.
*/
void PackCellArray(cell_t const *vals, cell_t count);
/**
* @brief Packs an array of cells into the data stream.
*
* @param vals Cells to write.
* @param count Number of cells.
*/
void PackFloatArray(cell_t const *vals, cell_t count);
/**
* @brief Creates a generic block of memory in the stream.
*
@ -182,6 +214,7 @@ private:
float fval;
uint8_t *vval;
ke::AString *sval;
cell_t *aval;
} InternalPackValue;
typedef struct {

View File

@ -166,6 +166,62 @@ static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params
return 1;
}
static cell_t smn_WritePackCellArray(IPluginContext *pContext, const cell_t *params)
{
HandleError herr;
HandleSecurity sec;
sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent;
Handle_t hndl = static_cast<Handle_t>(params[1]);
CDataPack *pDataPack = nullptr;
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
pContext->ReportError("Invalid data pack handle %x (error %d).", hndl, herr);
return 0;
}
if (!params[4])
{
pDataPack->RemoveItem();
}
cell_t *pArray;
pContext->LocalToPhysAddr(params[2], &pArray);
pDataPack->PackCellArray(pArray, params[3]);
return 1;
}
static cell_t smn_WritePackFloatArray(IPluginContext *pContext, const cell_t *params)
{
HandleError herr;
HandleSecurity sec;
sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent;
Handle_t hndl = static_cast<Handle_t>(params[1]);
CDataPack *pDataPack = nullptr;
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
pContext->ReportError("Invalid data pack handle %x (error %d).", hndl, herr);
return 0;
}
if (!params[4])
{
pDataPack->RemoveItem();
}
cell_t *pArray;
pContext->LocalToPhysAddr(params[2], &pArray);
pDataPack->PackFloatArray(pArray, params[3]);
return 1;
}
static cell_t smn_WritePackFunction(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
@ -312,6 +368,108 @@ static cell_t smn_ReadPackFunction(IPluginContext *pContext, const cell_t *param
return pDataPack->ReadFunction();
}
static cell_t smn_ReadPackCellArray(IPluginContext *pContext, const cell_t *params)
{
HandleError herr;
HandleSecurity sec;
sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent;
Handle_t hndl = static_cast<Handle_t>(params[1]);
CDataPack *pDataPack = nullptr;
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
pContext->ReportError("Invalid data pack handle %x (error %d).", hndl, herr);
return 0;
}
if (!pDataPack->IsReadable())
{
pContext->ReportError("Data pack operation is out of bounds.");
return 0;
}
if (pDataPack->GetCurrentType() != CDataPackType::CellArray)
{
pContext->ReportError("Invalid data pack type (got %d / expected %d).", pDataPack->GetCurrentType(), CDataPackType::CellArray);
return 0;
}
cell_t packCount = 0;
cell_t *pData = pDataPack->ReadCellArray(&packCount);
if(pData == nullptr || packCount == 0)
{
pContext->ReportError("Invalid data pack operation: current position isn't an array!");
return 0;
}
cell_t count = params[3];
if(packCount > count)
{
pContext->ReportError("Input buffer too small (needed %d, got %d).", packCount, count);
return 0;
}
cell_t *pArray;
pContext->LocalToPhysAddr(params[2], &pArray);
memcpy(pArray, pData, sizeof(cell_t) * count);
return 1;
}
static cell_t smn_ReadPackFloatArray(IPluginContext *pContext, const cell_t *params)
{
HandleError herr;
HandleSecurity sec;
sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent;
Handle_t hndl = static_cast<Handle_t>(params[1]);
CDataPack *pDataPack = nullptr;
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
pContext->ReportError("Invalid data pack handle %x (error %d).", hndl, herr);
return 0;
}
if (!pDataPack->IsReadable())
{
pContext->ReportError("Data pack operation is out of bounds.");
return 0;
}
if (pDataPack->GetCurrentType() != CDataPackType::FloatArray)
{
pContext->ReportError("Invalid data pack type (got %d / expected %d).", pDataPack->GetCurrentType(), CDataPackType::FloatArray);
return 0;
}
cell_t packCount = 0;
cell_t *pData = pDataPack->ReadFloatArray(&packCount);
if(pData == nullptr || packCount == 0)
{
pContext->ReportError("Invalid data pack operation: current position isn't an array!");
return 0;
}
cell_t count = params[3];
if(packCount > count)
{
pContext->ReportError("Input buffer too small (needed %d, got %d).", packCount, count);
return 0;
}
cell_t *pArray;
pContext->LocalToPhysAddr(params[2], &pArray);
memcpy(pArray, pData, sizeof(cell_t) * count);
return 1;
}
static cell_t smn_ResetPack(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
@ -426,10 +584,14 @@ REGISTER_NATIVES(datapacknatives)
{"DataPack.WriteFloat", smn_WritePackFloat},
{"DataPack.WriteString", smn_WritePackString},
{"DataPack.WriteFunction", smn_WritePackFunction},
{"DataPack.WriteCellArray", smn_WritePackCellArray},
{"DataPack.WriteFloatArray", smn_WritePackFloatArray},
{"DataPack.ReadCell", smn_ReadPackCell},
{"DataPack.ReadFloat", smn_ReadPackFloat},
{"DataPack.ReadString", smn_ReadPackString},
{"DataPack.ReadFunction", smn_ReadPackFunction},
{"DataPack.ReadCellArray", smn_ReadPackCellArray},
{"DataPack.ReadFloatArray", smn_ReadPackFloatArray},
{"DataPack.Reset", smn_ResetPack},
{"DataPack.Position.get", smn_GetPackPosition},
{"DataPack.Position.set", smn_SetPackPosition},

View File

@ -71,6 +71,20 @@ methodmap DataPack < Handle
// @param insert Determines whether mid-pack writes will insert instead of overwrite.
public native void WriteFunction(Function fktptr, bool insert = false);
// Packs an array of cells into a data pack.
//
// @param array Array to add.
// @param count Number of elements
// @param insert Determines whether mid-pack writes will insert instead of overwrite.
public native void WriteCellArray(const any[] array, int count, bool insert = false);
// Packs an array of floats into a data pack.
//
// @param array Array to add.
// @param count Number of elements
// @param insert Determines whether mid-pack writes will insert instead of overwrite.
public native void WriteFloatArray(const float[] array, int count, bool insert = false);
// Reads a cell from a data pack.
//
// @return A cell at this position
@ -92,6 +106,18 @@ methodmap DataPack < Handle
// @return Function pointer.
public native Function ReadFunction();
// Reads an array of cells a data pack.
//
// @param buffer Destination buffer.
// @param count Maximum length of output buffer.
public native void ReadCellArray(any[] buffer, int count);
// Reads an array of floats from a data pack.
//
// @param buffer Destination buffer.
// @param count Maximum length of output buffer.
public native void ReadFloatArray(float[] buffer, int count);
// Resets the position in a data pack.
//
// @param clear If true, clears the contained data.