Add more functions to ArrayStack (#2019)

* Add more functions to ArrayStack

* Make formatting consistent with other functions

* Don't remove the element for TopArray

* Replace 4 with sizeof(cell_t)
This commit is contained in:
Mikusch 2023-09-27 15:43:04 +02:00 committed by GitHub
parent 0656696251
commit 1e8db957bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 123 additions and 4 deletions

View File

@ -240,9 +240,9 @@ static cell_t PopStackCell(IPluginContext *pContext, const cell_t *params)
}
else
{
if (idx >= array->blocksize() * 4)
if (idx >= array->blocksize() * sizeof(cell_t))
{
return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * sizeof(cell_t));
}
*buffer = (cell_t)*((char *)blk + idx);
}
@ -356,8 +356,8 @@ static cell_t ArrayStack_Pop(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
rval = blk[idx];
} else {
if (idx >= array->blocksize() * 4)
return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * 4);
if (idx >= array->blocksize() * sizeof(cell_t))
return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * sizeof(cell_t));
rval = (cell_t)*((char *)blk + idx);
}
@ -365,6 +365,32 @@ static cell_t ArrayStack_Pop(IPluginContext *pContext, const cell_t *params)
return rval;
}
static cell_t ArrayStack_Top(IPluginContext *pContext, const cell_t *params)
{
OpenHandle<CellArray> array(pContext, params[1], htCellStack);
if (!array.Ok())
return 0;
if (array->size() == 0)
return pContext->ThrowNativeError("stack is empty");
cell_t *blk = array->at(array->size() - 1);
size_t idx = (size_t)params[2];
cell_t rval;
if (params[3] == 0) {
if (idx >= array->blocksize())
return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", idx, array->blocksize());
rval = blk[idx];
} else {
if (idx >= array->blocksize() * sizeof(cell_t))
return pContext->ThrowNativeError("Invalid byte %d (blocksize: %d bytes)", idx, array->blocksize() * sizeof(cell_t));
rval = (cell_t)*((char *)blk + idx);
}
return rval;
}
static cell_t ArrayStack_PopString(IPluginContext *pContext, const cell_t *params)
{
OpenHandle<CellArray> array(pContext, params[1], htCellStack);
@ -387,6 +413,27 @@ static cell_t ArrayStack_PopString(IPluginContext *pContext, const cell_t *param
return 1;
}
static cell_t ArrayStack_TopString(IPluginContext *pContext, const cell_t *params)
{
OpenHandle<CellArray> array(pContext, params[1], htCellStack);
if (!array.Ok())
return 0;
if (array->size() == 0)
return pContext->ThrowNativeError("stack is empty");
size_t idx = array->size() - 1;
cell_t *blk = array->at(idx);
cell_t *pWritten;
pContext->LocalToPhysAddr(params[4], &pWritten);
size_t numWritten;
pContext->StringToLocalUTF8(params[2], params[3], (char *)blk, &numWritten);
*pWritten = (cell_t)numWritten;
return 1;
}
static cell_t ArrayStack_PopArray(IPluginContext *pContext, const cell_t *params)
{
OpenHandle<CellArray> array(pContext, params[1], htCellStack);
@ -411,6 +458,29 @@ static cell_t ArrayStack_PopArray(IPluginContext *pContext, const cell_t *params
return 0;
}
static cell_t ArrayStack_TopArray(IPluginContext *pContext, const cell_t *params)
{
OpenHandle<CellArray> array(pContext, params[1], htCellStack);
if (!array.Ok())
return 0;
if (array->size() == 0)
return pContext->ThrowNativeError("stack is empty");
cell_t *addr;
pContext->LocalToPhysAddr(params[2], &addr);
size_t idx = array->size() - 1;
cell_t *blk = array->at(idx);
size_t indexes = array->blocksize();
if (params[3] != -1 && (size_t)params[3] <= array->blocksize())
indexes = params[3];
memcpy(addr, blk, sizeof(cell_t) * indexes);
return 0;
}
static cell_t GetStackBlockSize(IPluginContext *pContext, const cell_t *params)
{
HandleError err;
@ -426,6 +496,21 @@ static cell_t GetStackBlockSize(IPluginContext *pContext, const cell_t *params)
return array->blocksize();
}
static cell_t GetStackSize(IPluginContext *pContext, const cell_t *params)
{
HandleError err;
CellArray *array;
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
}
return array->size();
}
REGISTER_NATIVES(cellStackNatives)
{
{"CreateStack", CreateStack},
@ -444,13 +529,17 @@ REGISTER_NATIVES(cellStackNatives)
{"ArrayStack.Clear", ClearStack},
{"ArrayStack.Clone", CloneStack},
{"ArrayStack.Pop", ArrayStack_Pop},
{"ArrayStack.Top", ArrayStack_Top},
{"ArrayStack.PopString", ArrayStack_PopString},
{"ArrayStack.TopString", ArrayStack_TopString},
{"ArrayStack.PopArray", ArrayStack_PopArray},
{"ArrayStack.TopArray", ArrayStack_TopArray},
{"ArrayStack.Push", PushStackCell},
{"ArrayStack.PushString", PushStackString},
{"ArrayStack.PushArray", PushStackArray},
{"ArrayStack.Empty.get", IsStackEmpty},
{"ArrayStack.BlockSize.get", GetStackBlockSize},
{"ArrayStack.Length.get", GetStackSize},
{NULL, NULL},
};

View File

@ -99,6 +99,15 @@ methodmap ArrayStack < Handle
// @error The stack is empty.
public native any Pop(int block=0, bool asChar=false);
// Reads a cell value from a stack without removing it.
//
// @param block Optionally specify which block to read from
// (useful if the blocksize > 0).
// @param asChar Optionally read as a byte instead of a cell.
// @return Value read from the stack.
// @error The stack is empty.
public native any Top(int block=0, bool asChar=false);
// Pops a string value from a stack.
//
// @param buffer Buffer to store string.
@ -108,6 +117,15 @@ methodmap ArrayStack < Handle
// @error The stack is empty.
public native void PopString(char[] buffer, int maxlength, int &written = 0);
// Reads a string value from a stack without removing it.
//
// @param buffer Buffer to store string.
// @param maxlength Maximum size of the buffer.
// @param written Number of characters written to buffer, not including
// the null terminator.
// @error The stack is empty.
public native void TopString(char[] buffer, int maxlength, int &written = 0);
// Pops an array of cells from a stack.
//
// @param buffer Buffer to store the array in.
@ -116,6 +134,14 @@ methodmap ArrayStack < Handle
// @error The stack is empty.
public native void PopArray(any[] buffer, int size=-1);
// Reads an array of cells from a stack without removing it.
//
// @param buffer Buffer to store the array in.
// @param size If not set, assumes the buffer size is equal to the
// blocksize. Otherwise, the size passed is used.
// @error The stack is empty.
public native void TopArray(any[] buffer, int size=-1);
// Returns true if the stack is empty, false otherwise.
property bool Empty {
public native get();
@ -125,6 +151,10 @@ methodmap ArrayStack < Handle
property int BlockSize {
public native get();
}
property int Length {
public native get();
}
};
/**