core/CDataPack.cpp
author Scott Ehlert <ds@alliedmods.net>
Mon May 14 21:29:17 2007 +0000 (2007-05-14)
changeset 794 5947b0ee60bb
parent 653 ef60870067ff
child 1231 17badaf66ce4
permissions -rw-r--r--
Implemented amb286 - .smx extension no longer required with "sm plugins load"
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * ===============================================================
     6  *
     7  * This file is not open source and may not be copied without explicit
     8  * written permission of AlliedModders LLC.  This file may not be redistributed 
     9  * in whole or significant part.
    10  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    11  *
    12  * Version: $Id$
    13  */
    14 
    15 #include <malloc.h>
    16 #include <string.h>
    17 #include "CDataPack.h"
    18 
    19 #define DATAPACK_INITIAL_SIZE		512
    20 
    21 CDataPack::CDataPack()
    22 {
    23 	m_pBase = (char *)malloc(DATAPACK_INITIAL_SIZE);
    24 	m_capacity = DATAPACK_INITIAL_SIZE;
    25 	Initialize();
    26 }
    27 
    28 CDataPack::~CDataPack()
    29 {
    30 	free(m_pBase);
    31 }
    32 
    33 void CDataPack::Initialize()
    34 {
    35 	m_curptr = m_pBase;
    36 	m_size = 0;
    37 }
    38 
    39 void CDataPack::CheckSize(size_t typesize)
    40 {
    41 	if (m_curptr - m_pBase + typesize <= m_capacity)
    42 	{
    43 		return;
    44 	}
    45 
    46 	size_t pos = m_curptr - m_pBase;
    47 	do
    48 	{
    49 		m_capacity *= 2;
    50 		m_pBase = (char *)realloc(m_pBase, m_capacity);
    51 		m_curptr = m_pBase + pos;
    52 	} while (m_curptr - m_pBase + typesize > m_capacity);
    53 }
    54 
    55 void CDataPack::ResetSize()
    56 {
    57 	m_size = 0;
    58 }
    59 
    60 size_t CDataPack::CreateMemory(size_t size, void **addr)
    61 {
    62 	CheckSize(sizeof(size_t) + size);
    63 	size_t pos = m_curptr - m_pBase;
    64 
    65 	*(size_t *)m_curptr = size;
    66 	m_curptr += sizeof(size_t);
    67 
    68 	if (addr)
    69 	{
    70 		*addr = m_curptr;
    71 	}
    72 
    73 	m_curptr += size;
    74 	m_size += sizeof(size_t) + size;
    75 
    76 	return pos;
    77 }
    78 
    79 void CDataPack::PackCell(cell_t cell)
    80 {
    81 	CheckSize(sizeof(size_t) + sizeof(cell_t));
    82 
    83 	*(size_t *)m_curptr = sizeof(cell_t);
    84 	m_curptr += sizeof(size_t);
    85 
    86 	*(cell_t *)m_curptr = cell;
    87 	m_curptr += sizeof(cell_t);
    88 
    89 	m_size += sizeof(size_t) + sizeof(cell_t);
    90 }
    91 
    92 void CDataPack::PackFloat(float val)
    93 {
    94 	CheckSize(sizeof(size_t) + sizeof(float));
    95 
    96 	*(size_t *)m_curptr = sizeof(float);
    97 	m_curptr += sizeof(size_t);
    98 
    99 	*(float *)m_curptr = val;
   100 	m_curptr += sizeof(float);
   101 
   102 	m_size += sizeof(size_t) + sizeof(float);
   103 }
   104 
   105 void CDataPack::PackString(const char *string)
   106 {
   107 	size_t len = strlen(string);
   108 	size_t maxsize = sizeof(size_t) + len + 1;
   109 	CheckSize(maxsize);
   110 
   111 	// Pack the string length first for buffer overrun checking.
   112 	*(size_t *)m_curptr = len;
   113 	m_curptr += sizeof(size_t);
   114 
   115 	// Now pack the string.
   116 	memcpy(m_curptr, string, len);
   117 	m_curptr[len] = '\0';
   118 	m_curptr += len + 1;
   119 
   120 	m_size += maxsize;
   121 }
   122 
   123 void CDataPack::Reset() const
   124 {
   125 	m_curptr = m_pBase;
   126 }
   127 
   128 size_t CDataPack::GetPosition() const
   129 {
   130 	return static_cast<size_t>(m_curptr - m_pBase);
   131 }
   132 
   133 bool CDataPack::SetPosition(size_t pos) const
   134 {
   135 	if (pos > m_size-1)
   136 	{
   137 		return false;
   138 	}
   139 	m_curptr = m_pBase + pos;
   140 
   141 	return true;
   142 }
   143 
   144 cell_t CDataPack::ReadCell() const
   145 {
   146 	if (!IsReadable(sizeof(size_t) + sizeof(cell_t)))
   147 	{
   148 		return 0;
   149 	}
   150 	if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
   151 	{
   152 		return 0;
   153 	}
   154 
   155 	m_curptr += sizeof(size_t);
   156 
   157 	cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
   158 	m_curptr += sizeof(cell_t);
   159 	return val;
   160 }
   161 
   162 float CDataPack::ReadFloat() const
   163 {
   164 	if (!IsReadable(sizeof(size_t) + sizeof(float)))
   165 	{
   166 		return 0;
   167 	}
   168 	if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
   169 	{
   170 		return 0;
   171 	}
   172 
   173 	m_curptr += sizeof(size_t);
   174 
   175 	float val = *reinterpret_cast<float *>(m_curptr);
   176 	m_curptr += sizeof(float);
   177 	return val;
   178 }
   179 
   180 bool CDataPack::IsReadable(size_t bytes) const
   181 {
   182 	return (bytes + (m_curptr - m_pBase) > m_size) ? false : true;
   183 }
   184 
   185 const char *CDataPack::ReadString(size_t *len) const
   186 {
   187 	if (!IsReadable(sizeof(size_t)))
   188 	{
   189 		return NULL;
   190 	}
   191 
   192 	size_t real_len = *(size_t *)m_curptr;
   193 
   194 	m_curptr += sizeof(size_t);
   195 	char *str = (char *)m_curptr;
   196 
   197 	if ((strlen(str) != real_len) || !(IsReadable(real_len+1)))
   198 	{
   199 		return NULL;
   200 	}
   201 
   202 	if (len)
   203 	{
   204 		*len = real_len;
   205 	}
   206 
   207 	m_curptr += real_len + 1;
   208 
   209 	return str;
   210 }
   211 
   212 void *CDataPack::GetMemory() const
   213 {
   214 	return m_curptr;
   215 }
   216 
   217 void *CDataPack::ReadMemory(size_t *size) const
   218 {
   219 	if (!IsReadable(sizeof(size_t)))
   220 	{
   221 		return NULL;
   222 	}
   223 
   224 	size_t bytecount = *(size_t *)m_curptr;
   225 	m_curptr += sizeof(size_t);
   226 
   227 	if (!IsReadable(bytecount))
   228 	{
   229 		return NULL;
   230 	}
   231 
   232 	void *ptr = m_curptr;
   233 
   234 	if (size)
   235 	{
   236 		*size = bytecount;
   237 	}
   238 
   239 	m_curptr += bytecount;
   240 
   241 	return ptr;
   242 }