Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WritePackFunction and ReadPackFunction natives #122

Merged
merged 1 commit into from
Aug 12, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
94 changes: 84 additions & 10 deletions core/CDataPack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,12 @@ void CDataPack::ResetSize()

size_t CDataPack::CreateMemory(size_t size, void **addr)
{
CheckSize(sizeof(size_t) + size);
CheckSize(sizeof(char) + sizeof(size_t) + size);
size_t pos = m_curptr - m_pBase;

*(char *)m_curptr = Raw;
m_curptr += sizeof(char);

*(size_t *)m_curptr = size;
m_curptr += sizeof(size_t);

Expand All @@ -88,43 +91,52 @@ size_t CDataPack::CreateMemory(size_t size, void **addr)
}

m_curptr += size;
m_size += sizeof(size_t) + size;
m_size += sizeof(char) + sizeof(size_t) + size;

return pos;
}

void CDataPack::PackCell(cell_t cell)
{
CheckSize(sizeof(size_t) + sizeof(cell_t));
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));

*(char *)m_curptr = Cell;
m_curptr += sizeof(char);

*(size_t *)m_curptr = sizeof(cell_t);
m_curptr += sizeof(size_t);

*(cell_t *)m_curptr = cell;
m_curptr += sizeof(cell_t);

m_size += sizeof(size_t) + sizeof(cell_t);
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
}

void CDataPack::PackFloat(float val)
{
CheckSize(sizeof(size_t) + sizeof(float));
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(float));

*(char *)m_curptr = Float;
m_curptr += sizeof(char);

*(size_t *)m_curptr = sizeof(float);
m_curptr += sizeof(size_t);

*(float *)m_curptr = val;
m_curptr += sizeof(float);

m_size += sizeof(size_t) + sizeof(float);
m_size += sizeof(char) + sizeof(size_t) + sizeof(float);
}

void CDataPack::PackString(const char *string)
{
size_t len = strlen(string);
size_t maxsize = sizeof(size_t) + len + 1;
size_t maxsize = sizeof(char) + sizeof(size_t) + len + 1;
CheckSize(maxsize);

*(char *)m_curptr = String;
m_curptr += sizeof(char);

// Pack the string length first for buffer overrun checking.
*(size_t *)m_curptr = len;
m_curptr += sizeof(size_t);
Expand Down Expand Up @@ -160,10 +172,16 @@ bool CDataPack::SetPosition(size_t pos) const

cell_t CDataPack::ReadCell() const
{
if (!IsReadable(sizeof(size_t) + sizeof(cell_t)))
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
{
return 0;
}
if (*reinterpret_cast<char *>(m_curptr) != Cell)
{
return 0;
}
m_curptr += sizeof(char);

if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
{
return 0;
Expand All @@ -178,10 +196,16 @@ cell_t CDataPack::ReadCell() const

float CDataPack::ReadFloat() const
{
if (!IsReadable(sizeof(size_t) + sizeof(float)))
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
{
return 0;
}
if (*reinterpret_cast<char *>(m_curptr) != Float)
{
return 0;
}
m_curptr += sizeof(char);

if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
{
return 0;
Expand All @@ -201,10 +225,15 @@ bool CDataPack::IsReadable(size_t bytes) const

const char *CDataPack::ReadString(size_t *len) const
{
if (!IsReadable(sizeof(size_t)))
if (!IsReadable(sizeof(char) + sizeof(size_t)))
{
return NULL;
}
if (*reinterpret_cast<char *>(m_curptr) != String)
{
return NULL;
}
m_curptr += sizeof(char);

size_t real_len = *(size_t *)m_curptr;

Expand Down Expand Up @@ -237,6 +266,11 @@ void *CDataPack::ReadMemory(size_t *size) const
{
return NULL;
}
if (*reinterpret_cast<char *>(m_curptr) != Raw)
{
return NULL;
}
m_curptr += sizeof(char);

size_t bytecount = *(size_t *)m_curptr;
m_curptr += sizeof(size_t);
Expand All @@ -257,3 +291,43 @@ void *CDataPack::ReadMemory(size_t *size) const

return ptr;
}

void CDataPack::PackFunction(cell_t function)
{
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));

*(char *)m_curptr = Function;
m_curptr += sizeof(char);

*(size_t *)m_curptr = sizeof(cell_t);
m_curptr += sizeof(size_t);

*(cell_t *)m_curptr = function;
m_curptr += sizeof(cell_t);

m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
}

cell_t CDataPack::ReadFunction() const
{
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
{
return 0;
}
if (*reinterpret_cast<char *>(m_curptr) != Function)
{
return 0;
}
m_curptr += sizeof(char);

if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
{
return 0;
}

m_curptr += sizeof(size_t);

cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
m_curptr += sizeof(cell_t);
return val;
}
10 changes: 10 additions & 0 deletions core/CDataPack.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,14 @@ class CDataPack : public IDataPack
const char *ReadString(size_t *len) const;
void *GetMemory() const;
void *ReadMemory(size_t *size) const;
cell_t ReadFunction() const;
public: //IDataPack
void ResetSize();
void PackCell(cell_t cell);
void PackFloat(float val);
void PackString(const char *string);
size_t CreateMemory(size_t size, void **addr);
void PackFunction(cell_t function);
public:
void Initialize();
private:
Expand All @@ -66,6 +68,14 @@ class CDataPack : public IDataPack
mutable char *m_curptr;
size_t m_capacity;
size_t m_size;

enum DataPackType {
Raw,
Cell,
Float,
String,
Function
};
};

#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
51 changes: 49 additions & 2 deletions core/logic/smn_datapacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,27 @@ static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params
return 1;
}

static cell_t smn_WritePackFunction(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;

sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent;

if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}

pDataPack->PackFunction(params[2]);

return 1;
}

static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
Expand All @@ -164,7 +185,7 @@ static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}

if (!pDataPack->IsReadable(sizeof(size_t) + sizeof(cell_t)))
if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
{
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
}
Expand All @@ -188,7 +209,7 @@ static cell_t smn_ReadPackFloat(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}

if (!pDataPack->IsReadable(sizeof(size_t) + sizeof(float)))
if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
{
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
}
Expand Down Expand Up @@ -223,6 +244,30 @@ static cell_t smn_ReadPackString(IPluginContext *pContext, const cell_t *params)
return 1;
}

static cell_t smn_ReadPackFunction(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;

sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent;

if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}

if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
{
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
}

return pDataPack->ReadFunction();
}

static cell_t smn_ResetPack(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
Expand Down Expand Up @@ -318,9 +363,11 @@ REGISTER_NATIVES(datapacknatives)
{"WritePackCell", smn_WritePackCell},
{"WritePackFloat", smn_WritePackFloat},
{"WritePackString", smn_WritePackString},
{"WritePackFunction", smn_WritePackFunction},
{"ReadPackCell", smn_ReadPackCell},
{"ReadPackFloat", smn_ReadPackFloat},
{"ReadPackString", smn_ReadPackString},
{"ReadPackFunction", smn_ReadPackFunction},
{"ResetPack", smn_ResetPack},
{"GetPackPosition", smn_GetPackPosition},
{"SetPackPosition", smn_SetPackPosition},
Expand Down
19 changes: 19 additions & 0 deletions plugins/include/datapack.inc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ native WritePackFloat(Handle:pack, Float:val);
*/
native WritePackString(Handle:pack, const String:str[]);

/**
* Packs a function pointer into a data pack.
*
* @param pack Handle to the data pack.
* @param fktptr Function pointer to add.
* @noreturn
* @error Invalid handle.
*/
native WritePackFunction(Handle:pack, Function:fktptr);

/**
* Reads a cell from a data pack.
*
Expand Down Expand Up @@ -101,6 +111,15 @@ native Float:ReadPackFloat(Handle:pack);
*/
native ReadPackString(Handle:pack, String:buffer[], maxlen);

/**
* Reads a function pointer from a data pack.
*
* @param pack Handle to the data pack.
* @return Function pointer.
* @error Invalid handle, or bounds error.
*/
native Function ReadPackFunction(Handle:pack);

/**
* Resets the position in a data pack.
*
Expand Down
14 changes: 14 additions & 0 deletions public/IDataPack.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ namespace SourceMod
* @return Pointer to the data, or NULL if out of bounds.
*/
virtual void *ReadMemory(size_t *size) const =0;

/**
* @brief Reads a function pointer from the data stream.
*
* @return A function pointer read from the current position.
*/
virtual cell_t ReadFunction() const =0;
};

/**
Expand Down Expand Up @@ -160,6 +167,13 @@ namespace SourceMod
* @return Current position of the stream beforehand.
*/
virtual size_t CreateMemory(size_t size, void **addr) =0;

/**
* @brief Packs one function pointer into the data stream.
*
* @param function The function pointer to write.
*/
virtual void PackFunction(cell_t function) =0;
};
}

Expand Down