Import of GameData MD5 hashing app.
authorMatt Woodrow <pred@alliedmods.net>
Sun Jun 29 22:23:14 2008 +0000 (2008-06-29)
changeset 2125ec2047b363c0
parent 2124 e3665367ce8d
child 2126 1c94cf83aaed
Import of GameData MD5 hashing app.
tools/gamedata md5/Makefile
tools/gamedata md5/TextParsers.cpp
tools/gamedata md5/TextParsers.h
tools/gamedata md5/main.cpp
tools/gamedata md5/main.h
tools/gamedata md5/md5.cpp
tools/gamedata md5/md5.h
tools/gamedata md5/msvc9/gamedatamd5.sln
tools/gamedata md5/msvc9/gamedatamd5.vcproj
tools/gamedata md5/sm_memtable.cpp
tools/gamedata md5/sm_memtable.h
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/gamedata md5/Makefile	Sun Jun 29 22:23:14 2008 +0000
     1.3 @@ -0,0 +1,74 @@
     1.4 +# (C)2004-2008 SourceMod Development Team
     1.5 +# Makefile written by David "BAILOPAN" Anderson
     1.6 +
     1.7 +
     1.8 +#####################################
     1.9 +### EDIT BELOW FOR OTHER PROJECTS ###
    1.10 +#####################################
    1.11 +
    1.12 +OBJECTS = main.cpp TextParsers.cpp sm_memtable.cpp md5.cpp
    1.13 +
    1.14 +##############################################
    1.15 +### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
    1.16 +##############################################
    1.17 +
    1.18 +C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
    1.19 +C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
    1.20 +C_GCC4_FLAGS = -fvisibility=hidden
    1.21 +CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
    1.22 +CPP = gcc-4.1
    1.23 +
    1.24 +BINARY = gamedatamd5
    1.25 +
    1.26 +INCLUDE += -I. -I../../public -I../../public/sourcepawn
    1.27 +
    1.28 +CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
    1.29 +	-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \
    1.30 +	-Wno-uninitialized -mfpmath=sse -msse -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32
    1.31 +CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
    1.32 +
    1.33 +################################################
    1.34 +### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
    1.35 +################################################
    1.36 +
    1.37 +ifeq "$(DEBUG)" "true"
    1.38 +	BIN_DIR = Debug
    1.39 +	CFLAGS += $(C_DEBUG_FLAGS)
    1.40 +else
    1.41 +	BIN_DIR = Release
    1.42 +	CFLAGS += $(C_OPT_FLAGS)
    1.43 +endif
    1.44 +
    1.45 +GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
    1.46 +ifeq "$(GCC_VERSION)" "4"
    1.47 +	CFLAGS += $(C_GCC4_FLAGS)
    1.48 +	CPPFLAGS += $(CPP_GCC4_FLAGS)
    1.49 +endif
    1.50 +
    1.51 +OBJ_LINUX := $(OBJECTS:%vm_engine.cpp=$(BIN_DIR)/%vm_engine.o)
    1.52 +OBJ_LINUX := $(OBJ_LINUX:%.cpp=$(BIN_DIR)/%.o)
    1.53 +OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
    1.54 +
    1.55 +$(BIN_DIR)/%vm_engine.o: %vm_engine.cpp
    1.56 +	$(CPP) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
    1.57 +
    1.58 +$(BIN_DIR)/%.o: %.cpp
    1.59 +	$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
    1.60 +
    1.61 +$(BIN_DIR)/%.o: %.c
    1.62 +	$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
    1.63 +
    1.64 +all:
    1.65 +	mkdir -p $(BIN_DIR)
    1.66 +	$(MAKE) -f Makefile sourcemod
    1.67 +
    1.68 +sourcemod: $(OBJ_LINUX)
    1.69 +	$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -lstdc++ -o$(BIN_DIR)/$(BINARY)
    1.70 +
    1.71 +debug:
    1.72 +	$(MAKE) -f Makefile all DEBUG=true
    1.73 +
    1.74 +default: all
    1.75 +
    1.76 +clean:
    1.77 +	rm -rf $(BIN_DIR)/$(BINARY)
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/gamedata md5/TextParsers.cpp	Sun Jun 29 22:23:14 2008 +0000
     2.3 @@ -0,0 +1,1082 @@
     2.4 +/**
     2.5 + * vim: set ts=4 :
     2.6 + * =============================================================================
     2.7 + * SourceMod
     2.8 + * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     2.9 + * =============================================================================
    2.10 + *
    2.11 + * This program is free software; you can redistribute it and/or modify it under
    2.12 + * the terms of the GNU General Public License, version 3.0, as published by the
    2.13 + * Free Software Foundation.
    2.14 + * 
    2.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
    2.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    2.17 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    2.18 + * details.
    2.19 + *
    2.20 + * You should have received a copy of the GNU General Public License along with
    2.21 + * this program.  If not, see <http://www.gnu.org/licenses/>.
    2.22 + *
    2.23 + * As a special exception, AlliedModders LLC gives you permission to link the
    2.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
    2.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    2.26 + * by the Valve Corporation.  You must obey the GNU General Public License in
    2.27 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
    2.28 + * this exception to all derivative works.  AlliedModders LLC defines further
    2.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    2.30 + * or <http://www.sourcemod.net/license.php>.
    2.31 + *
    2.32 + * Version: $Id$
    2.33 + */
    2.34 +
    2.35 +#include <stdio.h>
    2.36 +#include <ctype.h>
    2.37 +#include <wctype.h>
    2.38 +#include <string.h>
    2.39 +#include <stdlib.h>
    2.40 +#include <assert.h>
    2.41 +#include "TextParsers.h"
    2.42 +//#include "ShareSys.h"
    2.43 +//#include "sm_stringutil.h"
    2.44 +//#include "LibrarySys.h"
    2.45 +
    2.46 +TextParsers g_TextParser;
    2.47 +ITextParsers *textparsers = &g_TextParser;
    2.48 +
    2.49 +static int g_ini_chartable1[255] = {0};
    2.50 +static int g_ws_chartable[255] = {0};
    2.51 +
    2.52 +bool TextParsers::IsWhitespace(const char *stream)
    2.53 +{
    2.54 +	return g_ws_chartable[(unsigned)*stream] == 1;
    2.55 +}
    2.56 +
    2.57 +TextParsers::TextParsers()
    2.58 +{
    2.59 +	g_ini_chartable1[(unsigned)'_'] = 1;
    2.60 +	g_ini_chartable1[(unsigned)'-'] = 1;
    2.61 +	g_ini_chartable1[(unsigned)','] = 1;
    2.62 +	g_ini_chartable1[(unsigned)'+'] = 1;
    2.63 +	g_ini_chartable1[(unsigned)'.'] = 1;
    2.64 +	g_ini_chartable1[(unsigned)'$'] = 1;
    2.65 +	g_ini_chartable1[(unsigned)'?'] = 1;
    2.66 +	g_ini_chartable1[(unsigned)'/'] = 1;
    2.67 +	g_ws_chartable[(unsigned)'\n'] = 1;
    2.68 +	g_ws_chartable[(unsigned)'\v'] = 1;
    2.69 +	g_ws_chartable[(unsigned)'\r'] = 1;
    2.70 +	g_ws_chartable[(unsigned)'\t'] = 1;
    2.71 +	g_ws_chartable[(unsigned)'\f'] = 1;
    2.72 +	g_ws_chartable[(unsigned)' '] = 1;
    2.73 +}
    2.74 +
    2.75 +unsigned int TextParsers::GetUTF8CharBytes(const char *stream)
    2.76 +{
    2.77 +	return _GetUTF8CharBytes(stream);
    2.78 +}
    2.79 +
    2.80 +/**
    2.81 + * Character streams
    2.82 + */
    2.83 +
    2.84 +struct CharStream
    2.85 +{
    2.86 +	const char *curpos;
    2.87 +};
    2.88 +
    2.89 +bool CharStreamReader(void *stream, char *buffer, size_t maxlength, unsigned int *read)
    2.90 +{
    2.91 +	CharStream *srdr = (CharStream *)stream;
    2.92 +
    2.93 +	const char *ptr = srdr->curpos;
    2.94 +	for (size_t i=0; i<maxlength; i++)
    2.95 +	{
    2.96 +		if (*ptr == '\0')
    2.97 +		{
    2.98 +			break;
    2.99 +		}
   2.100 +		*buffer++ = *ptr++;
   2.101 +	}
   2.102 +
   2.103 +	*read = ptr - srdr->curpos;
   2.104 +
   2.105 +	srdr->curpos = ptr;
   2.106 +
   2.107 +	return true;
   2.108 +}
   2.109 +
   2.110 +SMCError TextParsers::ParseString_SMC(const char *stream, 
   2.111 +					 ITextListener_SMC *smc,
   2.112 +					 SMCStates *states)
   2.113 +{
   2.114 +	CharStream srdr = { stream };
   2.115 +
   2.116 +	return ParseStream_SMC(&srdr, CharStreamReader, smc, states);
   2.117 +}
   2.118 +
   2.119 +/**
   2.120 + * File streams
   2.121 + */
   2.122 +
   2.123 +bool FileStreamReader(void *stream, char *buffer, size_t maxlength, unsigned int *read)
   2.124 +{
   2.125 +	size_t num = fread(buffer, 1, maxlength, (FILE *)stream);
   2.126 +
   2.127 +	*read = static_cast<unsigned int>(num);
   2.128 +
   2.129 +	if (num == 0 && feof((FILE *)stream))
   2.130 +	{
   2.131 +		return true;
   2.132 +	}
   2.133 +
   2.134 +	return (ferror((FILE *)stream) == 0);
   2.135 +}
   2.136 +
   2.137 +SMCError TextParsers::ParseFile_SMC(const char *file, ITextListener_SMC *smc, SMCStates *states)
   2.138 +{
   2.139 +	FILE *fp = fopen(file, "rt");
   2.140 +
   2.141 +	if (!fp)
   2.142 +	{
   2.143 +		if (states != NULL)
   2.144 +		{
   2.145 +			states->line = 0;
   2.146 +			states->col = 0;
   2.147 +		}
   2.148 +		return SMCError_StreamOpen;
   2.149 +	}
   2.150 +
   2.151 +	SMCError result = ParseStream_SMC(fp, FileStreamReader, smc, states);
   2.152 +
   2.153 +	fclose(fp);
   2.154 +
   2.155 +	return result;
   2.156 +}
   2.157 +
   2.158 +SMCError TextParsers::ParseSMCFile(const char *file,
   2.159 +								   ITextListener_SMC *smc_listener,
   2.160 +								   SMCStates *states,
   2.161 +								   char *buffer,
   2.162 +								   size_t maxsize)
   2.163 +{
   2.164 +	const char *errstr;
   2.165 +	FILE *fp = fopen(file, "rt");
   2.166 +
   2.167 +	if (fp == NULL)
   2.168 +	{
   2.169 +		char error[256] = "unknown";
   2.170 +		if (states != NULL)
   2.171 +		{
   2.172 +			states->line = 0;
   2.173 +			states->col = 0;
   2.174 +		}
   2.175 +		//g_LibSys.GetPlatformError(error, sizeof(error));
   2.176 +		UTIL_Format(buffer, maxsize, "File could not be opened: %s", error);
   2.177 +		return SMCError_StreamOpen;
   2.178 +	}
   2.179 +
   2.180 +	SMCError result = ParseStream_SMC(fp, FileStreamReader, smc_listener, states);
   2.181 +
   2.182 +	fclose(fp);
   2.183 +
   2.184 +	errstr = GetSMCErrorString(result);
   2.185 +	UTIL_Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
   2.186 +
   2.187 +	return result;
   2.188 +}
   2.189 +
   2.190 +/** 
   2.191 + * Raw parsing of streams with helper functions
   2.192 + */
   2.193 +
   2.194 +struct StringInfo
   2.195 +{
   2.196 +	StringInfo() : quoted(false), ptr(NULL), end(NULL), special(false) { }
   2.197 +	bool quoted;
   2.198 +	char *ptr;
   2.199 +	char *end;
   2.200 +	bool special;
   2.201 +};
   2.202 +
   2.203 +const char *FixupString(StringInfo &data)
   2.204 +{
   2.205 +	if (!data.ptr)
   2.206 +	{
   2.207 +		return NULL;
   2.208 +	}
   2.209 +
   2.210 +	if (data.quoted)
   2.211 +	{
   2.212 +		data.ptr++;
   2.213 +	}
   2.214 +#if defined _DEBUG
   2.215 +	else {
   2.216 +		/* A string will never have beginning whitespace because we ignore it in the stream.
   2.217 +		 * Furthermore, if there is trailing whitespace, the end ptr will point to it, so it is valid
   2.218 +		 * to overwrite!  Lastly, the last character must be whitespace or a comment/invalid character.
   2.219 +		 */
   2.220 + 	}
   2.221 +#endif
   2.222 +
   2.223 +	/* Do some extra work on strings that have special quoted characters. */
   2.224 +	if (data.special)
   2.225 +	{
   2.226 +		char *outptr = data.ptr;
   2.227 +		size_t len = data.end - data.ptr;
   2.228 +		if (len >= 2)
   2.229 +		{
   2.230 +			for (size_t i=0; i<len; i++)
   2.231 +			{
   2.232 +				if (data.ptr[i] == '\\' && i < len - 1)
   2.233 +				{
   2.234 +					/* Resolve the next character. */
   2.235 +					i++;
   2.236 +					if (data.ptr[i] == 'n')
   2.237 +					{
   2.238 +						data.ptr[i] = '\n';
   2.239 +					} else if (data.ptr[i] == 't') {
   2.240 +						data.ptr[i] = '\t';
   2.241 +					} else if (data.ptr[i] == 'r') {
   2.242 +						data.ptr[i] = '\r';
   2.243 +					} else if (data.ptr[i] != '\\'
   2.244 +						&& data.ptr[i] != '"') {
   2.245 +						/* This character is invalid, so go back one */
   2.246 +						i--;
   2.247 +					}
   2.248 +				}
   2.249 +				*outptr++ = data.ptr[i];
   2.250 +			}
   2.251 +			*outptr = '\0';
   2.252 +		}
   2.253 +	}
   2.254 +
   2.255 +	if (data.end)
   2.256 +	{
   2.257 +		*(data.end) = '\0';
   2.258 +	}
   2.259 +
   2.260 +	return data.ptr;
   2.261 +}
   2.262 +
   2.263 +const char *rotate(StringInfo info[3])
   2.264 +{
   2.265 +	if (info[2].ptr != NULL)
   2.266 +	{
   2.267 +		return info[2].ptr;
   2.268 +	}
   2.269 +
   2.270 +	if (info[0].ptr != NULL)
   2.271 +	{
   2.272 +		info[2] = info[1];
   2.273 +		info[1] = info[0];
   2.274 +		info[0] = StringInfo();
   2.275 +	}
   2.276 +	
   2.277 +	return NULL;
   2.278 +}
   2.279 +
   2.280 +void scrap(StringInfo info[3])
   2.281 +{
   2.282 +	info[2] = StringInfo();
   2.283 +	info[1] = StringInfo();
   2.284 +	info[0] = StringInfo();
   2.285 +}
   2.286 +
   2.287 +void reloc(StringInfo &data, unsigned int bytes)
   2.288 +{
   2.289 +	if (data.ptr)
   2.290 +	{
   2.291 +		data.ptr -= bytes;
   2.292 +	}
   2.293 +	if (data.end)
   2.294 +	{
   2.295 +		data.end -= bytes;
   2.296 +	}
   2.297 +}
   2.298 +
   2.299 +char *lowstring(StringInfo info[3])
   2.300 +{
   2.301 +	for (int i=2; i>=0; i--)
   2.302 +	{
   2.303 +		if (info[i].ptr)
   2.304 +		{
   2.305 +			return info[i].ptr;
   2.306 +		}
   2.307 +	}
   2.308 +
   2.309 +	return NULL;
   2.310 +}
   2.311 +
   2.312 +SMCError TextParsers::ParseStream_SMC(void *stream, 
   2.313 +								   STREAMREADER srdr, 
   2.314 +								   ITextListener_SMC *smc, 
   2.315 +								   SMCStates *pStates)
   2.316 +{
   2.317 +	char *reparse_point = NULL;
   2.318 +	char in_buf[4096];
   2.319 +	char *parse_point = in_buf;
   2.320 +	char *line_begin = in_buf;
   2.321 +	unsigned int read;
   2.322 +	unsigned int curlevel = 0;
   2.323 +	bool in_quote = false;
   2.324 +	bool ignoring = false;
   2.325 +	bool eol_comment = false;
   2.326 +	bool ml_comment = false;
   2.327 +	unsigned int i;
   2.328 +	SMCError err = SMCError_Okay;
   2.329 +	SMCResult res;
   2.330 +	SMCStates states;
   2.331 +	char c;
   2.332 +
   2.333 +	StringInfo strings[3];
   2.334 +	StringInfo emptystring;
   2.335 +
   2.336 +	states.line = 1;
   2.337 +	states.col = 0;
   2.338 +
   2.339 +	smc->ReadSMC_ParseStart();
   2.340 +
   2.341 +	/**
   2.342 +	 * The stream reader reads in as much as it can fill the buffer with.
   2.343 +	 * It then processes the buffer.  If the buffer cannot be fully processed, for example, 
   2.344 +	 * a line is left hanging with no newline, then the contents of the buffer is shifted 
   2.345 +	 * down, and the buffer is filled from the stream reader again.
   2.346 +	 *
   2.347 +	 * What makes this particularly annoying is that we cache pointers everywhere, so when 
   2.348 +	 * the shifting process takes place, all those pointers must be shifted as well.
   2.349 +	 */
   2.350 +	while (srdr(stream, parse_point, sizeof(in_buf) - (parse_point - in_buf) - 1, &read))
   2.351 +	{
   2.352 +		if (!read)
   2.353 +		{
   2.354 +			break;
   2.355 +		}
   2.356 +
   2.357 +		/* Check for BOM markings, which is only relevant on the first line.
   2.358 +		 * Not worth it, but it could be moved out of the loop.
   2.359 +		 */
   2.360 +		if (states.line == 1 && 
   2.361 +			in_buf[0] == (char)0xEF && 
   2.362 +			in_buf[1] == (char)0xBB && 
   2.363 +			in_buf[2] == (char)0xBF)
   2.364 +		{
   2.365 +			/* Move EVERYTHING down :\ */
   2.366 +			memmove(in_buf, &in_buf[3], read - 3);
   2.367 +			read -= 3;
   2.368 +		}
   2.369 +
   2.370 +		if (reparse_point)
   2.371 +		{
   2.372 +			read += (parse_point - reparse_point);
   2.373 +			parse_point = reparse_point;
   2.374 +			reparse_point = NULL;
   2.375 +		}
   2.376 +
   2.377 +		for (i=0; i<read; i++)
   2.378 +		{
   2.379 +			c = parse_point[i];
   2.380 +			if (c == '\n')
   2.381 +			{
   2.382 +				/* If we got a newline, there's a lot of things that could have happened in the interim.
   2.383 +				 * First, let's make sure the staged strings are rotated.
   2.384 +				 */
   2.385 +				if (strings[0].ptr)
   2.386 +				{
   2.387 +					strings[0].end = &parse_point[i];
   2.388 +					if (rotate(strings) != NULL)
   2.389 +					{
   2.390 +						err = SMCError_InvalidTokens;
   2.391 +						goto failed;
   2.392 +					}
   2.393 +				}
   2.394 +
   2.395 +				/* Next, let's clear some line-based values that may no longer have meaning */
   2.396 +				eol_comment = false;
   2.397 +				in_quote = false;
   2.398 +				if (ignoring && !ml_comment)
   2.399 +				{
   2.400 +					ignoring = false;
   2.401 +				}
   2.402 +
   2.403 +				/* Pass the raw line onto the listener.  We terminate the line so the receiver 
   2.404 +				 * doesn't get tons of useless info.  We restore the newline after.
   2.405 +				 */
   2.406 +				parse_point[i] = '\0';
   2.407 +				if ((res=smc->ReadSMC_RawLine(&states, line_begin)) != SMCResult_Continue)
   2.408 +				{
   2.409 +					err = (res == SMCResult_HaltFail) ? SMCError_Custom : SMCError_Okay;
   2.410 +					goto failed;
   2.411 +				}
   2.412 +				parse_point[i] = '\n';
   2.413 +
   2.414 +				/* Now we check the sanity of our staged strings! */
   2.415 +				if (strings[2].ptr)
   2.416 +				{
   2.417 +					if (!curlevel)
   2.418 +					{
   2.419 +						err = SMCError_InvalidProperty1;
   2.420 +						goto failed;
   2.421 +					}
   2.422 +					/* Assume the next string is a property and pass the info on. */
   2.423 +					if ((res=smc->ReadSMC_KeyValue(
   2.424 +						&states,
   2.425 +						FixupString(strings[2]),
   2.426 +						FixupString(strings[1]))) != SMCResult_Continue)
   2.427 +					{
   2.428 +						err = (res == SMCResult_HaltFail) ? SMCError_Custom : SMCError_Okay;
   2.429 +						goto failed;
   2.430 +					}
   2.431 +					scrap(strings);
   2.432 +				}
   2.433 +
   2.434 +				/* Change the states for the next line */
   2.435 +				states.col = 0;
   2.436 +				states.line++;
   2.437 +				line_begin = &parse_point[i+1];		//Note: safe because this gets relocated later
   2.438 +			} 
   2.439 +			else if (ignoring) 
   2.440 +			{
   2.441 +				if (in_quote)
   2.442 +				{
   2.443 +					/* If i was 0, we could have reparsed, so make sure there's no buffer underrun */
   2.444 +					if ((&parse_point[i] != in_buf) && c == '"' && parse_point[i-1] != '\\')
   2.445 +					{
   2.446 +						/* If we reached a quote in an ignore phase,
   2.447 +						 * we're staging a string and we must rotate it out.
   2.448 +						 */
   2.449 +						in_quote = false;
   2.450 +						ignoring = false;
   2.451 +						/* Set our info */
   2.452 +						strings[0].end = &parse_point[i];
   2.453 +						strings[0].quoted = true;
   2.454 +						if (rotate(strings) != NULL)
   2.455 +						{
   2.456 +							/* If we rotated too many strings, there was too much crap on one line */
   2.457 +							err = SMCError_InvalidTokens;
   2.458 +							goto failed;
   2.459 +						}
   2.460 +					} 
   2.461 +					else if (c == '\\') 
   2.462 +					{
   2.463 +						strings[0].special = true;
   2.464 +						if (i == (read - 1))
   2.465 +						{
   2.466 +							reparse_point = &parse_point[i];
   2.467 +							break;
   2.468 +						}
   2.469 +					}
   2.470 +				} 
   2.471 +				else if (ml_comment) 
   2.472 +				{
   2.473 +					if (c == '*')
   2.474 +					{
   2.475 +						/* Check if we need to get more input first */
   2.476 +						if (i == read - 1)
   2.477 +						{
   2.478 +							reparse_point = &parse_point[i];
   2.479 +							break;
   2.480 +						}
   2.481 +						if (parse_point[i+1] == '/')
   2.482 +						{
   2.483 +							ml_comment = false;
   2.484 +							ignoring = false;
   2.485 +							/* We should not be staging anything right now. */
   2.486 +							assert(strings[0].ptr == NULL);
   2.487 +							/* Advance the input stream so we don't choke on this token */
   2.488 +							i++;
   2.489 +							states.col++;
   2.490 +						}
   2.491 +					}
   2.492 +				}
   2.493 +			} 
   2.494 +			else 
   2.495 +			{
   2.496 +				/* Check if we're whitespace or not */
   2.497 +				if (!g_ws_chartable[(unsigned)c])
   2.498 +				{
   2.499 +					bool restage = false;
   2.500 +					/* Check various special tokens:
   2.501 +					 * ;
   2.502 +					 * //
   2.503 +					 * / *
   2.504 +					 * {
   2.505 +					 * }
   2.506 +					 */
   2.507 +					if (c == ';' || c == '/')
   2.508 +					{
   2.509 +						/* If it's a line-based comment (that is, ; or //)
   2.510 +						 * we will need to scrap everything until the end of the line.
   2.511 +						 */
   2.512 +						if (c == '/')
   2.513 +						{
   2.514 +							if (i == read - 1)
   2.515 +							{
   2.516 +								/* If we reached the end of the look-ahead, we need to re-check our input.
   2.517 +								 * Breaking out will force this to be the new reparse point!
   2.518 +								 */
   2.519 +								reparse_point = &parse_point[i];
   2.520 +								break;
   2.521 +							}
   2.522 +							if (parse_point[i + 1] == '/')
   2.523 +							{
   2.524 +								/* standard comment */
   2.525 +								ignoring = true;
   2.526 +								eol_comment = true;
   2.527 +								restage = true;
   2.528 +							} 
   2.529 +							else if (parse_point[i+1] == '*') 
   2.530 +							{
   2.531 +								/* inline comment - start ignoring */
   2.532 +								ignoring = true;
   2.533 +								ml_comment = true;
   2.534 +								/* yes, we restage, meaning that:
   2.535 +								 * STR/ *stuff* /ING  (space because ml comments don't nest in C++)
   2.536 +								 * will not generate 'STRING', but rather 'STR' and 'ING'.
   2.537 +								 * This should be a rare occurrence and is done here for convenience.
   2.538 +								 */
   2.539 +								restage = true;
   2.540 +							}
   2.541 +						} 
   2.542 +						else 
   2.543 +						{
   2.544 +							ignoring = true;
   2.545 +							eol_comment = true;
   2.546 +							restage = true;
   2.547 +						}
   2.548 +					} 
   2.549 +					else if (c == '{') 
   2.550 +					{
   2.551 +						/* If we are staging a string, we must rotate here */
   2.552 +						if (strings[0].ptr)
   2.553 +						{
   2.554 +							/* We have unacceptable tokens on this line */
   2.555 +							if (rotate(strings) != NULL)
   2.556 +							{
   2.557 +								err = SMCError_InvalidSection1;
   2.558 +								goto failed;
   2.559 +							}
   2.560 +						}
   2.561 +						/* Sections must always be alone */
   2.562 +						if (strings[2].ptr != NULL)
   2.563 +						{
   2.564 +							err = SMCError_InvalidSection1;
   2.565 +							goto failed;
   2.566 +						} 
   2.567 +						else if (strings[1].ptr == NULL)
   2.568 +						{
   2.569 +							err = SMCError_InvalidSection2;
   2.570 +							goto failed;
   2.571 +						}
   2.572 +						if ((res=smc->ReadSMC_NewSection(&states, FixupString(strings[1])))
   2.573 +							!= SMCResult_Continue)
   2.574 +						{
   2.575 +							err = (res == SMCResult_HaltFail) ? SMCError_Custom : SMCError_Okay;
   2.576 +							goto failed;
   2.577 +						}
   2.578 +						strings[1] = emptystring;
   2.579 +						curlevel++;
   2.580 +					} 
   2.581 +					else if (c == '}') 
   2.582 +					{
   2.583 +						/* Unlike our matching friend, this can be on the same line as something prior */
   2.584 +						if (rotate(strings) != NULL)
   2.585 +						{
   2.586 +							err = SMCError_InvalidSection3;
   2.587 +							goto failed;
   2.588 +						}
   2.589 +						if (strings[2].ptr)
   2.590 +						{
   2.591 +							if (!curlevel)
   2.592 +							{
   2.593 +								err = SMCError_InvalidProperty1;
   2.594 +								goto failed;
   2.595 +							}
   2.596 +							if ((res=smc->ReadSMC_KeyValue(
   2.597 +											&states,
   2.598 +											FixupString(strings[2]),
   2.599 +											FixupString(strings[1])))
   2.600 +								!= SMCResult_Continue)
   2.601 +							{
   2.602 +								err = (res == SMCResult_HaltFail) ? SMCError_Custom : SMCError_Okay;
   2.603 +								goto failed;
   2.604 +							}
   2.605 +						} 
   2.606 +						else if (strings[1].ptr) 
   2.607 +						{
   2.608 +							err = SMCError_InvalidSection3;
   2.609 +							goto failed;
   2.610 +						} 
   2.611 +						else if (!curlevel) 
   2.612 +						{
   2.613 +							err = SMCError_InvalidSection4;
   2.614 +							goto failed;
   2.615 +						}
   2.616 +						/* Now it's safe to leave the section */
   2.617 +						scrap(strings);
   2.618 +						if ((res=smc->ReadSMC_LeavingSection(&states)) != SMCResult_Continue)
   2.619 +						{
   2.620 +							err = (res == SMCResult_HaltFail) ? SMCError_Custom : SMCError_Okay;
   2.621 +							goto failed;
   2.622 +						}
   2.623 +						curlevel--;
   2.624 +					} 
   2.625 +					else if (c == '"') 
   2.626 +					{
   2.627 +						/* If we get a quote mark, we always restage, but we need to do it beforehand */
   2.628 +						if (strings[0].ptr)
   2.629 +						{
   2.630 +							strings[0].end = &parse_point[i];
   2.631 +							if (rotate(strings) != NULL)
   2.632 +							{
   2.633 +								err = SMCError_InvalidTokens;
   2.634 +								goto failed;
   2.635 +							}
   2.636 +						}
   2.637 +						strings[0].ptr = &parse_point[i];
   2.638 +						in_quote = true;
   2.639 +						ignoring = true;
   2.640 +					} 
   2.641 +					else if (!strings[0].ptr) 
   2.642 +					{
   2.643 +						/* If we have no string, we must start one */
   2.644 +						strings[0].ptr = &parse_point[i];
   2.645 +					}
   2.646 +					if (restage && strings[0].ptr)
   2.647 +					{
   2.648 +						strings[0].end = &parse_point[i];
   2.649 +						if (rotate(strings) != NULL)
   2.650 +						{
   2.651 +							err = SMCError_InvalidTokens;
   2.652 +							goto failed;
   2.653 +						}
   2.654 +					}
   2.655 +				} 
   2.656 +				else 
   2.657 +				{
   2.658 +					/* If we're eating a string and get whitespace, we need to restage.
   2.659 +					 * (Note that if we are quoted, this is being ignored)
   2.660 +					 */
   2.661 +					if (strings[0].ptr)
   2.662 +					{
   2.663 +						/*
   2.664 +						 * The specification says the second string in a pair does not need to be quoted.
   2.665 +						 * Thus, we check if there's already a string on the stack.
   2.666 +						 * If there's a newline, we always rotate so the newline has an empty starter.
   2.667 +						 */
   2.668 +						if (!strings[1].ptr)
   2.669 +						{
   2.670 +							/* There's no string, so we must move this one down and eat up another */
   2.671 +							strings[0].end = &parse_point[i];
   2.672 +							rotate(strings);
   2.673 +						} 
   2.674 +						else if (!strings[1].quoted) 
   2.675 +						{
   2.676 +							err = SMCError_InvalidTokens;
   2.677 +							goto failed;
   2.678 +						}
   2.679 +					}
   2.680 +				}
   2.681 +			}
   2.682 +
   2.683 +			/* Advance which token we're on */
   2.684 +			states.col++;
   2.685 +		}
   2.686 +
   2.687 +		if (line_begin != in_buf)
   2.688 +		{
   2.689 +			/* The line buffer has advanced, so it's safe to copy N bytes back to the beginning.
   2.690 +			 * What's N?  N is the lowest point we're currently relying on.
   2.691 +			 */
   2.692 +			char *stage = lowstring(strings);
   2.693 +			if (!stage || stage > line_begin)
   2.694 +			{
   2.695 +				stage = line_begin;
   2.696 +			}
   2.697 +			unsigned int bytes = read - (stage - parse_point);
   2.698 +
   2.699 +			/* It is now safe to delete everything before the staged point */
   2.700 +			memmove(in_buf, stage, bytes);
   2.701 +
   2.702 +			/* Calculate the number of bytes in the new buffer */
   2.703 +			bytes = stage - in_buf;
   2.704 +			/* Relocate all the cached pointers to our new base */
   2.705 +			line_begin -= bytes;
   2.706 +			reloc(strings[0], bytes);
   2.707 +			reloc(strings[1], bytes);
   2.708 +			reloc(strings[2], bytes);
   2.709 +			if (reparse_point)
   2.710 +			{
   2.711 +				reparse_point -= bytes;
   2.712 +			}
   2.713 +			if (parse_point)
   2.714 +			{
   2.715 +				parse_point = &parse_point[read];
   2.716 +				parse_point -= bytes;
   2.717 +			}
   2.718 +		} 
   2.719 +		else if (read == sizeof(in_buf) - 1) 
   2.720 +		{
   2.721 +			err = SMCError_TokenOverflow;
   2.722 +			goto failed;
   2.723 +		}
   2.724 +	}
   2.725 +
   2.726 +	/* If we're done parsing and there are tokens left over... */
   2.727 +	if (curlevel)
   2.728 +	{
   2.729 +		err = SMCError_InvalidSection5;
   2.730 +		goto failed;
   2.731 +	} 
   2.732 +	else if (strings[0].ptr || strings[1].ptr) 
   2.733 +	{
   2.734 +		err = SMCError_InvalidTokens;
   2.735 +		goto failed;
   2.736 +	}
   2.737 +	
   2.738 +	smc->ReadSMC_ParseEnd(false, false);
   2.739 +	
   2.740 +	if (pStates != NULL)
   2.741 +	{
   2.742 +		*pStates = states;
   2.743 +	}
   2.744 +
   2.745 +	return SMCError_Okay;
   2.746 +
   2.747 +failed:
   2.748 +	if (pStates != NULL)
   2.749 +	{
   2.750 +		*pStates = states;
   2.751 +	}
   2.752 +
   2.753 +	smc->ReadSMC_ParseEnd(true, (err == SMCError_Custom));
   2.754 +
   2.755 +	return err;
   2.756 +}
   2.757 +
   2.758 +
   2.759 +/**
   2.760 + * INI parser 
   2.761 + */
   2.762 +
   2.763 +bool TextParsers::ParseFile_INI(const char *file, ITextListener_INI *ini_listener, unsigned int *line, unsigned int *col)
   2.764 +{
   2.765 +	FILE *fp = fopen(file, "rt");
   2.766 +	unsigned int curline = 0;
   2.767 +	unsigned int curtok;
   2.768 +	size_t len;
   2.769 +
   2.770 +	if (!fp)
   2.771 +	{
   2.772 +		if (line)
   2.773 +		{
   2.774 +			*line = 0;
   2.775 +		}
   2.776 +
   2.777 +		return false;
   2.778 +	}
   2.779 +
   2.780 +	char buffer[2048];
   2.781 +	char *ptr, *save_ptr;
   2.782 +	bool in_quote;
   2.783 +
   2.784 +	while (!feof(fp))
   2.785 +	{
   2.786 +		curline++;
   2.787 +		curtok = 0;
   2.788 +		buffer[0] = '\0';
   2.789 +		if (fgets(buffer, sizeof(buffer), fp) == NULL)
   2.790 +		{
   2.791 +			break;
   2.792 +		}
   2.793 +
   2.794 +		//:TODO: this will only run once, so find a nice way to move it out of the while loop
   2.795 +		/* If this is the first line, check the first three bytes for BOM */
   2.796 +		if (curline == 1 && 
   2.797 +			buffer[0] == (char)0xEF && 
   2.798 +			buffer[1] == (char)0xBB && 
   2.799 +			buffer[2] == (char)0xBF)
   2.800 +		{
   2.801 +			/* We have a UTF-8 marked file... skip these bytes */
   2.802 +			ptr = &buffer[3];
   2.803 +		} else {
   2.804 +			ptr = buffer;
   2.805 +		}
   2.806 +
   2.807 +		/***************************************************
   2.808 +		 * We preprocess the string before parsing tokens! *
   2.809 +		 ***************************************************/
   2.810 +
   2.811 +		/* First strip beginning whitespace */
   2.812 +		while (*ptr != '\0' && g_ws_chartable[(unsigned)*ptr] != 0)
   2.813 +		{
   2.814 +			ptr++;
   2.815 +		}
   2.816 +
   2.817 +		len = strlen(ptr);
   2.818 +
   2.819 +		if (!len)
   2.820 +		{
   2.821 +			continue;
   2.822 +		}
   2.823 +
   2.824 +		/* Now search for comment characters */
   2.825 +		in_quote = false;
   2.826 +		save_ptr = ptr;
   2.827 +		for (size_t i=0; i<len; i++,ptr++)
   2.828 +		{
   2.829 +			if (!in_quote)
   2.830 +			{
   2.831 +				switch (*ptr)
   2.832 +				{
   2.833 +				case '"':
   2.834 +					{
   2.835 +						in_quote = true;
   2.836 +						break;
   2.837 +					}
   2.838 +				case ';':
   2.839 +					{
   2.840 +						/* Stop the loop */
   2.841 +						len = i;
   2.842 +						/* Terminate the string here */
   2.843 +						*ptr = '\0';
   2.844 +						break;
   2.845 +					}
   2.846 +				}
   2.847 +			} else {
   2.848 +				if (*ptr == '"')
   2.849 +				{
   2.850 +					in_quote = false;
   2.851 +				}
   2.852 +			}
   2.853 +		}
   2.854 +
   2.855 +		if (!len)
   2.856 +		{
   2.857 +			continue;
   2.858 +		}
   2.859 +
   2.860 +		ptr = save_ptr;
   2.861 +
   2.862 +		/* Lastly, strip ending whitespace off */
   2.863 +		for (size_t i=len-1; i>=0 && i<len; i--)
   2.864 +		{
   2.865 +			if (g_ws_chartable[(unsigned)ptr[i]])
   2.866 +			{
   2.867 +				ptr[i] = '\0';
   2.868 +				len--;
   2.869 +			} else {
   2.870 +				break;
   2.871 +			}
   2.872 +		}
   2.873 +
   2.874 +		if (!len)
   2.875 +		{
   2.876 +			continue;
   2.877 +		}
   2.878 +
   2.879 +		if (!ini_listener->ReadINI_RawLine(ptr, &curtok))
   2.880 +		{
   2.881 +			goto event_failed;
   2.882 +		}
   2.883 +
   2.884 +		if (*ptr == '[')
   2.885 +		{
   2.886 +			bool invalid_tokens = false;
   2.887 +			bool got_bracket = false;
   2.888 +			bool extra_tokens = false;
   2.889 +			char c;
   2.890 +			bool alnum;
   2.891 +			wchar_t wc;
   2.892 +
   2.893 +			for (size_t i=1; i<len; i++)
   2.894 +			{
   2.895 +				c = ptr[i];
   2.896 +				alnum = false;
   2.897 +
   2.898 +				if (c & (1<<7))
   2.899 +				{
   2.900 +					if (mbtowc(&wc, &ptr[i], len-i) != -1)
   2.901 +					{
   2.902 +						alnum = (iswalnum(wc) != 0);
   2.903 +						i += _GetUTF8CharBytes(&ptr[i]) - 1;
   2.904 +					}
   2.905 +				} else {
   2.906 +					alnum = (isalnum(c) != 0) || (g_ini_chartable1[(unsigned)c] != 0);
   2.907 +				}
   2.908 +				if (!alnum)
   2.909 +				{
   2.910 +					/* First check - is this a bracket? */
   2.911 +					if (c == ']')
   2.912 +					{
   2.913 +						/* Yes! */
   2.914 +						got_bracket = true;
   2.915 +						/* If this isn't the last character... */
   2.916 +						if (i != len - 1)
   2.917 +						{
   2.918 +							extra_tokens = true;
   2.919 +						}
   2.920 +						/* terminate */
   2.921 +						ptr[i] = '\0';
   2.922 +						break;
   2.923 +					} else {
   2.924 +						/* n...No! Continue copying. */
   2.925 +						invalid_tokens = true;
   2.926 +					}
   2.927 +				}
   2.928 +			}
   2.929 +
   2.930 +			/* Tell the handler */
   2.931 +			if (!ini_listener->ReadINI_NewSection(&ptr[1], invalid_tokens, got_bracket, extra_tokens, &curtok))
   2.932 +			{
   2.933 +				goto event_failed;
   2.934 +			}
   2.935 +		} else {
   2.936 +			char *key_ptr = ptr;
   2.937 +			char *val_ptr = NULL;
   2.938 +			char c;
   2.939 +			size_t first_space = 0;
   2.940 +			bool invalid_tokens = false;
   2.941 +			bool equal_token = false;
   2.942 +			bool quotes = false;
   2.943 +			bool alnum;
   2.944 +			wchar_t wc;
   2.945 +
   2.946 +			for (size_t i=0; i<len; i++)
   2.947 +			{
   2.948 +				c = ptr[i];
   2.949 +				alnum = false;
   2.950 +				/* is this an invalid char? */
   2.951 +				if (c & (1<<7))
   2.952 +				{
   2.953 +					if (mbtowc(&wc, &ptr[i], len-i) != -1)
   2.954 +					{
   2.955 +						alnum = (iswalnum(wc) != 0);
   2.956 +						i += _GetUTF8CharBytes(&ptr[i]) - 1;
   2.957 +					}
   2.958 +				} else {
   2.959 +					alnum = (isalnum(c) != 0) || (g_ini_chartable1[(unsigned)c] != 0);
   2.960 +				}
   2.961 +
   2.962 +				if (!alnum)
   2.963 +				{
   2.964 +					if (g_ws_chartable[(unsigned)c])
   2.965 +					{
   2.966 +						/* if it's a space, keep track of the first occurring space */
   2.967 +						if (!first_space)
   2.968 +						{
   2.969 +							first_space = i;
   2.970 +						}
   2.971 +					} else {
   2.972 +						if (c == '=')
   2.973 +						{
   2.974 +							/* if it's an equal sign, we're done with the key */
   2.975 +							if (first_space)
   2.976 +							{
   2.977 +								/* remove excess whitespace */
   2.978 +								key_ptr[first_space] = '\0';
   2.979 +							} else {
   2.980 +								/* remove the equal sign */
   2.981 +								key_ptr[i] = '\0';
   2.982 +							}
   2.983 +							if (ptr[++i] != '\0')
   2.984 +							{
   2.985 +								/* If this isn't the end, set next pointer */
   2.986 +								val_ptr = &ptr[i];
   2.987 +							}
   2.988 +							equal_token = true;
   2.989 +							break;
   2.990 +						} else {
   2.991 +							/* Mark that we got something invalid! */
   2.992 +							invalid_tokens = true;
   2.993 +							first_space = 0;
   2.994 +						}
   2.995 +					}
   2.996 +				}
   2.997 +			}
   2.998 +
   2.999 +			/* Now we need to parse the value, if any */
  2.1000 +			if (val_ptr)
  2.1001 +			{
  2.1002 +				/* eat up spaces! there shouldn't be any h*/
  2.1003 +				while ((*val_ptr != '\0') && g_ws_chartable[(unsigned)*val_ptr] != 0)
  2.1004 +				{
  2.1005 +					val_ptr++;
  2.1006 +				}
  2.1007 +				if (*val_ptr == '\0')
  2.1008 +				{
  2.1009 +					val_ptr = NULL;
  2.1010 +					goto skip_value;
  2.1011 +				}
  2.1012 +				/* Do we have an initial quote? If so, the parsing rules change! */
  2.1013 +				if (*val_ptr == '"' && *val_ptr != '\0')
  2.1014 +				{
  2.1015 +					len = strlen(val_ptr);
  2.1016 +					if (val_ptr[len-1] == '"')
  2.1017 +					{
  2.1018 +						/* Strip quotes! */
  2.1019 +						val_ptr[--len] = '\0';
  2.1020 +						val_ptr++;
  2.1021 +						quotes = true;
  2.1022 +					}
  2.1023 +				}
  2.1024 +			}
  2.1025 +skip_value:
  2.1026 +			/* We're done! */
  2.1027 +			curtok = val_ptr - buffer;
  2.1028 +			if (!ini_listener->ReadINI_KeyValue(key_ptr, val_ptr, invalid_tokens, equal_token, quotes, &curtok))
  2.1029 +			{
  2.1030 +				curtok = 0;
  2.1031 +				goto event_failed;
  2.1032 +			}
  2.1033 +		}
  2.1034 +	}
  2.1035 +
  2.1036 +	if (line)
  2.1037 +	{
  2.1038 +		*line = curline;
  2.1039 +	}
  2.1040 +
  2.1041 +	fclose(fp);
  2.1042 +
  2.1043 +	return true;
  2.1044 +
  2.1045 +event_failed:
  2.1046 +	if (line)
  2.1047 +	{
  2.1048 +		*line = curline;
  2.1049 +	}
  2.1050 +
  2.1051 +	if (col)
  2.1052 +	{
  2.1053 +		*col = curtok;
  2.1054 +	}
  2.1055 +
  2.1056 +	fclose(fp);
  2.1057 +
  2.1058 +	return false;
  2.1059 +}
  2.1060 +
  2.1061 +const char *TextParsers::GetSMCErrorString(SMCError err)
  2.1062 +{
  2.1063 +	static const char *s_errors[] = 
  2.1064 +	{
  2.1065 +		NULL,
  2.1066 +		"Stream failed to open",
  2.1067 +		"Stream returned read error",
  2.1068 +		NULL,
  2.1069 +		"Un-quoted section has invalid tokens",
  2.1070 +		"Section declared without header",
  2.1071 +		"Section declared with unknown tokens",
  2.1072 +		"Section ending without a matching section beginning",
  2.1073 +		"Section beginning without a matching ending",
  2.1074 +		"Line contained too many invalid tokens",
  2.1075 +		"Token buffer overflowed",
  2.1076 +		"A property was declared outside of a section",
  2.1077 +	};
  2.1078 +
  2.1079 +	if (err < SMCError_Okay || err > SMCError_InvalidProperty1)
  2.1080 +	{
  2.1081 +		return NULL;
  2.1082 +	}
  2.1083 +
  2.1084 +	return s_errors[err];
  2.1085 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/gamedata md5/TextParsers.h	Sun Jun 29 22:23:14 2008 +0000
     3.3 @@ -0,0 +1,87 @@
     3.4 +/**
     3.5 + * vim: set ts=4 :
     3.6 + * =============================================================================
     3.7 + * SourceMod
     3.8 + * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     3.9 + * =============================================================================
    3.10 + *
    3.11 + * This program is free software; you can redistribute it and/or modify it under
    3.12 + * the terms of the GNU General Public License, version 3.0, as published by the
    3.13 + * Free Software Foundation.
    3.14 + * 
    3.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
    3.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    3.17 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    3.18 + * details.
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License along with
    3.21 + * this program.  If not, see <http://www.gnu.org/licenses/>.
    3.22 + *
    3.23 + * As a special exception, AlliedModders LLC gives you permission to link the
    3.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
    3.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    3.26 + * by the Valve Corporation.  You must obey the GNU General Public License in
    3.27 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
    3.28 + * this exception to all derivative works.  AlliedModders LLC defines further
    3.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    3.30 + * or <http://www.sourcemod.net/license.php>.
    3.31 + *
    3.32 + * Version: $Id$
    3.33 + */
    3.34 +
    3.35 +#ifndef _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
    3.36 +#define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
    3.37 +
    3.38 +#include "ITextParsers.h"
    3.39 +#include "main.h"
    3.40 +
    3.41 +using namespace SourceMod;
    3.42 +
    3.43 +/**
    3.44 + * @param void *			IN: Stream pointer
    3.45 + * @param char *			IN/OUT: Stream buffer
    3.46 + * @param size_t			IN: Maximum size of buffer
    3.47 + * @param unsigned int *	OUT: Number of bytes read (0 = end of stream)
    3.48 + * @return					True on success, false on failure
    3.49 + */
    3.50 +typedef bool (*STREAMREADER)(void *, char *, size_t, unsigned int *);
    3.51 +
    3.52 +class TextParsers : public ITextParsers
    3.53 +{
    3.54 +public:
    3.55 +	TextParsers();
    3.56 +public:
    3.57 +	bool ParseFile_INI(const char *file, 
    3.58 +		ITextListener_INI *ini_listener,
    3.59 +		unsigned int *line,
    3.60 +		unsigned int *col);
    3.61 +
    3.62 +	SMCError ParseFile_SMC(const char *file, 
    3.63 +		ITextListener_SMC *smc_listener, 
    3.64 +		SMCStates *states);
    3.65 +
    3.66 +	SMCError ParseSMCFile(const char *file,
    3.67 +			ITextListener_SMC *smc_listener,
    3.68 +			SMCStates *states,
    3.69 +			char *buffer,
    3.70 +			size_t maxsize);
    3.71 +
    3.72 +	unsigned int GetUTF8CharBytes(const char *stream);
    3.73 +
    3.74 +	const char *GetSMCErrorString(SMCError err);
    3.75 +	bool IsWhitespace(const char *stream);
    3.76 +private:
    3.77 +	SMCError ParseString_SMC(const char *stream, 
    3.78 +		ITextListener_SMC *smc,
    3.79 +		SMCStates *states);
    3.80 +	SMCError ParseStream_SMC(void *stream, 
    3.81 +		STREAMREADER srdr,
    3.82 +		ITextListener_SMC *smc,
    3.83 +		SMCStates *states);
    3.84 +
    3.85 +};
    3.86 +
    3.87 +extern TextParsers g_TextParser;
    3.88 +
    3.89 +#endif //_INCLUDE_SOURCEMOD_TEXTPARSERS_H_
    3.90 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/gamedata md5/main.cpp	Sun Jun 29 22:23:14 2008 +0000
     4.3 @@ -0,0 +1,45 @@
     4.4 +#include "main.h"
     4.5 +#include <stdarg.h>
     4.6 +
     4.7 +BuildMD5ableBuffer g_MD5Builder;
     4.8 +
     4.9 +int main(int argc, char **argv)
    4.10 +{
    4.11 +	SMCStates states;
    4.12 +	SMCError error;
    4.13 +
    4.14 +	if (argc < 2)
    4.15 +	{
    4.16 +		fprintf(stderr, "Usage: <file>\n");
    4.17 +		return -1;
    4.18 +	}
    4.19 +
    4.20 +	error = g_TextParser.ParseFile_SMC(argv[1], &g_MD5Builder, &states);
    4.21 +
    4.22 +	if (error == SMCError_Okay)
    4.23 +	{
    4.24 +		printf("MD5: %s\n", g_MD5Builder.GetMD5String());
    4.25 +		return 0;
    4.26 +	}
    4.27 +
    4.28 +	fprintf(stderr, "Failed to parse file, Error %i at line %i and col %i\n", error, states.line, states.col);
    4.29 +	return -1;
    4.30 +}
    4.31 +
    4.32 +size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
    4.33 +{
    4.34 +	va_list ap;
    4.35 +	va_start(ap, fmt);
    4.36 +	size_t len = vsnprintf(buffer, maxlength, fmt, ap);
    4.37 +	va_end(ap);
    4.38 +
    4.39 +	if (len >= maxlength)
    4.40 +	{
    4.41 +		buffer[maxlength - 1] = '\0';
    4.42 +		return (maxlength - 1);
    4.43 +	}
    4.44 +	else
    4.45 +	{
    4.46 +		return len;
    4.47 +	}
    4.48 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/gamedata md5/main.h	Sun Jun 29 22:23:14 2008 +0000
     5.3 @@ -0,0 +1,88 @@
     5.4 +#ifndef _INCLUDE_GAMEDATAMD5_MAIN_H_
     5.5 +#define _INCLUDE_GAMEDATAMD5_MAIN_H_
     5.6 +
     5.7 +#include "TextParsers.h"
     5.8 +#include "sm_memtable.h"
     5.9 +#include "md5.h"
    5.10 +
    5.11 +using namespace SourceMod;
    5.12 +
    5.13 +size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
    5.14 +
    5.15 +class BuildMD5ableBuffer : public ITextListener_SMC
    5.16 +{
    5.17 +public:
    5.18 +
    5.19 +	BuildMD5ableBuffer()
    5.20 +	{
    5.21 +		stringTable = new BaseStringTable(2048);
    5.22 +		md5[0] = 0;
    5.23 +		md5String[0] = 0;
    5.24 +	}
    5.25 +
    5.26 +	~BuildMD5ableBuffer()
    5.27 +	{
    5.28 +		delete stringTable;
    5.29 +	}
    5.30 +
    5.31 +	void ReadSMC_ParseStart()
    5.32 +	{
    5.33 +		checksum = MD5();
    5.34 +	}
    5.35 +
    5.36 +	SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
    5.37 +	{
    5.38 +		stringTable->AddString(key);
    5.39 +		stringTable->AddString(value);
    5.40 +
    5.41 +		return SMCResult_Continue;
    5.42 +	}
    5.43 +
    5.44 +	SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name)
    5.45 +	{
    5.46 +		stringTable->AddString(name);
    5.47 +
    5.48 +		return SMCResult_Continue;
    5.49 +	}
    5.50 +
    5.51 +	void ReadSMC_ParseEnd(bool halted, bool failed)
    5.52 +	{
    5.53 +		if (halted || failed)
    5.54 +		{
    5.55 +			return;
    5.56 +		}
    5.57 +
    5.58 +		void *data = stringTable->GetMemTable()->GetAddress(0);
    5.59 +
    5.60 +		if (data != NULL)
    5.61 +		{
    5.62 +			checksum.update((unsigned char *)data, stringTable->GetMemTable()->GetActualMemUsed());
    5.63 +		}
    5.64 +
    5.65 +		checksum.finalize();
    5.66 +
    5.67 +		checksum.hex_digest(md5String);
    5.68 +		checksum.raw_digest(md5);
    5.69 +
    5.70 +		stringTable->Reset();
    5.71 +	}
    5.72 +
    5.73 +	unsigned char * GetMD5()
    5.74 +	{
    5.75 +		return md5;
    5.76 +	}
    5.77 +
    5.78 +	unsigned char * GetMD5String()
    5.79 +	{
    5.80 +		return (unsigned char *)&md5String[0];
    5.81 +	}
    5.82 +
    5.83 +private:
    5.84 +	MD5 checksum;
    5.85 +	unsigned char md5[16];
    5.86 +	char md5String[33];
    5.87 +	BaseStringTable *stringTable;
    5.88 +};
    5.89 +
    5.90 +
    5.91 +#endif // _INCLUDE_GAMEDATAMD5_MAIN_H_
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/gamedata md5/md5.cpp	Sun Jun 29 22:23:14 2008 +0000
     6.3 @@ -0,0 +1,485 @@
     6.4 +// MD5.CC - source code for the C++/object oriented translation and 
     6.5 +//          modification of MD5.
     6.6 +
     6.7 +// Translation and modification (c) 1995 by Mordechai T. Abzug 
     6.8 +
     6.9 +// This translation/ modification is provided "as is," without express or 
    6.10 +// implied warranty of any kind.
    6.11 +
    6.12 +// The translator/ modifier does not claim (1) that MD5 will do what you think 
    6.13 +// it does; (2) that this translation/ modification is accurate; or (3) that 
    6.14 +// this software is "merchantible."  (Language for this disclaimer partially 
    6.15 +// copied from the disclaimer below).
    6.16 +
    6.17 +/* based on:
    6.18 +
    6.19 +   MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
    6.20 +   MDDRIVER.C - test driver for MD2, MD4 and MD5
    6.21 +
    6.22 +
    6.23 +   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
    6.24 +rights reserved.
    6.25 +
    6.26 +License to copy and use this software is granted provided that it
    6.27 +is identified as the "RSA Data Security, Inc. MD5 Message-Digest
    6.28 +Algorithm" in all material mentioning or referencing this software
    6.29 +or this function.
    6.30 +
    6.31 +License is also granted to make and use derivative works provided
    6.32 +that such works are identified as "derived from the RSA Data
    6.33 +Security, Inc. MD5 Message-Digest Algorithm" in all material
    6.34 +mentioning or referencing the derived work.
    6.35 +
    6.36 +RSA Data Security, Inc. makes no representations concerning either
    6.37 +the merchantability of this software or the suitability of this
    6.38 +software for any particular purpose. It is provided "as is"
    6.39 +without express or implied warranty of any kind.
    6.40 +
    6.41 +These notices must be retained in any copies of any part of this
    6.42 +documentation and/or software.
    6.43 +
    6.44 + */
    6.45 +
    6.46 +#include "md5.h"
    6.47 +
    6.48 +#include <assert.h>
    6.49 +#include <string.h>
    6.50 +
    6.51 +// MD5 simple initialization method
    6.52 +
    6.53 +MD5::MD5(){
    6.54 +
    6.55 +  init();
    6.56 +
    6.57 +}
    6.58 +
    6.59 +
    6.60 +// MD5 block update operation. Continues an MD5 message-digest
    6.61 +// operation, processing another message block, and updating the
    6.62 +// context.
    6.63 +
    6.64 +void MD5::update (uint1 *input, uint4 input_length) {
    6.65 +
    6.66 +  uint4 input_index, buffer_index;
    6.67 +  uint4 buffer_space;                // how much space is left in buffer
    6.68 +
    6.69 +  if (finalized){  // so we can't update!
    6.70 +    /*cerr << "MD5::update:  Can't update a finalized digest!" << endl;*/
    6.71 +    return;
    6.72 +  }
    6.73 +
    6.74 +  // Compute number of bytes mod 64
    6.75 +  buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
    6.76 +
    6.77 +  // Update number of bits
    6.78 +  if (  (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
    6.79 +    count[1]++;
    6.80 +
    6.81 +  count[1] += ((uint4)input_length >> 29);
    6.82 +
    6.83 +
    6.84 +  buffer_space = 64 - buffer_index;  // how much space is left in buffer
    6.85 +
    6.86 +  // Transform as many times as possible.
    6.87 +  if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
    6.88 +    // fill the rest of the buffer and transform
    6.89 +    memcpy (buffer + buffer_index, input, buffer_space);
    6.90 +    transform (buffer);
    6.91 +
    6.92 +    // now, transform each 64-byte piece of the input, bypassing the buffer
    6.93 +    for (input_index = buffer_space; input_index + 63 < input_length; 
    6.94 +	 input_index += 64)
    6.95 +      transform (input+input_index);
    6.96 +
    6.97 +    buffer_index = 0;  // so we can buffer remaining
    6.98 +  }
    6.99 +  else
   6.100 +    input_index=0;     // so we can buffer the whole input
   6.101 +
   6.102 +
   6.103 +  // and here we do the buffering:
   6.104 +  memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
   6.105 +}
   6.106 +
   6.107 +
   6.108 +
   6.109 +// MD5 update for files.
   6.110 +// Like above, except that it works on files (and uses above as a primitive.)
   6.111 +
   6.112 +void MD5::update(FILE *file){
   6.113 +
   6.114 +  unsigned char buffer[1024];
   6.115 +  int len;
   6.116 +
   6.117 +  while ((len=fread(buffer, 1, 1024, file)))
   6.118 +    update(buffer, len);
   6.119 +
   6.120 +  fclose (file);
   6.121 +
   6.122 +}
   6.123 +
   6.124 +
   6.125 +// MD5 finalization. Ends an MD5 message-digest operation, writing the
   6.126 +// the message digest and zeroizing the context.
   6.127 +
   6.128 +
   6.129 +void MD5::finalize (){
   6.130 +
   6.131 +  unsigned char bits[8];
   6.132 +  unsigned int index, padLen;
   6.133 +  static uint1 PADDING[64]={
   6.134 +    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   6.135 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   6.136 +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   6.137 +    };
   6.138 +
   6.139 +  if (finalized){
   6.140 +   /* cerr << "MD5::finalize:  Already finalized this digest!" << endl;*/
   6.141 +    return;
   6.142 +  }
   6.143 +
   6.144 +  // Save number of bits
   6.145 +  encode (bits, count, 8);
   6.146 +
   6.147 +  // Pad out to 56 mod 64.
   6.148 +  index = (uint4) ((count[0] >> 3) & 0x3f);
   6.149 +  padLen = (index < 56) ? (56 - index) : (120 - index);
   6.150 +  update (PADDING, padLen);
   6.151 +
   6.152 +  // Append length (before padding)
   6.153 +  update (bits, 8);
   6.154 +
   6.155 +  // Store state in digest
   6.156 +  encode (digest, state, 16);
   6.157 +
   6.158 +  // Zeroize sensitive information
   6.159 +  memset (buffer, 0, sizeof(*buffer));
   6.160 +
   6.161 +  finalized=1;
   6.162 +
   6.163 +}
   6.164 +
   6.165 +
   6.166 +
   6.167 +
   6.168 +MD5::MD5(FILE *file){
   6.169 +
   6.170 +  init();  // must be called be all constructors
   6.171 +  update(file);
   6.172 +  finalize ();
   6.173 +}
   6.174 +
   6.175 +unsigned char *MD5::raw_digest(){
   6.176 +
   6.177 +  uint1 *s = new uint1[16];
   6.178 +
   6.179 +  if (!finalized){
   6.180 +/*    cerr << "MD5::raw_digest:  Can't get digest if you haven't "<<
   6.181 +      "finalized the digest!" <<endl;*/
   6.182 +    return ( (unsigned char*) "");
   6.183 +  }
   6.184 +
   6.185 +  memcpy(s, digest, 16);
   6.186 +  return s;
   6.187 +}
   6.188 +
   6.189 +unsigned char *MD5::raw_digest(unsigned char buffer[16])
   6.190 +{
   6.191 +	if (!finalized)
   6.192 +	{
   6.193 +		return ( (unsigned char*) "");
   6.194 +	}
   6.195 +
   6.196 +	 memcpy(buffer, digest, 16);
   6.197 +	 return buffer;
   6.198 +}
   6.199 +
   6.200 +
   6.201 +
   6.202 +char *MD5::hex_digest(){
   6.203 +
   6.204 +  int i;
   6.205 +  char *s= new char[33];
   6.206 +
   6.207 +  if (!finalized){
   6.208 +/*    cerr << "MD5::hex_digest:  Can't get digest if you haven't "<<
   6.209 +      "finalized the digest!" <<endl;*/
   6.210 +    return "";
   6.211 +  }
   6.212 +
   6.213 +  for (i=0; i<16; i++)
   6.214 +    sprintf(s+i*2, "%02x", digest[i]);
   6.215 +
   6.216 +  s[32]='\0';
   6.217 +
   6.218 +  return s;
   6.219 +}
   6.220 +
   6.221 +
   6.222 +char *MD5::hex_digest(char buffer[33]){
   6.223 +
   6.224 +  int i;
   6.225 +
   6.226 +  if (!finalized)
   6.227 +  {
   6.228 +	 /* cerr << "MD5::hex_digest:  Can't get digest if you haven't "<<
   6.229 +      "finalized the digest!" <<endl;*/
   6.230 +    return "";
   6.231 +  }
   6.232 +
   6.233 +  for (i=0; i<16; i++)
   6.234 +    sprintf(buffer+i*2, "%02x", digest[i]);
   6.235 +
   6.236 +  buffer[32]='\0';
   6.237 +
   6.238 +  return buffer;
   6.239 +}
   6.240 +
   6.241 +
   6.242 +// PRIVATE METHODS:
   6.243 +
   6.244 +
   6.245 +
   6.246 +void MD5::init(){
   6.247 +  finalized=0;  // we just started!
   6.248 +
   6.249 +  // Nothing counted, so count=0
   6.250 +  count[0] = 0;
   6.251 +  count[1] = 0;
   6.252 +
   6.253 +  // Load magic initialization constants.
   6.254 +  state[0] = 0x67452301;
   6.255 +  state[1] = 0xefcdab89;
   6.256 +  state[2] = 0x98badcfe;
   6.257 +  state[3] = 0x10325476;
   6.258 +}
   6.259 +
   6.260 +
   6.261 +
   6.262 +// Constants for MD5Transform routine.
   6.263 +// Although we could use C++ style constants, defines are actually better,
   6.264 +// since they let us easily evade scope clashes.
   6.265 +
   6.266 +#define S11 7
   6.267 +#define S12 12
   6.268 +#define S13 17
   6.269 +#define S14 22
   6.270 +#define S21 5
   6.271 +#define S22 9
   6.272 +#define S23 14
   6.273 +#define S24 20
   6.274 +#define S31 4
   6.275 +#define S32 11
   6.276 +#define S33 16
   6.277 +#define S34 23
   6.278 +#define S41 6
   6.279 +#define S42 10
   6.280 +#define S43 15
   6.281 +#define S44 21
   6.282 +
   6.283 +
   6.284 +
   6.285 +
   6.286 +// MD5 basic transformation. Transforms state based on block.
   6.287 +void MD5::transform (uint1 block[64]){
   6.288 +
   6.289 +  uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
   6.290 +
   6.291 +  decode (x, block, 64);
   6.292 +
   6.293 +  assert(!finalized);  // not just a user error, since the method is private
   6.294 +
   6.295 +  /* Round 1 */
   6.296 +  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
   6.297 +  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
   6.298 +  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
   6.299 +  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
   6.300 +  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
   6.301 +  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
   6.302 +  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
   6.303 +  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
   6.304 +  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
   6.305 +  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
   6.306 +  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
   6.307 +  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
   6.308 +  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
   6.309 +  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
   6.310 +  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
   6.311 +  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
   6.312 +
   6.313 + /* Round 2 */
   6.314 +  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
   6.315 +  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
   6.316 +  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
   6.317 +  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
   6.318 +  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
   6.319 +  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
   6.320 +  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
   6.321 +  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
   6.322 +  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
   6.323 +  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
   6.324 +  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
   6.325 +  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
   6.326 +  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
   6.327 +  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
   6.328 +  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
   6.329 +  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
   6.330 +
   6.331 +  /* Round 3 */
   6.332 +  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
   6.333 +  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
   6.334 +  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
   6.335 +  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
   6.336 +  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
   6.337 +  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
   6.338 +  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
   6.339 +  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
   6.340 +  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
   6.341 +  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
   6.342 +  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
   6.343 +  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
   6.344 +  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
   6.345 +  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
   6.346 +  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
   6.347 +  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
   6.348 +
   6.349 +  /* Round 4 */
   6.350 +  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
   6.351 +  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
   6.352 +  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
   6.353 +  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
   6.354 +  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
   6.355 +  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
   6.356 +  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
   6.357 +  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
   6.358 +  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
   6.359 +  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
   6.360 +  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
   6.361 +  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
   6.362 +  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
   6.363 +  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
   6.364 +  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
   6.365 +  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
   6.366 +
   6.367 +  state[0] += a;
   6.368 +  state[1] += b;
   6.369 +  state[2] += c;
   6.370 +  state[3] += d;
   6.371 +
   6.372 +  // Zeroize sensitive information.
   6.373 +  memset ( (uint1 *) x, 0, sizeof(x));
   6.374 +
   6.375 +}
   6.376 +
   6.377 +
   6.378 +
   6.379 +// Encodes input (UINT4) into output (unsigned char). Assumes len is
   6.380 +// a multiple of 4.
   6.381 +void MD5::encode (uint1 *output, uint4 *input, uint4 len) {
   6.382 +
   6.383 +  unsigned int i, j;
   6.384 +
   6.385 +  for (i = 0, j = 0; j < len; i++, j += 4) {
   6.386 +    output[j]   = (uint1)  (input[i] & 0xff);
   6.387 +    output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
   6.388 +    output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
   6.389 +    output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
   6.390 +  }
   6.391 +}
   6.392 +
   6.393 +
   6.394 +
   6.395 +
   6.396 +// Decodes input (unsigned char) into output (UINT4). Assumes len is
   6.397 +// a multiple of 4.
   6.398 +void MD5::decode (uint4 *output, uint1 *input, uint4 len){
   6.399 +
   6.400 +  unsigned int i, j;
   6.401 +
   6.402 +  for (i = 0, j = 0; j < len; i++, j += 4)
   6.403 +    output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
   6.404 +      (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
   6.405 +}
   6.406 +
   6.407 +
   6.408 +
   6.409 +
   6.410 +
   6.411 +// Note: Replace "for loop" with standard memcpy if possible.
   6.412 +void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){
   6.413 +
   6.414 +  unsigned int i;
   6.415 +
   6.416 +  for (i = 0; i < len; i++)
   6.417 +    output[i] = input[i];
   6.418 +}
   6.419 +
   6.420 +
   6.421 +
   6.422 +// Note: Replace "for loop" with standard memset if possible.
   6.423 +void MD5::memset (uint1 *output, uint1 value, uint4 len){
   6.424 +
   6.425 +  unsigned int i;
   6.426 +
   6.427 +  for (i = 0; i < len; i++)
   6.428 +    output[i] = value;
   6.429 +}
   6.430 +
   6.431 +
   6.432 +
   6.433 +// ROTATE_LEFT rotates x left n bits.
   6.434 +
   6.435 +inline unsigned int MD5::rotate_left  (uint4 x, uint4 n){
   6.436 +  return (x << n) | (x >> (32-n))  ;
   6.437 +}
   6.438 +
   6.439 +
   6.440 +
   6.441 +
   6.442 +// F, G, H and I are basic MD5 functions.
   6.443 +
   6.444 +inline unsigned int MD5::F            (uint4 x, uint4 y, uint4 z){
   6.445 +  return (x & y) | (~x & z);
   6.446 +}
   6.447 +
   6.448 +inline unsigned int MD5::G            (uint4 x, uint4 y, uint4 z){
   6.449 +  return (x & z) | (y & ~z);
   6.450 +}
   6.451 +
   6.452 +inline unsigned int MD5::H            (uint4 x, uint4 y, uint4 z){
   6.453 +  return x ^ y ^ z;
   6.454 +}
   6.455 +
   6.456 +inline unsigned int MD5::I            (uint4 x, uint4 y, uint4 z){
   6.457 +  return y ^ (x | ~z);
   6.458 +}
   6.459 +
   6.460 +
   6.461 +
   6.462 +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
   6.463 +// Rotation is separate from addition to prevent recomputation.
   6.464 +
   6.465 +
   6.466 +inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
   6.467 +		    uint4  s, uint4 ac){
   6.468 + a += F(b, c, d) + x + ac;
   6.469 + a = rotate_left (a, s) +b;
   6.470 +}
   6.471 +
   6.472 +inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
   6.473 +		    uint4 s, uint4 ac){
   6.474 + a += G(b, c, d) + x + ac;
   6.475 + a = rotate_left (a, s) +b;
   6.476 +}
   6.477 +
   6.478 +inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
   6.479 +		    uint4 s, uint4 ac){
   6.480 + a += H(b, c, d) + x + ac;
   6.481 + a = rotate_left (a, s) +b;
   6.482 +}
   6.483 +
   6.484 +inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
   6.485 +			     uint4 s, uint4 ac){
   6.486 + a += I(b, c, d) + x + ac;
   6.487 + a = rotate_left (a, s) +b;
   6.488 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/gamedata md5/md5.h	Sun Jun 29 22:23:14 2008 +0000
     7.3 @@ -0,0 +1,106 @@
     7.4 +// MD5.CC - source code for the C++/object oriented translation and 
     7.5 +//          modification of MD5.
     7.6 +
     7.7 +// Translation and modification (c) 1995 by Mordechai T. Abzug 
     7.8 +
     7.9 +// This translation/ modification is provided "as is," without express or 
    7.10 +// implied warranty of any kind.
    7.11 +
    7.12 +// The translator/ modifier does not claim (1) that MD5 will do what you think 
    7.13 +// it does; (2) that this translation/ modification is accurate; or (3) that 
    7.14 +// this software is "merchantible."  (Language for this disclaimer partially 
    7.15 +// copied from the disclaimer below).
    7.16 +
    7.17 +/* based on:
    7.18 +
    7.19 +   MD5.H - header file for MD5C.C
    7.20 +   MDDRIVER.C - test driver for MD2, MD4 and MD5
    7.21 +
    7.22 +   Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
    7.23 +rights reserved.
    7.24 +
    7.25 +License to copy and use this software is granted provided that it
    7.26 +is identified as the "RSA Data Security, Inc. MD5 Message-Digest
    7.27 +Algorithm" in all material mentioning or referencing this software
    7.28 +or this function.
    7.29 +
    7.30 +License is also granted to make and use derivative works provided
    7.31 +that such works are identified as "derived from the RSA Data
    7.32 +Security, Inc. MD5 Message-Digest Algorithm" in all material
    7.33 +mentioning or referencing the derived work.
    7.34 +
    7.35 +RSA Data Security, Inc. makes no representations concerning either
    7.36 +the merchantability of this software or the suitability of this
    7.37 +software for any particular purpose. It is provided "as is"
    7.38 +without express or implied warranty of any kind.
    7.39 +
    7.40 +These notices must be retained in any copies of any part of this
    7.41 +documentation and/or software.
    7.42 +
    7.43 +*/
    7.44 +
    7.45 +#include <stdio.h>
    7.46 +//#include <fstream.h>
    7.47 +//#include <iostream.h>
    7.48 +
    7.49 +class MD5 {
    7.50 +
    7.51 +public:
    7.52 +// methods for controlled operation:
    7.53 +  MD5              ();  // simple initializer
    7.54 +  void  update     (unsigned char *input, unsigned int input_length);
    7.55 +  void  update     (FILE *file);
    7.56 +  void  finalize   ();
    7.57 +
    7.58 +// constructors for special circumstances.  All these constructors finalize
    7.59 +// the MD5 context.
    7.60 +  MD5              (unsigned char *string); // digest string, finalize
    7.61 +  MD5              (FILE *file);            // digest file, close, finalize
    7.62 +
    7.63 +// methods to acquire finalized result
    7.64 +  unsigned char    *raw_digest ();  // digest as a 16-byte binary array
    7.65 +  unsigned char		*raw_digest(unsigned char buffer[16]);
    7.66 +  char *            hex_digest ();  // digest as a 33-byte ascii-hex string
    7.67 +  char *			hex_digest (char buffer[33]); //same as above, passing buffer
    7.68 +
    7.69 +
    7.70 +
    7.71 +private:
    7.72 +
    7.73 +// first, some types:
    7.74 +  typedef unsigned       int uint4; // assumes integer is 4 words long
    7.75 +  typedef unsigned short int uint2; // assumes short integer is 2 words long
    7.76 +  typedef unsigned      char uint1; // assumes char is 1 word long
    7.77 +
    7.78 +// next, the private data:
    7.79 +  uint4 state[4];
    7.80 +  uint4 count[2];     // number of *bits*, mod 2^64
    7.81 +  uint1 buffer[64];   // input buffer
    7.82 +  uint1 digest[16];
    7.83 +  uint1 finalized;
    7.84 +
    7.85 +// last, the private methods, mostly static:
    7.86 +  void init             ();               // called by all constructors
    7.87 +  void transform        (uint1 *buffer);  // does the real update work.  Note 
    7.88 +                                          // that length is implied to be 64.
    7.89 +
    7.90 +  static void encode    (uint1 *dest, uint4 *src, uint4 length);
    7.91 +  static void decode    (uint4 *dest, uint1 *src, uint4 length);
    7.92 +  static void memcpy    (uint1 *dest, uint1 *src, uint4 length);
    7.93 +  static void memset    (uint1 *start, uint1 val, uint4 length);
    7.94 +
    7.95 +  static inline uint4  rotate_left (uint4 x, uint4 n);
    7.96 +  static inline uint4  F           (uint4 x, uint4 y, uint4 z);
    7.97 +  static inline uint4  G           (uint4 x, uint4 y, uint4 z);
    7.98 +  static inline uint4  H           (uint4 x, uint4 y, uint4 z);
    7.99 +  static inline uint4  I           (uint4 x, uint4 y, uint4 z);
   7.100 +  static inline void   FF  (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
   7.101 +			    uint4 s, uint4 ac);
   7.102 +  static inline void   GG  (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
   7.103 +			    uint4 s, uint4 ac);
   7.104 +  static inline void   HH  (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
   7.105 +			    uint4 s, uint4 ac);
   7.106 +  static inline void   II  (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, 
   7.107 +			    uint4 s, uint4 ac);
   7.108 +
   7.109 +};
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/gamedata md5/msvc9/gamedatamd5.sln	Sun Jun 29 22:23:14 2008 +0000
     8.3 @@ -0,0 +1,20 @@
     8.4 +
     8.5 +Microsoft Visual Studio Solution File, Format Version 10.00
     8.6 +# Visual Studio 2008
     8.7 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gamedatamd5", "gamedatamd5.vcproj", "{E1C96598-E1AC-4928-8930-F8B6CD245B12}"
     8.8 +EndProject
     8.9 +Global
    8.10 +	GlobalSection(SolutionConfigurationPlatforms) = preSolution
    8.11 +		Debug|Win32 = Debug|Win32
    8.12 +		Release|Win32 = Release|Win32
    8.13 +	EndGlobalSection
    8.14 +	GlobalSection(ProjectConfigurationPlatforms) = postSolution
    8.15 +		{E1C96598-E1AC-4928-8930-F8B6CD245B12}.Debug|Win32.ActiveCfg = Debug|Win32
    8.16 +		{E1C96598-E1AC-4928-8930-F8B6CD245B12}.Debug|Win32.Build.0 = Debug|Win32
    8.17 +		{E1C96598-E1AC-4928-8930-F8B6CD245B12}.Release|Win32.ActiveCfg = Release|Win32
    8.18 +		{E1C96598-E1AC-4928-8930-F8B6CD245B12}.Release|Win32.Build.0 = Release|Win32
    8.19 +	EndGlobalSection
    8.20 +	GlobalSection(SolutionProperties) = preSolution
    8.21 +		HideSolutionNode = FALSE
    8.22 +	EndGlobalSection
    8.23 +EndGlobal
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/gamedata md5/msvc9/gamedatamd5.vcproj	Sun Jun 29 22:23:14 2008 +0000
     9.3 @@ -0,0 +1,219 @@
     9.4 +<?xml version="1.0" encoding="UTF-8"?>
     9.5 +<VisualStudioProject
     9.6 +	ProjectType="Visual C++"
     9.7 +	Version="9.00"
     9.8 +	Name="gamedatamd5"
     9.9 +	ProjectGUID="{E1C96598-E1AC-4928-8930-F8B6CD245B12}"
    9.10 +	Keyword="Win32Proj"
    9.11 +	TargetFrameworkVersion="0"
    9.12 +	>
    9.13 +	<Platforms>
    9.14 +		<Platform
    9.15 +			Name="Win32"
    9.16 +		/>
    9.17 +	</Platforms>
    9.18 +	<ToolFiles>
    9.19 +	</ToolFiles>
    9.20 +	<Configurations>
    9.21 +		<Configuration
    9.22 +			Name="Debug|Win32"
    9.23 +			OutputDirectory="Debug"
    9.24 +			IntermediateDirectory="Debug"
    9.25 +			ConfigurationType="1"
    9.26 +			CharacterSet="2"
    9.27 +			>
    9.28 +			<Tool
    9.29 +				Name="VCPreBuildEventTool"
    9.30 +			/>
    9.31 +			<Tool
    9.32 +				Name="VCCustomBuildTool"
    9.33 +			/>
    9.34 +			<Tool
    9.35 +				Name="VCXMLDataGeneratorTool"
    9.36 +			/>
    9.37 +			<Tool
    9.38 +				Name="VCWebServiceProxyGeneratorTool"
    9.39 +			/>
    9.40 +			<Tool
    9.41 +				Name="VCMIDLTool"
    9.42 +			/>
    9.43 +			<Tool
    9.44 +				Name="VCCLCompilerTool"
    9.45 +				Optimization="0"
    9.46 +				AdditionalIncludeDirectories="../../../public;../../../public/sourcepawn"
    9.47 +				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
    9.48 +				MinimalRebuild="true"
    9.49 +				BasicRuntimeChecks="3"
    9.50 +				RuntimeLibrary="1"
    9.51 +				UsePrecompiledHeader="0"
    9.52 +				WarningLevel="3"
    9.53 +				Detect64BitPortabilityProblems="false"
    9.54 +				DebugInformationFormat="4"
    9.55 +			/>
    9.56 +			<Tool
    9.57 +				Name="VCManagedResourceCompilerTool"
    9.58 +			/>
    9.59 +			<Tool
    9.60 +				Name="VCResourceCompilerTool"
    9.61 +			/>
    9.62 +			<Tool
    9.63 +				Name="VCPreLinkEventTool"
    9.64 +			/>
    9.65 +			<Tool
    9.66 +				Name="VCLinkerTool"
    9.67 +				LinkIncremental="2"
    9.68 +				GenerateDebugInformation="true"
    9.69 +				SubSystem="1"
    9.70 +				TargetMachine="1"
    9.71 +			/>
    9.72 +			<Tool
    9.73 +				Name="VCALinkTool"
    9.74 +			/>
    9.75 +			<Tool
    9.76 +				Name="VCManifestTool"
    9.77 +			/>
    9.78 +			<Tool
    9.79 +				Name="VCXDCMakeTool"
    9.80 +			/>
    9.81 +			<Tool
    9.82 +				Name="VCBscMakeTool"
    9.83 +			/>
    9.84 +			<Tool
    9.85 +				Name="VCFxCopTool"
    9.86 +			/>
    9.87 +			<Tool
    9.88 +				Name="VCAppVerifierTool"
    9.89 +			/>
    9.90 +			<Tool
    9.91 +				Name="VCPostBuildEventTool"
    9.92 +			/>
    9.93 +		</Configuration>
    9.94 +		<Configuration
    9.95 +			Name="Release|Win32"
    9.96 +			OutputDirectory="Release"
    9.97 +			IntermediateDirectory="Release"
    9.98 +			ConfigurationType="1"
    9.99 +			>
   9.100 +			<Tool
   9.101 +				Name="VCPreBuildEventTool"
   9.102 +			/>
   9.103 +			<Tool
   9.104 +				Name="VCCustomBuildTool"
   9.105 +			/>
   9.106 +			<Tool
   9.107 +				Name="VCXMLDataGeneratorTool"
   9.108 +			/>
   9.109 +			<Tool
   9.110 +				Name="VCWebServiceProxyGeneratorTool"
   9.111 +			/>
   9.112 +			<Tool
   9.113 +				Name="VCMIDLTool"
   9.114 +			/>
   9.115 +			<Tool
   9.116 +				Name="VCCLCompilerTool"
   9.117 +				AdditionalIncludeDirectories="../../../public;../../../public/sourcepawn"
   9.118 +				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
   9.119 +				RuntimeLibrary="0"
   9.120 +				UsePrecompiledHeader="0"
   9.121 +				WarningLevel="3"
   9.122 +				Detect64BitPortabilityProblems="false"
   9.123 +				DebugInformationFormat="3"
   9.124 +			/>
   9.125 +			<Tool
   9.126 +				Name="VCManagedResourceCompilerTool"
   9.127 +			/>
   9.128 +			<Tool
   9.129 +				Name="VCResourceCompilerTool"
   9.130 +			/>
   9.131 +			<Tool
   9.132 +				Name="VCPreLinkEventTool"
   9.133 +			/>
   9.134 +			<Tool
   9.135 +				Name="VCLinkerTool"
   9.136 +				LinkIncremental="2"
   9.137 +				GenerateDebugInformation="true"
   9.138 +				SubSystem="1"
   9.139 +				OptimizeReferences="2"
   9.140 +				EnableCOMDATFolding="2"
   9.141 +				TargetMachine="1"
   9.142 +			/>
   9.143 +			<Tool
   9.144 +				Name="VCALinkTool"
   9.145 +			/>
   9.146 +			<Tool
   9.147 +				Name="VCManifestTool"
   9.148 +			/>
   9.149 +			<Tool
   9.150 +				Name="VCXDCMakeTool"
   9.151 +			/>
   9.152 +			<Tool
   9.153 +				Name="VCBscMakeTool"
   9.154 +			/>
   9.155 +			<Tool
   9.156 +				Name="VCFxCopTool"
   9.157 +			/>
   9.158 +			<Tool
   9.159 +				Name="VCAppVerifierTool"
   9.160 +			/>
   9.161 +			<Tool
   9.162 +				Name="VCPostBuildEventTool"
   9.163 +			/>
   9.164 +		</Configuration>
   9.165 +	</Configurations>
   9.166 +	<References>
   9.167 +	</References>
   9.168 +	<Files>
   9.169 +		<Filter
   9.170 +			Name="Header Files"
   9.171 +			Filter="h;hpp;hxx;hm;inl;inc;xsd"
   9.172 +			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
   9.173 +			>
   9.174 +			<File
   9.175 +				RelativePath="..\main.h"
   9.176 +				>
   9.177 +			</File>
   9.178 +			<File
   9.179 +				RelativePath="..\md5.h"
   9.180 +				>
   9.181 +			</File>
   9.182 +			<File
   9.183 +				RelativePath="..\sm_memtable.h"
   9.184 +				>
   9.185 +			</File>
   9.186 +			<File
   9.187 +				RelativePath="..\TextParsers.h"
   9.188 +				>
   9.189 +			</File>
   9.190 +		</Filter>
   9.191 +		<Filter
   9.192 +			Name="Resource Files"
   9.193 +			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
   9.194 +			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
   9.195 +			>
   9.196 +		</Filter>
   9.197 +		<Filter
   9.198 +			Name="Source Files"
   9.199 +			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
   9.200 +			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
   9.201 +			>
   9.202 +			<File
   9.203 +				RelativePath="..\main.cpp"
   9.204 +				>
   9.205 +			</File>
   9.206 +			<File
   9.207 +				RelativePath="..\md5.cpp"
   9.208 +				>
   9.209 +			</File>
   9.210 +			<File
   9.211 +				RelativePath="..\sm_memtable.cpp"
   9.212 +				>
   9.213 +			</File>
   9.214 +			<File
   9.215 +				RelativePath="..\TextParsers.cpp"
   9.216 +				>
   9.217 +			</File>
   9.218 +		</Filter>
   9.219 +	</Files>
   9.220 +	<Globals>
   9.221 +	</Globals>
   9.222 +</VisualStudioProject>
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/gamedata md5/sm_memtable.cpp	Sun Jun 29 22:23:14 2008 +0000
    10.3 @@ -0,0 +1,112 @@
    10.4 +/**
    10.5 + * vim: set ts=4 :
    10.6 + * =============================================================================
    10.7 + * SourceMod
    10.8 + * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
    10.9 + * =============================================================================
   10.10 + *
   10.11 + * This program is free software; you can redistribute it and/or modify it under
   10.12 + * the terms of the GNU General Public License, version 3.0, as published by the
   10.13 + * Free Software Foundation.
   10.14 + * 
   10.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
   10.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   10.17 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
   10.18 + * details.
   10.19 + *
   10.20 + * You should have received a copy of the GNU General Public License along with
   10.21 + * this program.  If not, see <http://www.gnu.org/licenses/>.
   10.22 + *
   10.23 + * As a special exception, AlliedModders LLC gives you permission to link the
   10.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
   10.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
   10.26 + * by the Valve Corporation.  You must obey the GNU General Public License in
   10.27 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
   10.28 + * this exception to all derivative works.  AlliedModders LLC defines further
   10.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
   10.30 + * or <http://www.sourcemod.net/license.php>.
   10.31 + *
   10.32 + * Version: $Id$
   10.33 + */
   10.34 +
   10.35 +#include <string.h>
   10.36 +#include <malloc.h>
   10.37 +#include "sm_memtable.h"
   10.38 +
   10.39 +BaseMemTable::BaseMemTable(unsigned int init_size)
   10.40 +{
   10.41 +	membase = (unsigned char *)malloc(init_size);
   10.42 +	size = init_size;
   10.43 +	tail = 0;
   10.44 +}
   10.45 +
   10.46 +BaseMemTable::~BaseMemTable()
   10.47 +{
   10.48 +	free(membase);
   10.49 +	membase = NULL;
   10.50 +}
   10.51 +
   10.52 +int BaseMemTable::CreateMem(unsigned int addsize, void **addr)
   10.53 +{
   10.54 +	int idx = (int)tail;
   10.55 +
   10.56 +	while (tail + addsize >= size)
   10.57 +	{
   10.58 +		size *= 2;
   10.59 +		membase = (unsigned char *)realloc(membase, size);
   10.60 +	}
   10.61 +
   10.62 +	tail += addsize;
   10.63 +
   10.64 +	if (addr)
   10.65 +	{
   10.66 +		*addr = (void *)&membase[idx];
   10.67 +	}
   10.68 +
   10.69 +	return idx;
   10.70 +}
   10.71 +
   10.72 +void *BaseMemTable::GetAddress(int index)
   10.73 +{
   10.74 +	if (index < 0 || (unsigned int)index >= tail)
   10.75 +	{
   10.76 +		return NULL;
   10.77 +	}
   10.78 +
   10.79 +	return &membase[index];
   10.80 +}
   10.81 +
   10.82 +void BaseMemTable::Reset()
   10.83 +{
   10.84 +	tail = 0;
   10.85 +}
   10.86 +
   10.87 +BaseStringTable::BaseStringTable(unsigned int init_size) : m_table(init_size)
   10.88 +{
   10.89 +}
   10.90 +
   10.91 +BaseStringTable::~BaseStringTable()
   10.92 +{
   10.93 +}
   10.94 +
   10.95 +int BaseStringTable::AddString(const char *string)
   10.96 +{
   10.97 +	size_t len = strlen(string) + 1;
   10.98 +	int idx;
   10.99 +	char *addr;
  10.100 +
  10.101 +	idx = m_table.CreateMem(len, (void **)&addr);
  10.102 +	strcpy(addr, string);
  10.103 +
  10.104 +	return idx;
  10.105 +}
  10.106 +
  10.107 +/*const char *BaseStringTable::GetString(int str)
  10.108 +{
  10.109 +	return (const char *)m_table.GetAddress(str);
  10.110 +}*/
  10.111 +
  10.112 +void BaseStringTable::Reset()
  10.113 +{
  10.114 +	m_table.Reset();
  10.115 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/gamedata md5/sm_memtable.h	Sun Jun 29 22:23:14 2008 +0000
    11.3 @@ -0,0 +1,114 @@
    11.4 +/**
    11.5 + * vim: set ts=4 :
    11.6 + * =============================================================================
    11.7 + * SourceMod
    11.8 + * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
    11.9 + * =============================================================================
   11.10 + *
   11.11 + * This program is free software; you can redistribute it and/or modify it under
   11.12 + * the terms of the GNU General Public License, version 3.0, as published by the
   11.13 + * Free Software Foundation.
   11.14 + * 
   11.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
   11.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   11.17 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
   11.18 + * details.
   11.19 + *
   11.20 + * You should have received a copy of the GNU General Public License along with
   11.21 + * this program.  If not, see <http://www.gnu.org/licenses/>.
   11.22 + *
   11.23 + * As a special exception, AlliedModders LLC gives you permission to link the
   11.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
   11.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
   11.26 + * by the Valve Corporation.  You must obey the GNU General Public License in
   11.27 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
   11.28 + * this exception to all derivative works.  AlliedModders LLC defines further
   11.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
   11.30 + * or <http://www.sourcemod.net/license.php>.
   11.31 + *
   11.32 + * Version: $Id$
   11.33 + */
   11.34 +
   11.35 +#ifndef _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_
   11.36 +#define _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_
   11.37 +
   11.38 +class BaseMemTable
   11.39 +{
   11.40 +public:
   11.41 +	BaseMemTable(unsigned int init_size);
   11.42 +	~BaseMemTable();
   11.43 +public:
   11.44 +	/**
   11.45 +	 * Allocates 'size' bytes of memory.
   11.46 +	 * Optionally outputs the address through 'addr'.
   11.47 +	 * Returns an index >= 0 on success, < 0 on failure.
   11.48 +	 */
   11.49 +	int CreateMem(unsigned int size, void **addr);
   11.50 +
   11.51 +	/**
   11.52 +	 * Given an index into the memory table, returns its address.
   11.53 +	 * Returns NULL if invalid.
   11.54 +	 */
   11.55 +	void *GetAddress(int index);
   11.56 +
   11.57 +	/**
   11.58 +	 * Scraps the memory table.  For caching purposes, the memory 
   11.59 +	 * is not freed, however subsequent calls to CreateMem() will 
   11.60 +	 * begin at the first index again.
   11.61 +	 */
   11.62 +	void Reset();
   11.63 +
   11.64 +	inline unsigned int GetMemUsage()
   11.65 +	{
   11.66 +		return size;
   11.67 +	}
   11.68 +
   11.69 +	inline unsigned int GetActualMemUsed()
   11.70 +	{
   11.71 +		return tail;
   11.72 +	}
   11.73 +
   11.74 +private:
   11.75 +	unsigned char *membase;
   11.76 +	unsigned int size;
   11.77 +	unsigned int tail;
   11.78 +};
   11.79 +
   11.80 +class BaseStringTable
   11.81 +{
   11.82 +public:
   11.83 +	BaseStringTable(unsigned int init_size);
   11.84 +	~BaseStringTable();
   11.85 +public:
   11.86 +	/** 
   11.87 +	 * Adds a string to the string table and returns its index.
   11.88 +	 */
   11.89 +	int AddString(const char *string);
   11.90 +
   11.91 +	/**
   11.92 +	 * Given an index into the string table, returns the associated string.
   11.93 +	 */
   11.94 +	inline const char *GetString(int str)
   11.95 +	{
   11.96 +		return (const char *)m_table.GetAddress(str);
   11.97 +	}
   11.98 +
   11.99 +	/**
  11.100 +	 * Scraps the string table.  For caching purposes, the memory
  11.101 +	 * is not freed, however subsequent calls to AddString() will 
  11.102 +	 * begin at the first index again.
  11.103 +	 */
  11.104 +	void Reset();
  11.105 +
  11.106 +	/**
  11.107 +	 * Returns the parent BaseMemTable that this string table uses.
  11.108 +	 */
  11.109 +	inline BaseMemTable *GetMemTable()
  11.110 +	{
  11.111 +		return &m_table;
  11.112 +	}
  11.113 +private:
  11.114 +	BaseMemTable m_table;
  11.115 +};
  11.116 +
  11.117 +#endif //_INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_