1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/CDataPack.cpp Sun Jul 06 04:49:55 2008 +0000
1.3 @@ -0,0 +1,259 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include <malloc.h>
1.36 +#include <string.h>
1.37 +#include "CDataPack.h"
1.38 +
1.39 +#define DATAPACK_INITIAL_SIZE 512
1.40 +
1.41 +CDataPack::CDataPack()
1.42 +{
1.43 + m_pBase = (char *)malloc(DATAPACK_INITIAL_SIZE);
1.44 + m_capacity = DATAPACK_INITIAL_SIZE;
1.45 + Initialize();
1.46 +}
1.47 +
1.48 +CDataPack::~CDataPack()
1.49 +{
1.50 + free(m_pBase);
1.51 +}
1.52 +
1.53 +void CDataPack::Initialize()
1.54 +{
1.55 + m_curptr = m_pBase;
1.56 + m_size = 0;
1.57 +}
1.58 +
1.59 +void CDataPack::CheckSize(size_t typesize)
1.60 +{
1.61 + if (m_curptr - m_pBase + typesize <= m_capacity)
1.62 + {
1.63 + return;
1.64 + }
1.65 +
1.66 + size_t pos = m_curptr - m_pBase;
1.67 + do
1.68 + {
1.69 + m_capacity *= 2;
1.70 + m_pBase = (char *)realloc(m_pBase, m_capacity);
1.71 + m_curptr = m_pBase + pos;
1.72 + } while (m_curptr - m_pBase + typesize > m_capacity);
1.73 +}
1.74 +
1.75 +void CDataPack::ResetSize()
1.76 +{
1.77 + m_size = 0;
1.78 +}
1.79 +
1.80 +size_t CDataPack::CreateMemory(size_t size, void **addr)
1.81 +{
1.82 + CheckSize(sizeof(size_t) + size);
1.83 + size_t pos = m_curptr - m_pBase;
1.84 +
1.85 + *(size_t *)m_curptr = size;
1.86 + m_curptr += sizeof(size_t);
1.87 +
1.88 + if (addr)
1.89 + {
1.90 + *addr = m_curptr;
1.91 + }
1.92 +
1.93 + m_curptr += size;
1.94 + m_size += sizeof(size_t) + size;
1.95 +
1.96 + return pos;
1.97 +}
1.98 +
1.99 +void CDataPack::PackCell(cell_t cell)
1.100 +{
1.101 + CheckSize(sizeof(size_t) + sizeof(cell_t));
1.102 +
1.103 + *(size_t *)m_curptr = sizeof(cell_t);
1.104 + m_curptr += sizeof(size_t);
1.105 +
1.106 + *(cell_t *)m_curptr = cell;
1.107 + m_curptr += sizeof(cell_t);
1.108 +
1.109 + m_size += sizeof(size_t) + sizeof(cell_t);
1.110 +}
1.111 +
1.112 +void CDataPack::PackFloat(float val)
1.113 +{
1.114 + CheckSize(sizeof(size_t) + sizeof(float));
1.115 +
1.116 + *(size_t *)m_curptr = sizeof(float);
1.117 + m_curptr += sizeof(size_t);
1.118 +
1.119 + *(float *)m_curptr = val;
1.120 + m_curptr += sizeof(float);
1.121 +
1.122 + m_size += sizeof(size_t) + sizeof(float);
1.123 +}
1.124 +
1.125 +void CDataPack::PackString(const char *string)
1.126 +{
1.127 + size_t len = strlen(string);
1.128 + size_t maxsize = sizeof(size_t) + len + 1;
1.129 + CheckSize(maxsize);
1.130 +
1.131 + // Pack the string length first for buffer overrun checking.
1.132 + *(size_t *)m_curptr = len;
1.133 + m_curptr += sizeof(size_t);
1.134 +
1.135 + // Now pack the string.
1.136 + memcpy(m_curptr, string, len);
1.137 + m_curptr[len] = '\0';
1.138 + m_curptr += len + 1;
1.139 +
1.140 + m_size += maxsize;
1.141 +}
1.142 +
1.143 +void CDataPack::Reset() const
1.144 +{
1.145 + m_curptr = m_pBase;
1.146 +}
1.147 +
1.148 +size_t CDataPack::GetPosition() const
1.149 +{
1.150 + return static_cast<size_t>(m_curptr - m_pBase);
1.151 +}
1.152 +
1.153 +bool CDataPack::SetPosition(size_t pos) const
1.154 +{
1.155 + if (pos > m_size-1)
1.156 + {
1.157 + return false;
1.158 + }
1.159 + m_curptr = m_pBase + pos;
1.160 +
1.161 + return true;
1.162 +}
1.163 +
1.164 +cell_t CDataPack::ReadCell() const
1.165 +{
1.166 + if (!IsReadable(sizeof(size_t) + sizeof(cell_t)))
1.167 + {
1.168 + return 0;
1.169 + }
1.170 + if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
1.171 + {
1.172 + return 0;
1.173 + }
1.174 +
1.175 + m_curptr += sizeof(size_t);
1.176 +
1.177 + cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
1.178 + m_curptr += sizeof(cell_t);
1.179 + return val;
1.180 +}
1.181 +
1.182 +float CDataPack::ReadFloat() const
1.183 +{
1.184 + if (!IsReadable(sizeof(size_t) + sizeof(float)))
1.185 + {
1.186 + return 0;
1.187 + }
1.188 + if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
1.189 + {
1.190 + return 0;
1.191 + }
1.192 +
1.193 + m_curptr += sizeof(size_t);
1.194 +
1.195 + float val = *reinterpret_cast<float *>(m_curptr);
1.196 + m_curptr += sizeof(float);
1.197 + return val;
1.198 +}
1.199 +
1.200 +bool CDataPack::IsReadable(size_t bytes) const
1.201 +{
1.202 + return (bytes + (m_curptr - m_pBase) > m_size) ? false : true;
1.203 +}
1.204 +
1.205 +const char *CDataPack::ReadString(size_t *len) const
1.206 +{
1.207 + if (!IsReadable(sizeof(size_t)))
1.208 + {
1.209 + return NULL;
1.210 + }
1.211 +
1.212 + size_t real_len = *(size_t *)m_curptr;
1.213 +
1.214 + m_curptr += sizeof(size_t);
1.215 + char *str = (char *)m_curptr;
1.216 +
1.217 + if ((strlen(str) != real_len) || !(IsReadable(real_len+1)))
1.218 + {
1.219 + return NULL;
1.220 + }
1.221 +
1.222 + if (len)
1.223 + {
1.224 + *len = real_len;
1.225 + }
1.226 +
1.227 + m_curptr += real_len + 1;
1.228 +
1.229 + return str;
1.230 +}
1.231 +
1.232 +void *CDataPack::GetMemory() const
1.233 +{
1.234 + return m_curptr;
1.235 +}
1.236 +
1.237 +void *CDataPack::ReadMemory(size_t *size) const
1.238 +{
1.239 + if (!IsReadable(sizeof(size_t)))
1.240 + {
1.241 + return NULL;
1.242 + }
1.243 +
1.244 + size_t bytecount = *(size_t *)m_curptr;
1.245 + m_curptr += sizeof(size_t);
1.246 +
1.247 + if (!IsReadable(bytecount))
1.248 + {
1.249 + return NULL;
1.250 + }
1.251 +
1.252 + void *ptr = m_curptr;
1.253 +
1.254 + if (size)
1.255 + {
1.256 + *size = bytecount;
1.257 + }
1.258 +
1.259 + m_curptr += bytecount;
1.260 +
1.261 + return ptr;
1.262 +}