initial implementation of data packs

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40490
This commit is contained in:
Borja Ferrer 2007-02-13 16:11:04 +00:00
parent fbeabce6bf
commit 1ff370b91d
8 changed files with 597 additions and 16 deletions

176
core/CDataPack.cpp Normal file
View File

@ -0,0 +1,176 @@
#include <malloc.h>
#include <string.h>
#include "CDataPack.h"
#define DATAPACK_INITIAL_SIZE 512
CDataPack::CDataPack()
{
m_pBase = (char *)malloc(DATAPACK_INITIAL_SIZE);
m_capacity = DATAPACK_INITIAL_SIZE;
Initialize();
}
CDataPack::~CDataPack()
{
free(m_pBase);
}
void CDataPack::Initialize()
{
m_curptr = m_pBase;
m_size = 0;
}
void CDataPack::CheckSize(size_t typesize)
{
if (m_curptr - m_pBase + typesize <= m_capacity)
{
return;
}
size_t pos = m_curptr - m_pBase;
do
{
m_capacity *= 2;
m_pBase = (char *)realloc(m_pBase, m_capacity);
m_curptr = m_pBase + pos;
} while (m_curptr - m_pBase + typesize > m_capacity);
}
void CDataPack::ResetSize()
{
m_size = 0;
}
size_t CDataPack::CreateMemory(size_t size, void **addr)
{
size_t pos = m_curptr - m_pBase;
m_pBase = (char *)realloc(m_pBase, size);
m_curptr = m_pBase + pos;
m_capacity = size;
if (addr)
{
*addr = m_pBase;
}
return pos;
}
void CDataPack::PackCell(cell_t cell)
{
CheckSize(sizeof(cell_t));
*(cell_t *)m_curptr = cell;
m_curptr += sizeof(cell_t);
m_size += sizeof(cell_t);
}
void CDataPack::PackFloat(float val)
{
CheckSize(sizeof(float));
*(float *)m_curptr = val;
m_curptr += sizeof(float);
m_size += sizeof(float);
}
void CDataPack::PackString(const char *string)
{
size_t len = strlen(string);
size_t maxsize = sizeof(size_t) + len + 1;
CheckSize(maxsize);
// Pack the string length first for buffer overrun checking.
*(size_t *)m_curptr = len;
m_curptr += sizeof(size_t);
// Now pack the string.
memcpy(m_curptr, string, len);
m_curptr[len] = '\0';
m_curptr += len + 1;
m_size += maxsize;
}
void CDataPack::Reset() const
{
m_curptr = m_pBase;
}
size_t CDataPack::GetPosition() const
{
return static_cast<size_t>(m_curptr - m_pBase);
}
bool CDataPack::SetPosition(size_t pos) const
{
if (pos > m_size-1)
{
return false;
}
m_curptr = m_pBase + pos;
return true;
}
cell_t CDataPack::ReadCell() const
{
if (!IsReadable(sizeof(cell_t)))
{
return 0;
}
cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
m_curptr += sizeof(cell_t);
return val;
}
float CDataPack::ReadFloat() const
{
if (!IsReadable(sizeof(float)))
{
return 0;
}
float val = *reinterpret_cast<float *>(m_curptr);
m_curptr += sizeof(float);
return val;
}
bool CDataPack::IsReadable(size_t bytes) const
{
return (bytes + (m_curptr - m_pBase) > m_size) ? false : true;
}
const char *CDataPack::ReadString(size_t *len) const
{
if (!IsReadable(sizeof(size_t)))
{
return 0;
}
size_t real_len = *(size_t *)m_curptr;
m_curptr += sizeof(size_t);
char *str = (char *)m_curptr;
if ((strlen(str) != real_len) || !(IsReadable(real_len+1)))
{
return NULL;
}
if (len)
{
*len = real_len;
}
m_curptr += real_len + 1;
return str;
}
void *CDataPack::GetMemory() const
{
return m_curptr;
}

53
core/CDataPack.h Normal file
View File

@ -0,0 +1,53 @@
/**
* vim: set ts=4 :
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is not open source and may not be copied without explicit
* written permission of AlliedModders LLC. This file may not be redistributed
* in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_CDATAPACK_H_
#define _INCLUDE_SOURCEMOD_CDATAPACK_H_
#include <IDataPack.h>
using namespace SourceMod;
class CDataPack : public IDataPack
{
public:
CDataPack();
~CDataPack();
public: //IDataReader
void Reset() const;
size_t GetPosition() const;
bool SetPosition(size_t pos) const;
cell_t ReadCell() const;
float ReadFloat() const;
bool IsReadable(size_t bytes) const;
const char *ReadString(size_t *len) const;
void *GetMemory() 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);
public:
void Initialize();
private:
void CheckSize(size_t sizetype);
private:
char *m_pBase;
mutable char *m_curptr;
size_t m_capacity;
size_t m_size;
};
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="sourcemod_mm"
ProjectGUID="{E39527CD-7CAB-4420-97CC-DA1B93B260BC}"
RootNamespace="sourcemod_mm"
@ -187,6 +187,10 @@
RelativePath="..\CConVarManager.cpp"
>
</File>
<File
RelativePath="..\CDataPack.cpp"
>
</File>
<File
RelativePath="..\CDbgReporter.cpp"
>
@ -235,6 +239,10 @@
RelativePath="..\smn_convar.cpp"
>
</File>
<File
RelativePath="..\smn_datapacks.cpp"
>
</File>
<File
RelativePath="..\smn_filesystem.cpp"
>
@ -285,6 +293,10 @@
RelativePath="..\CConVarManager.h"
>
</File>
<File
RelativePath="..\CDataPack.h"
>
</File>
<File
RelativePath="..\CDbgReporter.h"
>

288
core/smn_datapacks.cpp Normal file
View File

@ -0,0 +1,288 @@
#include "sm_globals.h"
#include "HandleSys.h"
#include "CDataPack.h"
HandleType_t g_DataPackType;
class DataPackNatives :
public SMGlobalClass,
public IHandleTypeDispatch
{
public:
void OnSourceModAllInitialized()
{
g_DataPackType = g_HandleSys.CreateType("DataPack", this, 0, NULL, NULL, g_pCoreIdent, NULL);
}
void OnSourceModShutdown()
{
g_HandleSys.RemoveType(g_DataPackType, g_pCoreIdent);
g_DataPackType = 0;
}
void OnHandleDestroy(HandleType_t type, void *object)
{
g_SourceMod.FreeDataPack(reinterpret_cast<IDataPack *>(object));
}
};
static cell_t smn_CreateDataPack(IPluginContext *pContext, const cell_t *params)
{
IDataPack *pDataPack = g_SourceMod.CreateDataPack();
if (!pDataPack)
{
return 0;
}
return g_HandleSys.CreateHandle(g_DataPackType, pDataPack, pContext->GetIdentity(), g_pCoreIdent, NULL);
}
static cell_t smn_WritePackCell(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}
pDataPack->PackCell(params[2]);
return 1;
}
static cell_t smn_WritePackFloat(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}
pDataPack->PackFloat(sp_ctof(params[2]));
return 1;
}
static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;
int err;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}
char *str;
if ((err=pContext->LocalToString(params[2], &str)) != SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(err, NULL);
return 0;
}
pDataPack->PackString(str);
return 1;
}
static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_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(cell_t)))
{
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
}
return pDataPack->ReadCell();
}
static cell_t smn_ReadPackFloat(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_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(float)))
{
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
}
return sp_ftoc(pDataPack->ReadFloat());
}
static cell_t smn_ReadPackString(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}
const char *str;
if (!(str=pDataPack->ReadString(NULL)))
{
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
}
pContext->StringToLocal(params[2], params[3], str);
return 1;
}
static cell_t smn_ResetPack(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}
pDataPack->Reset();
if (params[2])
{
pDataPack->ResetSize();
}
return 1;
}
static cell_t smn_GetPackPosition(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}
return static_cast<cell_t>(pDataPack->GetPosition());
}
static cell_t smn_SetPackPosition(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}
if (!pDataPack->SetPosition(params[2]))
{
return pContext->ThrowNativeError("Invalid DataPack position, %d is out of bounds", params[2]);
}
return 1;
}
static cell_t smn_IsPackReadable(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IDataPack *pDataPack;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=g_HandleSys.ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr);
}
return pDataPack->IsReadable(params[2]) ? 1 : 0;
}
static DataPackNatives s_DataPackNatives;
REGISTER_NATIVES(datapacknatives)
{
{"CreateDataPack", smn_CreateDataPack},
{"WritePackCell", smn_WritePackCell},
{"WritePackFloat", smn_WritePackFloat},
{"WritePackString", smn_WritePackString},
{"ReadPackCell", smn_ReadPackCell},
{"ReadPackFloat", smn_ReadPackFloat},
{"ReadPackString", smn_ReadPackString},
{"ResetPack", smn_ResetPack},
{"GetPackPosition", smn_GetPackPosition},
{"SetPackPosition", smn_SetPackPosition},
{"IsPackReadable", smn_IsPackReadable},
{NULL, NULL}
};

View File

@ -226,7 +226,7 @@ void SourceModBase::LevelShutdown()
}
}
bool SourceModBase::IsMapLoading()
bool SourceModBase::IsMapLoading() const
{
return m_IsMapLoading;
}
@ -296,6 +296,16 @@ void SourceModBase::CloseSourceMod()
pBase = pBase->m_pGlobalClassNext;
}
/* Delete all data packs */
CStack<CDataPack *>::iterator iter;
CDataPack *pd;
for (iter=m_freepacks.begin(); iter!=m_freepacks.end(); iter++)
{
pd = (*iter);
delete pd;
}
m_freepacks.popall();
/* Notify! */
pBase = SMGlobalClass::head;
while (pBase)
@ -361,12 +371,12 @@ size_t SourceModBase::FormatString(char *buffer, size_t maxlength, IPluginContex
return atcprintf(buffer, maxlength, fmt, pContext, params, &lparam);
}
const char *SourceModBase::GetSourceModPath()
const char *SourceModBase::GetSourceModPath() const
{
return m_SMBaseDir;
}
const char *SourceModBase::GetModPath()
const char *SourceModBase::GetModPath() const
{
return g_BaseDir.c_str();
}
@ -386,6 +396,31 @@ unsigned int SourceModBase::GetGlobalTarget() const
return m_target;
}
IDataPack *SourceModBase::CreateDataPack()
{
CDataPack *pack;
if (m_freepacks.empty())
{
pack = new CDataPack;
} else {
pack = m_freepacks.front();
m_freepacks.pop();
pack->Initialize();
}
return pack;
}
void SourceModBase::FreeDataPack(IDataPack *pack)
{
m_freepacks.push(static_cast<CDataPack *>(pack));
}
Handle_t SourceModBase::GetDataPackHandleType(bool readonly)
{
//:TODO:
return 0;
}
SMGlobalClass *SMGlobalClass::head = NULL;
SMGlobalClass::SMGlobalClass()

View File

@ -16,6 +16,10 @@
#include "sm_globals.h"
#include <ISourceMod.h>
#include <sh_stack.h>
#include "CDataPack.h"
using namespace SourceHook;
/**
* @brief Implements SourceMod's global overall management, API, and logic
@ -52,9 +56,9 @@ public:
void LevelShutdown();
/**
* @brief Returns whether or not a mapload is in progress
* @brief Returns whether or not a map load is in progress
*/
bool IsMapLoading();
bool IsMapLoading() const;
/**
* @brief Stores the global target index.
@ -65,14 +69,21 @@ public:
* @brief Returns the global target index.
*/
unsigned int GetGlobalTarget() const;
/**
* @brief Sets whether if SoureMod needs to check player auths.
*/
void SetAuthChecking(bool set);
public: //ISourceMod
const char *GetModPath();
const char *GetSourceModPath();
const char *GetModPath() const;
const char *GetSourceModPath() const;
size_t BuildPath(PathType type, char *buffer, size_t maxlength, char *format, ...);
void LogMessage(IExtension *pExt, const char *format, ...);
void LogError(IExtension *pExt, const char *format, ...);
size_t FormatString(char *buffer, size_t maxlength, IPluginContext *pContext, const cell_t *params, unsigned int param);
void SetAuthChecking(bool set);
IDataPack *CreateDataPack();
void FreeDataPack(IDataPack *pack);
HandleType_t GetDataPackHandleType(bool readonly=false);
private:
/**
* @brief Loading plugins
@ -80,6 +91,7 @@ private:
void DoGlobalPluginLoads();
void GameFrame(bool simulating);
private:
CStack<CDataPack *> m_freepacks;
char m_SMBaseDir[PLATFORM_MAX_PATH+1];
char m_SMRelDir[PLATFORM_MAX_PATH+1];
bool m_IsMapLoading;

View File

@ -70,7 +70,8 @@ namespace SourceMod
virtual float ReadFloat() const =0;
/**
* @brief Returns whether or not a specified number of bytes can be read.
* @brief Returns whether or not a specified number of bytes from the current stream
* position to the end can be read.
*
* @param bytes Number of bytes to simulate reading.
* @return True if can be read, false otherwise.
@ -94,11 +95,16 @@ namespace SourceMod
};
/**
* @brief Specifices a data pack that can only be written.
* @brief Specifies a data pack that can only be written.
*/
class IDataPack : public IDataReader
{
public:
/**
* @brief Resets the used size of the stream back to zero.
*/
virtual void ResetSize() =0;
/**
* @brief Packs one cell into the data stream.
*

View File

@ -24,6 +24,7 @@
#include <IShareSys.h>
#include <sp_vm_api.h>
#include <IDataPack.h>
#define SMINTERFACE_SOURCEMOD_NAME "ISourceMod"
#define SMINTERFACE_SOURCEMOD_VERSION 1
@ -42,7 +43,7 @@ namespace SourceMod
};
/**
* @brief Contains miscellanious helper functions.
* @brief Contains miscellaneous helper functions.
*/
class ISourceMod : public SMInterface
{
@ -61,14 +62,14 @@ namespace SourceMod
*
* @return A string containing the full mod path.
*/
virtual const char *GetModPath() =0;
virtual const char *GetModPath() const =0;
/**
* @brief Returns the full path to the SourceMod directory.
*
* @return A string containing the full SourceMod path.
*/
virtual const char *GetSourceModPath() =0;
virtual const char *GetSourceModPath() const =0;
/**
* @brief Builds a platform path for a specific target base path.
@ -117,7 +118,6 @@ namespace SourceMod
const cell_t *params,
unsigned int param) =0;
#if 0
/**
* @brief Creates a data pack object.
*
@ -144,7 +144,6 @@ namespace SourceMod
* @return The Handle type for storing generic data packs.
*/
virtual HandleType_t GetDataPackHandleType(bool readonly=false) =0;
#endif
};
}