Initial commit of the sharedFoundation library

This commit is contained in:
Anonymous
2014-01-13 06:41:27 -07:00
parent 004d02c834
commit f1479f792b
202 changed files with 27918 additions and 0 deletions
@@ -0,0 +1,151 @@
set(SHARED_SOURCES
shared/ApplicationVersion.cpp
shared/ApplicationVersion.h
shared/ArrayList.h
shared/AutoDeltaNetworkIdPackedMap.cpp
shared/AutoDeltaNetworkIdPackedMap.h
shared/Binary.h
shared/BitArray.cpp
shared/BitArray.h
shared/Branch.cpp
shared/Branch.h
shared/CalendarTime.cpp
shared/CalendarTime.h
shared/CallbackEntryBase.h
shared/Clock.cpp
shared/Clock.h
shared/CommandLine.cpp
shared/CommandLine.h
shared/ConfigFile.cpp
shared/ConfigFile.h
shared/ConstCharCrcLowerString.cpp
shared/ConstCharCrcLowerString.h
shared/ConstCharCrcString.cpp
shared/ConstCharCrcString.h
shared/CrashReportInformation.cpp
shared/CrashReportInformation.h
shared/Crc.cpp
shared/Crc.h
shared/CrcLowerString.cpp
shared/CrcLowerString.h
shared/CrcString.cpp
shared/CrcString.h
shared/CrcStringTable.cpp
shared/CrcStringTable.h
shared/DataResource.cpp
shared/DataResource.h
shared/DataResourceList.h
shared/DebugInfoManager.cpp
shared/DebugInfoManager.h
shared/ExitChain.cpp
shared/ExitChain.h
shared/Fatal.cpp
shared/Fatal.h
shared/FirstSharedFoundation.h
shared/FloatMath.h
shared/FormattedString.h
shared/GameControllerMessage.h
shared/LabelHash.cpp
shared/LabelHash.h
shared/LessPointerComparator.h
shared/MacroFoundation.h
shared/Md5.cpp
shared/Md5.h
shared/MemoryBlockManager.cpp
shared/MemoryBlockManager.h
shared/MemoryBlockManagerMacros.h
shared/MessageQueue.cpp
shared/MessageQueueDataTemplate.cpp
shared/MessageQueueDataTemplate.h
shared/MessageQueue.h
shared/Misc.h
shared/NetworkIdArchive.cpp
shared/NetworkIdArchive.h
shared/NetworkId.cpp
shared/NetworkId.h
shared/PersistentCrcString.cpp
shared/PersistentCrcString.h
shared/PointerDeleter.h
shared/Production.h
shared/SafeCast.h
shared/Scheduler.cpp
shared/Scheduler.h
shared/StaticCallbackEntry.cpp
shared/StaticCallbackEntry.h
shared/StationId.h
shared/StlForwardDeclaration.h
shared/StringCompare.h
shared/Tag.h
shared/TemporaryCrcString.cpp
shared/TemporaryCrcString.h
shared/Timer.cpp
shared/Timer.h
shared/VoidBindSecond.h
shared/VoidMemberFunction.h
shared/Watcher.cpp
shared/Watcher.h
shared/dynamicVariable/DynamicVariable.cpp
shared/dynamicVariable/DynamicVariable.h
shared/dynamicVariable/DynamicVariableList.cpp
shared/dynamicVariable/DynamicVariableList.h
shared/dynamicVariable/DynamicVariableListNestedList.cpp
shared/dynamicVariable/DynamicVariableListNestedList.h
shared/dynamicVariable/DynamicVariableLocationData.h
)
if(WIN32)
set(PLATFORM_SOURCES
win32/ByteOrder.cpp
win32/ByteOrder.h
win32/ConfigSharedFoundation.cpp
win32/ConfigSharedFoundation.h
win32/FirstPlatform.h
win32/FloatingPointUnit.cpp
win32/FloatingPointUnit.h
win32/Os.cpp
win32/Os.h
win32/PerThreadData.cpp
win32/PerThreadData.h
win32/PlatformGlue.cpp
win32/PlatformGlue.h
win32/ProcessSpawner.cpp
win32/ProcessSpawner.h
win32/RegistryKey.cpp
win32/RegistryKey.h
win32/SetupSharedFoundation.cpp
win32/SetupSharedFoundation.h
win32/WindowsWrapper.h
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32)
else()
set(PLATFORM_SOURCES
linux/ByteOrder.h
linux/ConfigSharedFoundation.cpp
linux/ConfigSharedFoundation.h
linux/FirstPlatform.h
linux/FloatingPointUnit.cpp
linux/FloatingPointUnit.h
linux/Os.cpp
linux/Os.h
linux/PerThreadData.cpp
linux/PerThreadData.h
linux/PlatformGlue.cpp
linux/PlatformGlue.h
linux/SetupSharedFoundation.cpp
linux/SetupSharedFoundation.h
linux/vsnprintf.cpp
linux/vsnprintf.h
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/linux)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shared)
add_library(sharedFoundation
${SHARED_SOURCES}
${PLATFORM_SOURCES}
)
@@ -0,0 +1,20 @@
// ======================================================================
//
// ByteOrder.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef BYTE_ORDER_H
#define BYTE_ORDER_H
// ======================================================================
#include "sharedFoundation/FirstPlatform.h"
// ======================================================================
#endif
@@ -0,0 +1,289 @@
// ======================================================================
//
// ConfigSharedFoundation.cpp
// copyright 1998 Bootprint Entertainment
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include "sharedFoundation/ConfigFile.h"
// ======================================================================
const int c_defaultFatalCallStackDepth = 32;
const int c_defaultWarningCallStackDepth = 8;
// ======================================================================
namespace ConfigSharedFoundationNamespace
{
real ms_frameRateLimit;
real ms_minFrameRate;
bool ms_noExceptionHandling;
bool ms_fpuExceptionPrecision;
bool ms_fpuExceptionUnderflow;
bool ms_fpuExceptionOverflow;
bool ms_fpuExceptionZeroDivide;
bool ms_fpuExceptionDenormal;
bool ms_fpuExceptionInvalid;
bool ms_demoMode;
bool ms_useRemoteDebug;
int ms_defaultRemoteDebugPort;
bool ms_profilerExpandAllBranches = true;
bool ms_memoryManagerReportAllocations;
bool ms_memoryManagerReportOnOutOfMemory;
bool ms_useMemoryBlockManager;
bool ms_memoryBlockManagerDebugDumpOnRemove;
int ms_fatalCallStackDepth;
int ms_warningCallStackDepth;
bool ms_lookUpCallStackNames;
bool ms_alwaysCanSeeWorldCell;
bool ms_verboseWarnings;
float ms_debugReportLongFrameTime;
}
using namespace ConfigSharedFoundationNamespace;
// ======================================================================
#define KEY_INT(a,b) (ms_ ## a = ConfigFile::getKeyInt("SharedFoundation", #a, b))
#define KEY_BOOL(a,b) (ms_ ## a = ConfigFile::getKeyBool("SharedFoundation", #a, b))
#define KEY_FLOAT(a,b) (ms_ ## a = ConfigFile::getKeyFloat("SharedFoundation", #a, b))
// #define KEY_STRING(a,b) (ms_ ## a = ConfigFile::getKeyString("SharedFoundation", #a, b))
// ======================================================================
// Determine the Platform-specific configuration information
//
// Remarks:
//
// This routine inspects the ConfigFile class to set some variables for rapid access
// by the rest of the engine.
void ConfigSharedFoundation::install (const Defaults &defaults)
{
KEY_BOOL(noExceptionHandling, false);
KEY_BOOL(fpuExceptionPrecision, false);
KEY_BOOL(fpuExceptionUnderflow, false);
KEY_BOOL(fpuExceptionOverflow, false);
KEY_BOOL(fpuExceptionZeroDivide, false);
KEY_BOOL(fpuExceptionDenormal, false);
KEY_BOOL(fpuExceptionInvalid, false);
KEY_BOOL(demoMode, false);
KEY_FLOAT(frameRateLimit, defaults.frameRateLimit);
KEY_FLOAT(minFrameRate, 0.0f);
KEY_BOOL(useRemoteDebug, false);
KEY_INT(defaultRemoteDebugPort, 4445);
KEY_BOOL(profilerExpandAllBranches, true);
KEY_BOOL(memoryManagerReportAllocations, true);
KEY_BOOL(memoryManagerReportOnOutOfMemory, true);
KEY_BOOL(useMemoryBlockManager, true);
KEY_BOOL(memoryBlockManagerDebugDumpOnRemove, false);
KEY_INT(fatalCallStackDepth, c_defaultFatalCallStackDepth);
KEY_INT(warningCallStackDepth, c_defaultWarningCallStackDepth);
KEY_BOOL(lookUpCallStackNames, true);
KEY_BOOL(alwaysCanSeeWorldCell, false);
KEY_BOOL(verboseWarnings, false);
KEY_FLOAT(debugReportLongFrameTime, 0.25f);
}
// ======================================================================
/**
* Return the frame rate limit value for the game.
*
* @return The initial frame rate limiter value
*/
real ConfigSharedFoundation::getFrameRateLimit(void)
{
return ms_frameRateLimit;
}
// ----------------------------------------------------------------------
/**
* Return the minimum frame rate limit value for the game. Frame that take longer
* will be set to the minimum and a message will be logged.
*
* @return The minimum frame rate value
*/
real ConfigSharedFoundation::getMinFrameRate(void)
{
return ms_minFrameRate;
}
// ----------------------------------------------------------------------
/**
* Return whether to run with exception handling enabled.
*
* @return True to run without exception handling
*/
bool ConfigSharedFoundation::getNoExceptionHandling(void)
{
return ms_noExceptionHandling;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionPrecision(void)
{
return ms_fpuExceptionPrecision;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionUnderflow(void)
{
return ms_fpuExceptionUnderflow;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionOverflow(void)
{
return ms_fpuExceptionOverflow;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionZeroDivide(void)
{
return ms_fpuExceptionZeroDivide;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionDenormal(void)
{
return ms_fpuExceptionDenormal;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getFpuExceptionInvalid(void)
{
return ms_fpuExceptionInvalid;
}
// ----------------------------------------------------------------------
int ConfigSharedFoundation::getFatalCallStackDepth()
{
return ms_fatalCallStackDepth;
}
// ----------------------------------------------------------------------
int ConfigSharedFoundation::getWarningCallStackDepth()
{
return ms_warningCallStackDepth;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getProfilerExpandAllBranches()
{
return ms_profilerExpandAllBranches;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getUseRemoteDebug()
{
return ms_useRemoteDebug;
}
// ----------------------------------------------------------------------
int ConfigSharedFoundation::getDefaultRemoteDebugPort()
{
return ms_defaultRemoteDebugPort;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getDemoMode()
{
return ms_demoMode;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getAlwaysCanSeeWorldCell()
{
return ms_alwaysCanSeeWorldCell;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getLookUpCallStackNames()
{
return ms_lookUpCallStackNames;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getMemoryManagerReportAllocations()
{
return ms_memoryManagerReportAllocations;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getMemoryManagerReportOnOutOfMemory()
{
return ms_memoryManagerReportOnOutOfMemory;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getUseMemoryBlockManager()
{
return ms_useMemoryBlockManager;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getMemoryBlockManagerDebugDumpOnRemove ()
{
return ms_memoryBlockManagerDebugDumpOnRemove;
}
// ----------------------------------------------------------------------
bool ConfigSharedFoundation::getVerboseWarnings()
{
return ms_verboseWarnings;
}
// ----------------------------------------------------------------------
float ConfigSharedFoundation::getDebugReportLongFrameTime()
{
return ms_debugReportLongFrameTime;
}
// ======================================================================
@@ -0,0 +1,64 @@
// ======================================================================
//
// ConfigSharedFoundation.h
// copyright 1998 Bootprint Entertainment
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_ConfigSharedFoundation_H
#define INCLUDED_ConfigSharedFoundation_H
// ======================================================================
class ConfigSharedFoundation
{
public:
struct Defaults
{
real frameRateLimit;
};
public:
static void install (const Defaults &defaults);
static real getFrameRateLimit();
static real getMinFrameRate();
static bool getNoExceptionHandling();
static bool getFpuExceptionPrecision();
static bool getFpuExceptionUnderflow();
static bool getFpuExceptionOverflow();
static bool getFpuExceptionZeroDivide();
static bool getFpuExceptionDenormal();
static bool getFpuExceptionInvalid();
static bool getDemoMode();
static bool getUseRemoteDebug();
static int getDefaultRemoteDebugPort();
static bool getProfilerExpandAllBranches();
static bool getMemoryManagerReportAllocations();
static bool getMemoryManagerReportOnOutOfMemory();
static bool getUseMemoryBlockManager();
static bool getMemoryBlockManagerDebugDumpOnRemove();
static int getFatalCallStackDepth();
static int getWarningCallStackDepth();
static bool getLookUpCallStackNames();
static bool getAlwaysCanSeeWorldCell();
static bool getVerboseWarnings();
static float getDebugReportLongFrameTime();
};
// ======================================================================
#endif
@@ -0,0 +1,54 @@
// ======================================================================
//
// FirstPlatform.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef FIRST_PLATFORM_H
#define FIRST_PLATFORM_H
// ======================================================================
#include <cstdlib>
#define DLLEXPORT
// ======================================================================
// C4514 unreferenced inline function has been removed
// C4710 inline function not expanded
// C4291 no matching operator delete found; memory will not be freed if initialization throws an exception
#include <float.h>
#include <math.h>
#include <ctype.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdarg.h>
#include <string.h>
#include <wchar.h>
#include "sharedFoundation/PlatformGlue.h"
#include "sharedMemoryManager/MemoryManager.h"
// ======================================================================
template <class T>
inline int ComGetReferenceCount(T *t)
{
t->AddRef();
return t->Release();
}
// ======================================================================
#define FATAL_HR(a,b) FATAL(FAILED(b), (a, HRESULT_CODE(b)))
#define DEBUG_FATAL_HR(a,b) DEBUG_FATAL(FAILED(b), (a, HRESULT_CODE(b)))
// ======================================================================
#endif
@@ -0,0 +1,266 @@
// ======================================================================
//
// FloatingPointUnit.cpp
// jeff grills
//
// copyright 1999 Bootprint Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/FloatingPointUnit.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
// ======================================================================
int FloatingPointUnit::updateNumber;
WORD FloatingPointUnit::status;
FloatingPointUnit::Precision FloatingPointUnit::precision;
FloatingPointUnit::Rounding FloatingPointUnit::rounding;
bool FloatingPointUnit::exceptionEnabled[E_max];
// ======================================================================
const WORD PRECISION_MASK = BINARY4(0000,0011,0000,0000);
const WORD PRECISION_24 = BINARY4(0000,0000,0000,0000);
const WORD PRECISION_53 = BINARY4(0000,0010,0000,0000);
const WORD PRECISION_64 = BINARY4(0000,0011,0000,0000);
const WORD ROUND_MASK = BINARY4(0000,1100,0000,0000);
const WORD ROUND_NEAREST = BINARY4(0000,0000,0000,0000);
const WORD ROUND_CHOP = BINARY4(0000,1100,0000,0000);
const WORD ROUND_DOWN = BINARY4(0000,0100,0000,0000);
const WORD ROUND_UP = BINARY4(0000,1000,0000,0000);
const WORD EXCEPTION_PRECISION = BINARY4(0000,0000,0010,0000);
const WORD EXCEPTION_UNDERFLOW = BINARY4(0000,0000,0001,0000);
const WORD EXCEPTION_OVERFLOW = BINARY4(0000,0000,0000,1000);
const WORD EXCEPTION_ZERO_DIVIDE = BINARY4(0000,0000,0000,0100);
const WORD EXCEPTION_DENORMAL = BINARY4(0000,0000,0000,0010);
const WORD EXCEPTION_INVALID = BINARY4(0000,0000,0000,0001);
const WORD EXCEPTION_ALL = BINARY4(0000,0000,0011,1111);
// ======================================================================
void FloatingPointUnit::install(void)
{
precision = P_24;
rounding = R_roundToNearestOrEven;
memset(exceptionEnabled, 0, sizeof(exceptionEnabled));
// preserve all other bits
status = getControlWord();
status &= ~(PRECISION_MASK | ROUND_MASK | EXCEPTION_ALL);
// set to single precision, rounding, and all exceptions masked
status |= PRECISION_24 | ROUND_NEAREST | EXCEPTION_ALL;
// check the config platform flags to see if we should enable some exceptions
if (ConfigSharedFoundation::getFpuExceptionPrecision())
{
exceptionEnabled[E_precision] = true;
status &= ~EXCEPTION_PRECISION;
}
if (ConfigSharedFoundation::getFpuExceptionUnderflow())
{
exceptionEnabled[E_underflow] = true;
status &= ~EXCEPTION_UNDERFLOW;
}
if (ConfigSharedFoundation::getFpuExceptionOverflow())
{
exceptionEnabled[E_overflow] = true;
status &= ~EXCEPTION_OVERFLOW;
}
if (ConfigSharedFoundation::getFpuExceptionZeroDivide())
{
exceptionEnabled[E_zeroDivide] = true;
status &= ~EXCEPTION_ZERO_DIVIDE;
}
if (ConfigSharedFoundation::getFpuExceptionDenormal())
{
exceptionEnabled[E_denormal] = true;
status &= ~EXCEPTION_DENORMAL;
}
if (ConfigSharedFoundation::getFpuExceptionInvalid())
{
exceptionEnabled[E_invalid] = true;
status &= ~EXCEPTION_INVALID;
}
setControlWord(status);
}
// ----------------------------------------------------------------------
void FloatingPointUnit::update(void)
{
WORD currentStatus = getControlWord();
if (currentStatus != status)
{
DEBUG_REPORT_LOG_PRINT(true, ("FPU: update=%d, in mode=%04x, should be in mode=%04x", updateNumber, static_cast<int>(currentStatus), static_cast<int>(status)));
setControlWord(status);
}
++updateNumber;
}
// ----------------------------------------------------------------------
WORD FloatingPointUnit::getControlWord(void)
{
//TODO wtf is this asm statement?
#if 0
WORD controlWord = 0;
__asm fnstcw controlWord;
return controlWord;
#else
return status;
#endif
}
// ----------------------------------------------------------------------
void FloatingPointUnit::setControlWord(WORD controlWord)
{
//TODO see above?
UNREF(controlWord);
#if 0
__asm fldcw controlWord;
#endif
}
// ----------------------------------------------------------------------
void FloatingPointUnit::setPrecision(Precision newPrecision)
{
WORD bits = 0;
switch (precision)
{
case P_24:
bits = PRECISION_24;
break;
case P_53:
bits = PRECISION_53;
break;
case P_64:
bits = PRECISION_64;
break;
case P_max:
default:
DEBUG_FATAL(true, ("bad case"));
}
// record the current state
precision = newPrecision;
// set the proper bit pattern
status &= ~PRECISION_MASK;
status |= bits;
// slam it into the FPU
setControlWord(status);
}
// ----------------------------------------------------------------------
void FloatingPointUnit::setRounding(Rounding newRounding)
{
WORD bits = 0;
switch (newRounding)
{
case R_roundToNearestOrEven:
bits = ROUND_NEAREST;
break;
case R_chop:
bits = ROUND_CHOP;
break;
case R_roundDown:
bits = ROUND_DOWN;
break;
case R_roundUp:
bits = ROUND_UP;
break;
case R_max:
default:
DEBUG_FATAL(true, ("bad case"));
}
// record the current state
rounding = newRounding;
// set the proper bit pattern
status &= ~ROUND_MASK;
status |= bits;
// slam it into the FPU
setControlWord(status);
}
// ----------------------------------------------------------------------
void FloatingPointUnit::setExceptionEnabled(Exception exception, bool enabled)
{
WORD bits = 0;
switch (exception)
{
case E_precision:
bits = EXCEPTION_PRECISION;
break;
case E_underflow:
bits = EXCEPTION_UNDERFLOW;
break;
case E_overflow:
bits = EXCEPTION_OVERFLOW;
break;
case E_zeroDivide:
bits = EXCEPTION_ZERO_DIVIDE;
break;
case E_denormal:
bits = EXCEPTION_DENORMAL;
break;
case E_invalid:
bits = EXCEPTION_INVALID;
break;
case E_max:
default:
DEBUG_FATAL(true, ("bad case"));
}
// record the current state
exceptionEnabled[exception] = enabled;
// twiddle the bit appropriately. these bits masks, so set the bit to disable the exception, clear the bit to enable it.
if (enabled)
status &= ~bits;
else
status |= bits;
// slam it into the FPU
setControlWord(status);
}
// ======================================================================
@@ -0,0 +1,102 @@
// ======================================================================
//
// FloatingPointUnit.h
// jeff grills
//
// copyright 1999 Bootprint Entertainment
//
// ======================================================================
#ifndef FLOATING_POINT_UNIT_H
#define FLOATING_POINT_UNIT_H
// ======================================================================
class FloatingPointUnit
{
public:
enum Precision
{
P_24,
P_53,
P_64,
P_max
};
enum Rounding
{
R_roundToNearestOrEven,
R_chop,
R_roundDown,
R_roundUp,
R_max
};
enum Exception
{
E_precision,
E_underflow,
E_overflow,
E_zeroDivide,
E_denormal,
E_invalid,
E_max
};
private:
static int updateNumber;
static WORD status;
static Precision precision;
static Rounding rounding;
static bool exceptionEnabled[E_max];
public:
static WORD getControlWord(void);
static void setControlWord(WORD controlWord);
public:
static void install(void);
static void update(void);
static void setPrecision(Precision newPrecision);
static void setRounding(Rounding newRounding);
static void setExceptionEnabled(Exception exception, bool enabled);
static Precision getPrecision(void);
static Rounding getRounding(void);
static bool getExceptionEnabled(Exception exception);
};
// ======================================================================
inline FloatingPointUnit::Precision FloatingPointUnit::getPrecision(void)
{
return precision;
}
// ----------------------------------------------------------------------
inline FloatingPointUnit::Rounding FloatingPointUnit::getRounding(void)
{
return rounding;
}
// ----------------------------------------------------------------------
inline bool FloatingPointUnit::getExceptionEnabled(Exception exception)
{
DEBUG_FATAL(static_cast<int>(exception) < 0 || static_cast<int>(exception) >= static_cast<int>(E_max), ("exception out of range")); //lint !e568 // non-negative quantity is never less than 0
return exceptionEnabled[exception];
}
// ======================================================================
#endif
@@ -0,0 +1,468 @@
// ======================================================================
//
// Os.cpp
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/Clock.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include "sharedDebug/DebugMonitor.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/FloatingPointUnit.h"
#include "sharedIoWin/IoWinManager.h"
#include <stack>
#include <string>
// ======================================================================
bool Os::installed;
bool Os::runInBackground;
int Os::numberOfUpdates;
int Os::menuValue;
bool Os::paused;
bool Os::wasPaused;
bool Os::gameOver;
bool Os::shouldReturnFromAbort;
char Os::programName[PROGRAM_NAME_SIZE];
char *Os::shortProgramName;
pthread_t Os::mainThreadId;
bool Os::threadDied;
bool Os::isMp;
int Os::processorCount;
// ----------------------------------------------------------------------
namespace OsNamespace
{
class UncatchableException
{
};
}
// ----------------------------------------------------------------------
/**
* Install the Os subsystem for non-games.
*
* This routine is supported for all platforms, although different platforms may
* require different arguments to this routine.
*
* This routine will add Os::remove to the ExitChain.
*
* @see Os::remove()
*/
void Os::install(void)
{
installCommon();
}
// ----------------------------------------------------------------------
/**
* This routine will remove the Os subsystem.
*
* This routine should not be called directly. It will be called from the ExitChain.
*
* @see Os::install()
*/
void Os::remove(void)
{
DEBUG_FATAL(!installed, ("not installed"));
installed = false;
}
// ----------------------------------------------------------------------
void Os::installCommon(void)
{
DEBUG_FATAL(installed, ("already installed"));
ExitChain::add(Os::remove, "Os::remove", 0, true);
#if 0 //TODO For now we won't screw with the priority of the process
HANDLE threadHandle = GetCurrentThread();
DEBUG_FATAL(!SetThreadPriority(threadHandle, THREAD_PRIORITY_ABOVE_NORMAL), ("Failed to set game thread priority"));
#endif
numberOfUpdates = 0;
mainThreadId = pthread_self();
// get the name of the executable
//Can't find UNIX call for this: DWORD result = GetModuleFileName(NULL, programName, sizeof(programName));
strcpy(programName, "TempName");
DWORD result = 1;
FATAL(result == 0, ("GetModuleFileName failed"));
// get the file name without the path
shortProgramName = strrchr(programName, '\\');
if (shortProgramName)
++shortProgramName;
else
shortProgramName = programName;
// determine the number of processors by parsing /proc/cpuinfo
processorCount = 1;
FILE * f = fopen("/proc/cpuinfo", "r");
if (f)
{
char buffer[512];
while (!feof(f))
{
fgets(buffer, 512, f);
if (strncmp(buffer, "processor\t: ", 12)==0)
{
processorCount = atoi(buffer+12)+1;
}
}
fclose(f);
}
isMp = processorCount > 1;
// switch into single-precision floating point mode
FloatingPointUnit::install();
installed = true;
}
// ----------------------------------------------------------------------
bool Os::isMainThread(void)
{
// if the Os class hasn't been installed, then assume we are the main thread.
// otherwise, check to see if our thread id is the main thread id
return !installed || (pthread_self() == mainThreadId);
}
// ----------------------------------------------------------------------
/**
* Terminate the application because of an error condition.
*
* This routine is supported for all platforms.
*
* This routine should not be called directly. The engine and game should use the
* FATAL macro to terminate the application because of an error.
*
* Calling Os::returnFromAbort() will cause the routine to do nothing but return
* immediately.
*
* @see Os::returnFromAbort(), FATAL()
*/
#include <signal.h>
void Os::abort(void)
{
if (!isMainThread())
{
threadDied = true;
pthread_exit(NULL);
}
if (!shouldReturnFromAbort)
{
// let the C runtime deal with the abnormal termination
int * dummy = NULL;
int forceCrash = *dummy;
UNREF(forceCrash);
for (;;)
{
// One of these should work:
pthread_kill(pthread_self(), SIGSEGV);
::kill(0,SIGSEGV);
::abort();
OsNamespace::UncatchableException ex;
throw ex;
sleep(10);
}
}
}
//-----------------------------------------------------------------
/**
* Create the specified directory and all of it's parents.
* @param directory the path to a directory
* @return always true currently
*/
bool Os::createDirectories (const char *directory)
{
//-- construct list of subdirectories all the way down to root
std::stack<std::string> directoryStack;
std::string currentDirectory = directory;
static const char path_seps [] = { '\\', '/', 0 };
// build the stack
while (!currentDirectory.empty())
{
// remove trailing backslash
if (currentDirectory[currentDirectory.size()-1] == '\\' || currentDirectory[currentDirectory.size()-1] == '/')
IGNORE_RETURN(currentDirectory.erase(currentDirectory.size()-1));
if (currentDirectory[currentDirectory.size()-1] == ':')
{
// we've hit something like c:
break;
}
if (!currentDirectory.empty())
directoryStack.push(currentDirectory);
// now strip off current directory
size_t previousDirIndex = currentDirectory.find_last_of (path_seps);
if (previousDirIndex == currentDirectory.npos)
break;
else
IGNORE_RETURN(currentDirectory.erase(previousDirIndex));
}
//-- build all directories specified by the initial directory
while (!directoryStack.empty())
{
// get the directory
currentDirectory = directoryStack.top();
directoryStack.pop();
// try to create it (don't pass any security attributes)
IGNORE_RETURN (mkdir (currentDirectory.c_str(), 0));
}
return true;
}
// ----------------------------------------------------------------------
/**
* Write out a file.
*
* The file name and where the file is written is system-dependent.
*
* @param fileName Name of the file to write
* @param data Data buffer to write to the file
*/
bool Os::writeFile(const char *fileName, const void *data, int length) // Length of the data bufferto write
{
BOOL result;
HANDLE handle;
DWORD written;
// open the file for writing
handle = CreateFile(fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// check if it was opened
if (handle == INVALID_HANDLE_VALUE)
return false;
// attempt to write the data
result = WriteFile(handle, data, static_cast<DWORD>(length), &written, NULL);
// make sure the data was written okay
if (!result || written != static_cast<DWORD>(length))
{
static_cast<void>(CloseHandle(handle));
return false;
}
// close the file
result = CloseHandle(handle);
// make sure the close was sucessful
if (!result)
return false;
return true;
}
// ----------------------------------------------------------------------
/**
* Update the Os subsystem.
*
* This routine is supported for all platforms.
*
* For the Win* platforms, this routine will process the windows message pump.
*/
bool Os::update(void)
{
static int ppid = getppid();
FloatingPointUnit::update();
++numberOfUpdates;
#if 0
#ifdef _DEBUG
if (DEBUG_FLAG_PLATFORM(validateHeap))
{
PROFILER_START("validate heap");
MemoryManager::validate();
PROFILER_STOP("validate heap");
}
#endif
#endif
Clock::update();
wasPaused = false;
// if our parent's pid has changed, we tell our caller it should exit
if (getppid() != ppid)
{
WARNING(true, ("Parent process exited!"));
// reset the parent process id, so we don't keep spamming warnings for processes that don't exit because of this
ppid = getppid();
return false;
}
return true;
}
// ----------------------------------------------------------------------
/**
* Formats a message error using GetLastError() and FormatMessge().
*
* The buffer returned from this function is dynamically allocated to prevent
* issues with this routine being called from multiple threads. The caller
* must delete the buffer when it is done.
*
* @return A dynamically allocated buffer containing the error message
*/
char *Os::getLastError(void)
{
return DuplicateString(strerror(errno));
}
// ----------------------------------------------------------------------
bool Os::getAbsolutePath(const char *relativePath, char *absolutePath, int absolutePathBufferSize)
{
// realpath sucks and could cause a buffer overrun. however, it's better than writing it ourselves for now.
char *result = realpath(relativePath, absolutePath);
if (!result)
return false;
FATAL(istrlen(absolutePath)+1 > absolutePathBufferSize, ("buffer overrun"));
return true;
}
// ----------------------------------------------------------------------
/**
* Get the actual system time, in seconds since the epoch.
*
* Do not use this for most game systems, since it does not take into account
* clock sku, game loop times, etc.
*/
time_t Os::getRealSystemTime(void)
{
return time(0);
}
// ----------------------------------------------------------------------
/**
* Convert a time in seconds since the epoch to GMT.
*
*/
void Os::convertTimeToGMT(const time_t &time, tm &zulu)
{
zulu=*gmtime(&time); // gmtime uses a single static tm structure. Yuck!
}
// ----------------------------------------------------------------------
/**
* Convert a tm structure to the time in seconds since the epoch.
*
*/
time_t Os::convertGMTToTime(const tm &zulu)
{
return mktime(const_cast<tm*>(&zulu));
}
// ----------------------------------------------------------------------
/**
* Get a unique identifier for this thread.
*
* @return A unique identifier for this thread.
*/
Os::ThreadId Os::getThreadId()
{
return pthread_self();
}
// ----------------------------------------------------------------------
/**
* Assign the given thread a reasonable name (only works for MSDev 6.0 debugger)
* Since this is Linux-specific, make sure this fuction does nothing
*
*/
void Os::setThreadName(DWORD threadID, const char* threadName)
{
}
// ----------------------------------------------------------------------
/**
* Cause the current thread to sleep for a period of time. If the period is
* zero, the current thread yields it's timeslice.
*/
void Os::sleep(int ms)
{
if (ms == 0)
{
sched_yield();
}
else
{
usleep(ms * 1000);
}
}
// ----------------------------------------------------------------------
/**
* Copy text to the system clipboard.
*
* This routine can be used if the application wants to make some data easily available for pasting (like crash call stacks).
*/
bool Os::copyTextToClipboard(const char *text)
{
UNREF(text);
return false;
}
// ----------------------------------------------------------------------
Os::OsPID_t Os::getProcessId()
{
return getpid();
}
// ----------------------------------------------------------------------
void Os::setProgramName(const char * name)
{
strncpy(programName, name, Os::PROGRAM_NAME_SIZE);
}
// ----------------------------------------------------------------------
bool Os::isFocused()
{
return true;
}
// ----------------------------------------------------------------------
@@ -0,0 +1,264 @@
// ======================================================================
//
// Os.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef OS_H
#define OS_H
#include <pthread.h>
// ======================================================================
struct DebugMenuEntry;
// ======================================================================
class Os
{
public:
typedef pthread_t ThreadId;
typedef pid_t OsPID_t;
enum
{
MAX_PATH_LENGTH = 512
};
typedef void (*QueueCharacterHookFunction)(int keyboard, int character);
typedef void (*SetSystemMouseCursorPositionHookFunction)(int x, int y);
typedef void (*QueueKeyDownHookFunction)(int keyboard, int character);
private:
Os(void);
Os(const Os &);
Os &operator =(const Os &);
enum
{
PROGRAM_NAME_SIZE = 512
};
private:
static void remove(void);
static void installCommon(void);
private:
static bool installed;
static bool runInBackground;
static int numberOfUpdates;
static int menuValue;
static DebugMenuEntry *debugMenuGame;
static bool paused;
static bool wasPaused;
static bool gameOver;
static bool shouldReturnFromAbort;
static bool wantPopupDebugMenu;
static char programName[PROGRAM_NAME_SIZE];
static char *shortProgramName;
static pthread_t mainThreadId;
static bool threadDied;
static bool isMp;
static int processorCount;
public:
static void install(void);
static bool isGameOver(void);
static bool isMainThread(void);
static bool wasApplicationPaused(void);
static bool update(void);
static void returnFromAbort(void);
static void abort(void);
static void requestPopupDebugMenu();
static bool createDirectories (const char *dirname);
static bool writeFile(const char *fileName, const void *data, int length);
static int getNumberOfUpdates(void);
static char *getLastError(void);
static void setThreadName(DWORD threadID, const char* name);
static ThreadId getThreadId();
static const char *getProgramName(void);
static const char *getShortProgramName(void);
static void setProgramName(const char * name);
static bool getAbsolutePath(const char *relativePath, char *absolutePath, int absolutePathBufferSize);
static void sleep(int ms);
static time_t getRealSystemTime(void);
static void convertTimeToGMT(const time_t &time, tm &zulu);
static time_t convertGMTToTime(const tm &zulu);
static bool isMultiprocessor();
static int getProcessorCount();
static bool copyTextToClipboard(const char *text);
static bool wasFocusLost();
static void setQueueCharacterHookFunction(QueueCharacterHookFunction queueCharacterHookFunction);
static void setSetSystemMouseCursorPositionHookFunction(SetSystemMouseCursorPositionHookFunction setSystemMouseCursorPositionHookFunction);
static OsPID_t getProcessId();
static bool isFocused();
static void setQueueKeyDownHookFunction(QueueKeyDownHookFunction queueKeyDownHookFunction);
};
// ----------------------------------------------------------------------
/**
* Return the full name of the running executable.
*
* The program name will include the path as well.
*
* @return The full name of the running executable
* @see Os::getShortProgramName()
*/
inline const char *Os::getProgramName(void)
{
return programName;
}
// ----------------------------------------------------------------------
/**
* Return the short name of the running executable.
*
* The program name will not include the path, but will just be the file name.
*
* @return The short name of the running executable
* @see Os::getProgramName()
*/
inline const char *Os::getShortProgramName(void)
{
return shortProgramName;
}
// ----------------------------------------------------------------------
/**
* Cause Os::abort() to return instead of abort the process.
*
* This routine should not be called directly by users.
*
* This routine is provided so that structured exception handling can catch
* an exception, call Fatal to run the ExitChain, and rethrow the exception
* so that the debugger will catch it.
*/
inline void Os::returnFromAbort(void)
{
shouldReturnFromAbort = true;
}
// ----------------------------------------------------------------------
/**
* Check if the Os knows the game needs to shut down.
*
* The Os can decide that the game need to end for a number of reasons,
* including closing the application or shutting the machine down.
*
* @return True if the game should quit, otherwise false
*/
inline bool Os::isGameOver(void)
{
return gameOver;
}
// ----------------------------------------------------------------------
/**
* Return the number of updates that the have occurred.
*
* @return This value is updated during the Os::update() routine.
*/
inline int Os::getNumberOfUpdates(void)
{
return numberOfUpdates;
}
// ----------------------------------------------------------------------
/**
* Indicate whether or not the application was paused.
*
* @return True if the application was in the background (paused), otherwise false
*/
inline bool Os::wasApplicationPaused(void)
{
return wasPaused;
}
// ----------------------------------------------------------------------
/**
* Return a flag indicating whether we are running a multiprocessor machine or not.
*
* @return True if the machine has more than one processor, false if not.
*/
inline bool Os::isMultiprocessor(void)
{
return isMp;
}
// ----------------------------------------------------------------------
/**
* Return the number of processors.
*
* @return The number of processors in the machine.
*/
inline int Os::getProcessorCount(void)
{
return processorCount;
}
// ----------------------------------------------------------------------
inline bool Os::wasFocusLost()
{
return false;
}
// ----------------------------------------------------------------------
inline void Os::setQueueCharacterHookFunction(QueueCharacterHookFunction queueCharacterHookFunction)
{
}
// ----------------------------------------------------------------------
inline void Os::setSetSystemMouseCursorPositionHookFunction(SetSystemMouseCursorPositionHookFunction setSystemMouseCursorPositionHookFunction)
{
}
// ----------------------------------------------------------------------
inline void Os::setQueueKeyDownHookFunction(QueueKeyDownHookFunction)
{
}
// ----------------------------------------------------------------------
#endif
@@ -0,0 +1,161 @@
// ======================================================================
//
// PerThreadData.cpp
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/PerThreadData.h"
#include "sharedSynchronization/Gate.h"
// ======================================================================
pthread_key_t PerThreadData::slot;
bool PerThreadData::slotCreated=false;
// ======================================================================
// Install the per-thread-data subsystem
//
// Remarks:
//
// This routine will install the per-thread-data subsystem that is required for several
// other subsystems in the engine. It should be called from the primary thread before
// any other threads have been created. It will also call threadInstall() for the
// primary thread.
//
// See Also:
//
// PerThreadData::remove()
void PerThreadData::install(void)
{
if (pthread_key_create(&slot, 0)!=0)
{
FATAL(true, ("pthread_key_create failed"));
}
slotCreated=true;
threadInstall();
}
// ----------------------------------------------------------------------
/**
* Remove the per-thread-subsystem.
*
* This routine should be called by the primary thread after all other threads have
* terminated, and no other uses of per-thread-data will occur.
*
* @see PerThreadData::install()
*/
void PerThreadData::remove(void)
{
threadRemove();
if (pthread_key_delete(slot)!=0)
{
FATAL(true, ("pthread_key_delete failed"));
}
slotCreated=false;
}
// ----------------------------------------------------------------------
/**
* Get access to the per-thread-data.
*
* This routine will verify the per-thread-data subsystem has been installed and the
* threadInstall() function has been called for the current thread.
*
* @return A pointer to the per-thread-data.
*/
PerThreadData::Data *PerThreadData::getData(bool allowReturnNull)
{
UNREF(allowReturnNull);
if (!slotCreated)
{
DEBUG_FATAL(true && !allowReturnNull, ("not installed"));
return NULL;
}
Data * const data = reinterpret_cast<Data *>(pthread_getspecific(slot));
DEBUG_FATAL(!data && !allowReturnNull, ("not installed for this thread"));
return data;
}
// ----------------------------------------------------------------------
/**
* Create the per-thread-data for a new thread.
*
* This routine should be called in a thread before the first usage of per-thread-data.
*
* If the client is calling this function on a thread that existed before the engine was
* installed, the client should set isNewThread to false. Setting isNewThread to false
* prevents the function from validating that the thread's TLS is NULL. For threads existing
* before the engine is installed, the TLS data for the thread is undefined.
*
* @param isNewThread [IN] true if the thread was created after the engine was installed, false otherwise
* @see PerThreadData::threadRemove()
*/
void PerThreadData::threadInstall(bool isNewThread)
{
UNREF(isNewThread);
DEBUG_FATAL(!slotCreated, ("not installed"));
// only check for already-set data if this is supposed to be a new thread
DEBUG_FATAL(isNewThread && pthread_getspecific(slot), ("already installed for this thread"));
// create the data
Data * const data = new Data;
// initialize the data
memset(data, 0, sizeof(*data));
//create the event for file streaming reads
data->readGate = new Gate(false);
// set the data into the thread slot
const BOOL result = pthread_setspecific(slot, data);
UNREF(result);
DEBUG_FATAL(result, ("pthread_setspecific failed")); //NB: unlike Windows, returns 0 on success.
} //lint !e429 // Warning -- Custodial pointer 'data' has not been freed or returned) // stored int thread-local-storage
// ----------------------------------------------------------------------
/**
* Destroythe per-thread-data for a terminating thread.
*
* This routine should be called in a thread after the last usage of per-thread-data.
*
* @see PerThreadData::threadInstall()
*/
void PerThreadData::threadRemove(void)
{
DEBUG_FATAL(!slotCreated, ("not installed"));
DEBUG_FATAL(!pthread_getspecific(slot), ("thread not installed"));
// get the data
Data *data = getData();
//close the event used for file streaming reads
delete data->readGate;
data->readGate = NULL;
// wipe the data in the thread slot
const BOOL result2 = pthread_setspecific(slot, NULL);
UNREF(result2);
DEBUG_FATAL(result2, ("TlsSetValue failed")); //NB: unlike Windows, returns 0 on success.
// free the memory
delete data;
}
// ======================================================================
@@ -0,0 +1,232 @@
// ======================================================================
//
// PerThreadData.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef PER_THREAD_DATA_H
#define PER_THREAD_DATA_H
// ======================================================================
#include "sharedFoundation/ExitChain.h"
class Gate;
// ======================================================================
/**
* Provide thread local storage functionality.
*
* This class' purpose is to allow each thread to maintain some storage that is local and private to each thread.
* The system must be installed before use. Each thread that may use per-thread-data will also need to call the
* threadInstall() routine after creation and threadRemove() just before termination of the thread.
*/
class PerThreadData
{
private:
struct Data
{
bool exitChainRunning;
bool exitChainFataling;
ExitChain::Entry *exitChainFirstEntry;
int debugPrintFlags;
Gate *readGate;
};
static pthread_key_t slot;
static bool slotCreated;
private:
static Data *getData(bool allowReturnNull=false);
private:
PerThreadData(void);
PerThreadData(const PerThreadData &);
PerThreadData &operator =(const PerThreadData &);
public:
static void install(void);
static void remove(void);
static void threadInstall(bool isNewThread = true);
static void threadRemove(void);
static bool isThreadInstalled(void);
static bool getExitChainRunning(void);
static void setExitChainRunning(bool newValue);
static bool getExitChainFataling(void);
static void setExitChainFataling(bool newValue);
static ExitChain::Entry *getExitChainFirstEntry(void);
static void setExitChainFirstEntry(ExitChain::Entry *newValue);
static int getDebugPrintFlags(void);
static void setDebugPrintFlags(int newValue);
static Gate *getFileStreamerReadGate(void);
};
// ======================================================================
/**
* Determine if the per-thread-data is available for this thread
*
* Return value:
*
* True if the per-thread-data is installed correctly, false otherwise
*
* Remarks:
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
*
* -TRF- looks like Win98 does not zero out a new TLS slot for
* threads existing at the time of slot creation. Thus, if you build a
* plugin that only initializes the engine the first time it is
* used, and other threads already exist in the app, those threads
* will contain bogus non-null data in the TLS slot. If the plugin really
* wants to do lazy initialization of the engine, it will need
* to handle calling PerThreadData::threadInstall() for all existing threads
* (except the thread that initialized the engine, which already
* has its PerThreadData::threadInstall() called).
*/
inline bool PerThreadData::isThreadInstalled(void)
{
return (getData(true) != NULL);
}
// ----------------------------------------------------------------------
/**
* Get the exit chain running flag value.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
*
* @return True if the exit chain is running, false otherwise.
* @see ExitChain::isRunning()
*/
inline bool PerThreadData::getExitChainRunning(void)
{
return getData()->exitChainRunning;
}
// ----------------------------------------------------------------------
/**
* Set the exit chain running flag value.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
*
* @param newValue New value for the exit chain running flag
*/
inline void PerThreadData::setExitChainRunning(bool newValue)
{
getData()->exitChainRunning = newValue;
}
// ----------------------------------------------------------------------
/**
* Get the exit chain fataling flag value.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
*
* @return True if the exit chain is fataling, false otherwise.
* @see ExitChain::isFataling()
*/
inline bool PerThreadData::getExitChainFataling(void)
{
return getData()->exitChainFataling;
}
// ----------------------------------------------------------------------
/**
* Set the exit chain fataling flag value.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
*
* @param newValue New value for the exit chain fataling flag
*/
inline void PerThreadData::setExitChainFataling(bool newValue)
{
getData()->exitChainFataling = newValue;
}
// ----------------------------------------------------------------------
/**
* Get the first entry for the exit chain.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
* This routine may return NULL.
*
* @return Pointer to the first entry on the exit chain
* @see ExitChain::isFataling()
*/
inline ExitChain::Entry *PerThreadData::getExitChainFirstEntry(void)
{
return getData()->exitChainFirstEntry;
}
// ----------------------------------------------------------------------
/**
* Set the exit chain fataling flag value.
*
* This routine is not intended for general use; it should only be used by the ExitChain class.
* The parameter to this routine may be NULL.
*
* @param newValue New value for the exit chain first entry
*/
inline void PerThreadData::setExitChainFirstEntry(ExitChain::Entry *newValue)
{
getData()->exitChainFirstEntry = newValue;
}
// ----------------------------------------------------------------------
/**
* Get the debug print flags.
*
* This routine is not intended for general use; it should only be used by the DebugPrint functions.
*
* @return Current value of the debug print flags
*/
inline int PerThreadData::getDebugPrintFlags(void)
{
return getData()->debugPrintFlags;
}
// ----------------------------------------------------------------------
/**
* Set the debug print flags value.
*
* This routine is not intended for general use; it should only be used by the DebugPrint functions.
*/
inline void PerThreadData::setDebugPrintFlags(int newValue)
{
getData()->debugPrintFlags = newValue;
}
// ----------------------------------------------------------------------
inline Gate *PerThreadData::getFileStreamerReadGate(void)
{
return getData()->readGate;
}
// ======================================================================
#endif
@@ -0,0 +1,273 @@
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/PlatformGlue.h"
#include <ctime>
real abs(real x)
{
return fabs(x);
}
int _stricmp(const char* string1, const char* string2)
{
int first, second;
do
{
first = toupper(*string1);
second = toupper(*string2);
string1++;
string2++;
} while (first && first==second);
return (first - second);
}
char* _itoa(int value, char* stringOut, int radix)
{
DEBUG_FATAL((radix != 10), ("itoa only supprts base 10"));
sprintf(stringOut, "%d", value);
return stringOut;
}
bool QueryPerformanceCounter(__int64* time)
{
struct timeval tv;
gettimeofday(&tv, NULL);
*time = static_cast<LARGE_INTEGER>(tv.tv_sec);
*time = (*time * 1000000) + static_cast<LARGE_INTEGER>(tv.tv_usec);
return TRUE;
}
bool QueryPerformanceFrequency(__int64 *freq)
{
*freq = CLOCKS_PER_SEC;
return TRUE;
}
void Sleep(DWORD msecs)
{
//Sleep takes a time to sleep in milliseconds.
usleep(msecs*1000); //usleep works with microseconds
}
int GetLastError()
{
return errno;
}
void OutputDebugString(const char* stringOut)
{
fprintf(stderr,"%s",stringOut);
}
//File Support
BOOL WriteFile(FILE* hFile, const void* lpBuffer, DWORD numBytesToWrite, DWORD* numBytesWritten, void* unsup)
{
int retval;
if(unsup)
return FALSE; //Windows doesn't support this overrlap buffer
retval = fwrite(lpBuffer, sizeof(char), numBytesToWrite, hFile);
*numBytesWritten = retval;
return (retval < 0) ? FALSE : TRUE;
}
BOOL ReadFile(FILE* hFile, void* lpBuffer, DWORD numBytesToRead, DWORD* numBytesRead, void* unsup)
{
int retval;
if(unsup)
return FALSE; //Windows doesn't support this overrlap buffer
retval = fread(lpBuffer, sizeof(char), numBytesToRead, hFile);
*numBytesRead = retval;
return (retval <= 0) ? FALSE : TRUE;
}
DWORD SetFilePointer(FILE* hFile, long lDistanceToMove, long* lpDistanceToMoveHigh, DWORD dwMoveMethod)
{
//Mimics the Win32 function to set the position of a file pointer. return -1 on failure else current position.
int retval;
retval = fseek(hFile, lDistanceToMove, dwMoveMethod);
return (retval == 0) ? ftell(hFile) : -1;
}
//TODO Consider using a call to open() instead of fopen() to get a better mapping of parameters to Win32
FILE* CreateFile(const char* fileName, DWORD access, DWORD shareMode, void* unsupA, DWORD creationDisposition, DWORD flagsAndAttributes, FILE* unsupB)
{
FILE* retval = 0;
DEBUG_FATAL(flagsAndAttributes != FILE_ATTRIBUTE_NORMAL, ("Unsupported File mode call to CreateFile()"));
DEBUG_FATAL(unsupB != NULL, ("Unsupported File mode call to CreateFile()"));
//DEBUG_FATAL(shareMode != 0, ("Unsupported File mode call to CreateFile()"));
DEBUG_FATAL(unsupA != 0, ("Unsupported File mode call to CreateFile()"));
switch(creationDisposition)
{
case CREATE_NEW:
retval = fopen(fileName, "r");
if (retval)
{
fclose(retval);
retval = NULL;
}
else
{
fclose(retval);
retval = fopen(fileName, "w");
}
break;
case CREATE_ALWAYS:
retval = fopen(fileName, "w");
break;
case OPEN_EXISTING:
retval = fopen(fileName, "r");
if ((access & GENERIC_WRITE) && retval)
{
fclose(retval);
retval = fopen(fileName, "a");
rewind(retval);
}
break;
case OPEN_ALWAYS:
if (access & GENERIC_WRITE)
{
retval = fopen(fileName, "a");
rewind(retval);
}
else
{
retval = fopen(fileName, "r");
}
break;
case TRUNCATE_EXISTING:
DEBUG_FATAL(!(access & GENERIC_WRITE),("Must open truncate file with write access"));
retval = fopen(fileName, "w");
break;
}
return retval;
}
BOOL CloseHandle(FILE* hFile)
{
int retval = fclose(hFile);
return (retval == 0) ? TRUE : FALSE;
}
//TODO There must be a more elegant UNIX command to get file size...fstat() needs filename
DWORD GetFileSize(FILE* hFile, DWORD* lpHighSize)
{
long int curPos;
DWORD endPos;
curPos = ftell(hFile);
fseek(hFile, 0, SEEK_END);
endPos = ftell(hFile);
fseek(hFile, curPos, SEEK_SET);
return endPos;
#if 0
//This is what I want to do, but I have no file des number
struct stat buf;
fstat(hFile, &buf);
return buf->st_size;
#endif
}
BOOL FileExists(const char* filename)
{
BOOL retval = false;
struct stat info;
if (stat(filename, &info) == 0)
{
if (S_ISREG(info.st_mode))
retval = true;
}
return retval;
}
//Memory Functions
void* VirtualAlloc(void* location, DWORD size, DWORD flAllocationType, DWORD flProtect)
{
if (location)
return location;
return malloc(size);
}
BOOL VirtualFree(void* location, DWORD size, DWORD freeType)
{
free(location);
return TRUE;
}
BOOL VirtualProtect(void* location, DWORD size, DWORD newProtect, DWORD* oldProect)
{
//Unused. Function stub for compatibility
return TRUE;
}
BOOL IsBadReadPtr(const void* location, unsigned int size)
{
//unused
return TRUE;
}
void MessageBox (void* unused, const char* message, const char* unused2, int flags)
{
OutputDebugString(message);
}
char *ConvertCommandLine(int argc, char ** argv)
{
static char buffer[2048];
int totalSize=0;
for (int i=0; i<argc; ++i)
{
totalSize+=strlen(argv[i])+1;
}
if(totalSize>1023)
{
int argIndex = 0;
fprintf(stderr, "Exceeded command line args length of %d. Total size is %d\n", sizeof(buffer), totalSize);
for(argIndex = 0; argIndex < argc; ++argIndex)
{
fprintf(stderr, "argv[%d]=\"%s\"\n", argIndex, argv[argIndex]);
}
FATAL(true,("Command line exceeds maximum length."));
}
buffer[0]='\0';
for (int i=0; i<argc; ++i)
{
strcat(buffer,argv[i]);
if (i!=argc-1)
{
strcat(buffer," ");
}
}
return buffer;
}
@@ -0,0 +1,125 @@
#ifndef INCLUDED_MISC_H
#define INCLUDED_MISC_H
#include <netinet/in.h>
#include <sys/time.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
typedef unsigned short int WORD;
typedef unsigned long int DWORD;
typedef bool BOOL;
typedef long long __int64; //lint !e13 !e19 // Error: 13 (Bad type), Error: 19 (Useless declaration) // -TRF- Lint preprocessor discrepency, @todo look into this.
typedef __int64 LARGE_INTEGER;
const BOOL FALSE = 0;
const BOOL TRUE = 1;
float abs(float x);
int _stricmp(const char* string1, const char* string2);
//String to numeric conversions
char* _itoa(int value, char* stringOut, int radix);
//Format specifier for non-portable printf
#define UINT64_FORMAT_SPECIFIER "%llu"
#define INT64_FORMAT_SPECIFIER "%lli"
//Constant definition macro for 64 bit values
#define UINT64_LITERAL(a) a ## ull
#define INT64_LITERAL(a) a ## ll
bool QueryPerformanceCounter(__int64 *time);
bool QueryPerformanceFrequency(__int64 *freq);
void Sleep(DWORD msecs);
int GetLastError();
void OutputDebugString(const char* stringOut);
//File Support
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
typedef FILE* HANDLE;
#define INVALID_HANDLE_VALUE NULL //Have to use a #define because this may be a FILE*
const int GENERIC_READ = 1 << 0;
const int GENERIC_WRITE = 1 << 1;
const int CREATE_NEW = 1;
const int CREATE_ALWAYS = 2;
const int OPEN_EXISTING = 3;
const int OPEN_ALWAYS = 4;
const int TRUNCATE_EXISTING = 5;
const DWORD FILE_ATTRIBUTE_NORMAL = 1;
const int FILE_CURRENT = SEEK_CUR;
const int FILE_BEGIN = SEEK_SET;
const int FILE_END = SEEK_END;
const int FILE_SHARE_READ = 1;
BOOL WriteFile(FILE* hFile, const void* lpBuffer, DWORD numBytesToWrite, DWORD* numBytesWritten, void* unsup=NULL);
BOOL ReadFile(FILE* hFile, void* lpBuffer, DWORD numBytesToWrite, DWORD* numBytesRead, void* unsup=NULL);
DWORD SetFilePointer(FILE* hFile, long lDistanceToMove, long* lpDistanceToMoveHigh, DWORD dwMoveMethod);
FILE* CreateFile(const char* fileName, DWORD access, DWORD shareMode, void* unsupA, DWORD creationDisposition, DWORD flagsAndAttributes, FILE* unsup2);
BOOL CloseHandle(FILE* hFile);
DWORD GetFileSize(FILE* hFile, DWORD* lpHighSize);
BOOL FileExists(const char* fileName);
//Memory Support
const int MEM_RESERVE = 0;
const int MEM_COMMIT = 1;
const int PAGE_READWRITE = 0;
const int MEM_RELEASE = 0;
const int PAGE_NOACCESS = 0;
void* VirtualAlloc(void* location, DWORD size, DWORD flAllocationType, DWORD flProtect);
BOOL VirtualFree(void* location, DWORD size, DWORD freeType);
BOOL VirtualProtect(void* location, DWORD size, DWORD newProtect, DWORD* oldProect);
BOOL IsBadReadPtr(const void* location, unsigned int size);
//Misc output stuff
const int MB_OK = 0;
const int MB_ICONEXCLAMATION = 1;
void MessageBox (void* unused, const char* message, const char* unused2, int flags);
char *ConvertCommandLine(int argc, char ** argv);
//String functions
#define _vsnprintf vsnprintf
//-----------------------------------------------------------------
inline int _strnicmp (const char * a, const char * b, size_t count)
{
return ::strncasecmp (a, b, count);
}
//-----------------------------------------------------------------
inline int _open(const char *filename, int oflag) { return open(filename, oflag); }
inline int _open(const char *filename, int oflag, mode_t pmode) { return open(filename, oflag, pmode); }
inline int _creat(const char *filename, mode_t pmode) { return creat(filename, pmode); }
inline int _close(int fd) { return close(fd); }
inline int _write(int fd, const void *buffer, unsigned int count) { return write(fd, buffer, count); }
inline int _dup(int fd) { return dup(fd); }
inline int _dup2(int oldfd, int newfd) { return dup2(oldfd, newfd); }
inline long _lseek(int fd, long offset, int origin) { return lseek(fd, offset, origin); }
inline int _read(int fd, void *buffer, unsigned int count) { return read(fd, buffer, count); }
inline long _tell(int fd) { return _lseek(fd,0,SEEK_CUR); }
inline int _umask(int pmode) { return umask(pmode); }
inline int _unlink(const char *pathname) { return unlink(pathname); }
//-----------------------------------------------------------------
#endif //INCLUDED_MISC_H
@@ -0,0 +1,185 @@
// ======================================================================
//
// SetupSharedFoundation.cpp
// copyright 1998 Bootprint Entertainment
// copyright 2001 - 2002 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/SetupSharedFoundation.h"
#include "sharedDebug/ConfigSharedDebugLinux.h"
#include "sharedDebug/DebugMonitor.h"
#include "sharedDebug/Profiler.h"
#include "sharedFoundation/Clock.h"
#include "sharedFoundation/CommandLine.h"
#include "sharedFoundation/ConfigFile.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/PerThreadData.h"
#include "sharedFoundation/StaticCallbackEntry.h"
#include <ctime>
#include <math.h>
// ======================================================================
/**
* Install the engine.
*
* The settings in the Data structure will determine which subsystems
* get initialized.
*/
void SetupSharedFoundation::install(const Data &data)
{
// and get the command line stuff in quick so we can make decisions based on the command line settings
CommandLine::install();
ConfigFile::install();
if (data.lpCmdLine)
CommandLine::absorbString(data.lpCmdLine);
if (data.argc)
CommandLine::absorbStrings(const_cast<const char**>(data.argv+1), data.argc-1);
#if 0
//currently there's a problem that we cannot override the defaults here.
if (data.configFile)
IGNORE_RETURN(ConfigFile::loadFile(data.configFile));
#endif
// get the post command-line text for the ConfigFile (key-value pairs)
const char *configString = CommandLine::getPostCommandLineString();
if (configString)
ConfigFile::loadFromCommandLine(configString);
//@todo there is a lot of stuff in win32 setup not here...like exitchain
Profiler::registerDebugFlags();
#if _DEBUG
MemoryManager::registerDebugFlags();
#endif//_DEBUG
// Setup Linux DebugMonitor support.
// @todo fix this dependency: DebugMonitor really should be moved into Foundation the way things currently are. TRF is following the existing win32 setup.
#ifdef _DEBUG
ConfigSharedDebugLinux::install();
DebugMonitor::install();
#endif
// setup the engine configuration
ConfigSharedFoundation::Defaults defaults;
defaults.frameRateLimit = data.frameRateLimit;
ConfigSharedFoundation::install(defaults);
SetWarningStrictFatal(ConfigFile::getKeyBool("SharedDebug", "strict", false));
Report::install();
Clock::install(data.runInBackground, false);
PersistentCrcString::install();
CrcLowerString::install();
StaticCallbackEntry::install();
}
// ----------------------------------------------------------------------
// Call a function with appropriate exception handling (not)
//
// Remarks:
//
// this is stubbed and exception handling is ignored currently
void SetupSharedFoundation::callbackWithExceptionHandling(
void (*callback)(void) // Routine to call with exception handling
)
{
if (ConfigSharedFoundation::getNoExceptionHandling())
{
callback();
}
else
{
#if 0
try
{
callback();
}
catch (__exception * mathException)
{
FATAL(true, ("Math Exception: %s\n", mathException->name));
}
catch (const char* message)
{
FATAL(true, ("Character Exception: %s\n", message));
}
catch(std::exception & m)
{
const char * c = m.what();
FATAL(true, ("Std::exception: %s\n", c));
}
catch(...)
{
FATAL(true, ("Unknown exception\n"));
}
#else
callback();
#endif
}
}
// ----------------------------------------------------------------------
/**
* Uninstall the engine.
*
* This routine will properly uninstall the engine componenets that were
* installed by SetupSharedFoundation::install().
*/
void SetupSharedFoundation::remove(void)
{
ExitChain::quit();
if (GetNumberOfWarnings())
REPORT(true, Report::RF_print | Report::RF_log | Report::RF_dialog, ("%d warnings logged", GetNumberOfWarnings()));
// this routine can't be on the exit chain because the exit chain depends upon the PerThreadData class being around
//PerThreadData::remove();
}
// ----------------------------------------------------------------------
SetupSharedFoundation::Data::Data(Defaults defaults)
{
Zero(*this);
switch (defaults)
{
case D_game:
runInBackground = true;
lpCmdLine = NULL;
argc = 0;
argv = NULL;
configFile = NULL;
frameRateLimit = CONST_REAL(0);
break;
case D_console:
runInBackground = true;
lpCmdLine = NULL;
argc = 0;
argv = NULL;
configFile = NULL;
frameRateLimit = CONST_REAL(0);
break;
default:
DEBUG_FATAL(true, ("unknown case"));
}
}
// ======================================================================
@@ -0,0 +1,58 @@
// ======================================================================
//
// SetupSharedFoundation.h
// copyright 1998 Bootprint Entertainment
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_SetupSharedFoundation_H
#define INCLUDED_SetupSharedFoundation_H
// ======================================================================
struct DebugMenuEntry;
// ======================================================================
class SetupSharedFoundation
{
public:
struct Data
{
// allow running in background
bool runInBackground;
// pointer to command line
char* lpCmdLine;
int argc;
char **argv;
const char *configFile;
real frameRateLimit;
public:
enum Defaults
{
D_game,
D_console
};
Data(Defaults defaults);
};
public:
static void install(const Data &data);
static void remove(void);
static void callbackWithExceptionHandling(void (*callback)(void));
};
// ======================================================================
#endif
@@ -0,0 +1,35 @@
// ======================================================================
//
// vsnprintf.cpp
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/vsnprintf.h"
#include <cstdio>
// ======================================================================
// Format a printf-style string into a text buffer of fixed size
//
// Return value:
//
// The number of characters written into the buffer, or -1 if the buffer was too small
//
// Remarks:
//
// If the buffer would overflow, the null terminating character is not written and -1
// will be returned.
#ifdef _MSC_VER
int vsnprintf(char *buffer, size_t count, const char *format, va_list va)
{
return _vsnprintf(buffer, count, format, va);
}
#endif
// ======================================================================
@@ -0,0 +1,24 @@
// ======================================================================
//
// vsnprintf.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef VSNPRINTF_H
#define VSNPRINTF_H
// ======================================================================
#ifdef _MSC_VER
int vsnprintf(char *buffer, size_t count, const char *format, va_list va);
#endif
// ======================================================================
#endif
@@ -0,0 +1,75 @@
// ======================================================================
//
// ApplicationVersion.cpp
// Copyright 2002-2004, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/ApplicationVersion.h"
// ======================================================================
namespace ApplicationVersionNamespace
{
// WARNING do not change this string without making sure that the hardcoded offsets below are correct
char ms_version[] = "ApplicationVersionMarker 000 123456789012345678901234567890";
int const brandOffset = 25;
int const bootlegOffset = 26;
int const publishOffset = 27;
int const versionOffset = 29;
bool isBranded();
}
using namespace ApplicationVersionNamespace;
// ======================================================================
bool ApplicationVersionNamespace::isBranded()
{
return ms_version[brandOffset] == '1';
}
// ----------------------------------------------------------------------
bool ApplicationVersion::isBootlegBuild()
{
return ms_version[bootlegOffset] == '1';
}
// ----------------------------------------------------------------------
bool ApplicationVersion::isPublishBuild()
{
return ms_version[publishOffset] == '1';
}
// ----------------------------------------------------------------------
const char * ApplicationVersion::getPublicVersion()
{
if (!isBranded())
return "0";
char const * internal = ms_version + versionOffset;
while (*internal != '\0' && *internal != '.')
++internal;
if (*internal == '\0' || internal[1] == '\0')
return "0";
return internal + 1;
}
// ----------------------------------------------------------------------
char const * ApplicationVersion::getInternalVersion()
{
if (!isBranded())
return "unknown.0";
return ms_version + versionOffset;
}
// ======================================================================
@@ -0,0 +1,25 @@
// ======================================================================
//
// ApplicationVersion.h
// Copyright 2002-2004, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_ApplicationVersion_H
#define INCLUDED_ApplicationVersion_H
// ======================================================================
class ApplicationVersion
{
public:
static bool isBootlegBuild();
static bool isPublishBuild();
static char const * getPublicVersion();
static char const * getInternalVersion();
};
// ======================================================================
#endif
@@ -0,0 +1,552 @@
//===================================================================
//
// ArrayList.h
// asommers 10-2-98
//
// copyright 1998, bootprint entertainment
// copyright 2001, sony online entertainment
//
// generic list template
//
// @todo replace instances of ArrayList with std::vector
//
//===================================================================
#ifndef INCLUDED_ArrayList_H
#define INCLUDED_ArrayList_H
//===================================================================
template <class T>
class ArrayList
{
public:
// construction/destruction
explicit ArrayList (int newSize=0);
ArrayList (const ArrayList<T>& rhs);
~ArrayList (void);
// allow preallocation of list
void preallocate (int newSize, bool numberOfElementsToo=false);
void preallocateAndSet (int newSize, const T& newValue);
// destroy the list if it was created statically
void destroy (void);
// clear out the list
void clear (void);
// add a new item to the list
void add (const T& newElement);
void addIfNotExist (const T& newElement);
void allocateNext (void);
int findOrAdd (const T& newElement);
void insert (int index, const T& newElement);
// remove an item from the list
void remove (const T& element, bool mustExist=false);
void removeIndexAndCompactList (int index);
// delete the last item from the list
// NOTE: caller should know how to delete the element if necessary
void deleteLast (void);
// returns true if element is already in the list
bool existsInList (const T& element) const;
bool existsInList (const T& element, int& index) const;
// returns the number of elements in the list
int getNumberOfElements (void) const;
// returns the index'th item in the list (DOES NOT check for out of bounds)
T& getElement (int index);
const T& getElement (int index) const;
T& getLastElement (void);
const T& getLastElement (void) const;
// returns the index'th item in the list (DOES NOT check for out of bounds)
T& operator[] (int index);
const T& operator[] (int index) const;
//
ArrayList<T>& operator= (const ArrayList<T>& rhs);
// swapping
void swap (int index1, int index2);
// stl interface to make transition easier
const T& back () const;
T& back ();
int size () const;
bool empty () const;
void push_back (const T& element);
void pop_back ();
private:
enum
{
DEFAULT_SIZE = 16 // initial list m_size
};
private:
// resizes the list
void resizeUp (void);
void copy (const ArrayList<T>& rhs);
private:
int m_size; // list m_size
T* m_data; // list m_data
int m_numberOfElements; // number of items in the list
};
//===================================================================
template <class T>
inline ArrayList<T>::ArrayList (int newSize) :
m_size (newSize),
m_data (0),
m_numberOfElements (0)
{
if (newSize)
m_data = new T [m_size];
}
//-------------------------------------------------------------------
template <class T>
inline ArrayList<T>::ArrayList (const ArrayList<T>& rhs) :
m_size (0),
m_data (0),
m_numberOfElements (0)
{
copy (rhs);
}
//-------------------------------------------------------------------
template <class T>
inline ArrayList<T>& ArrayList<T>::operator= (const ArrayList<T>& rhs)
{
if (this != &rhs)
copy (rhs);
return *this;
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::copy (const ArrayList<T>& rhs)
{
// only delete and re-new the list if we don't have enough elements to hold the contents of rhs
if (m_numberOfElements < rhs.m_numberOfElements)
{
if (m_data)
delete [] m_data;
m_size = rhs.m_size;
m_data = new T [m_size];
}
// only copy the vital elements
memcpy (m_data, rhs.m_data, sizeof (T) * rhs.m_numberOfElements);
m_numberOfElements = rhs.m_numberOfElements;
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::destroy (void)
{
delete [] m_data;
m_data = 0;
m_size = 0;
m_numberOfElements = 0;
}
//-------------------------------------------------------------------
template <class T>
inline ArrayList<T>::~ArrayList (void)
{
destroy ();
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::preallocate (int newSize, bool numberOfElementsToo)
{
// if the m_size we want to preallocate is greater than our current m_size, grow to fit
if (newSize > m_size)
{
delete [] m_data;
m_data = new T [newSize];
m_size = newSize;
}
if (numberOfElementsToo)
m_numberOfElements = newSize;
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::preallocateAndSet (int newSize, const T& newValue)
{
preallocate (newSize, true);
int i;
for (i = 0; i < newSize; i++)
m_data [i] = newValue;
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::clear (void)
{
m_numberOfElements = 0;
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::add (const T& newElement)
{
// is the list full? if so, resize it
if (m_numberOfElements == m_size)
resizeUp ();
// add the m_data to the list
NOT_NULL (m_data);
m_data [m_numberOfElements++] = newElement;
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::addIfNotExist (const T& newElement)
{
if (existsInList (newElement))
return;
add (newElement);
}
//-------------------------------------------------------------------
template <class T>
inline int ArrayList<T>::findOrAdd (const T& newElement)
{
if (existsInList (newElement, index))
return index;
add (newElement);
return getNumberOfElements () - 1;
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::insert (int index, const T& newElement)
{
NOT_NULL (m_data);
//-- if inserting at end, just add it
if (index == m_numberOfElements)
add (newElement);
else
{
//-- is the list full? if so, resize it
if (m_numberOfElements == m_size)
resizeUp ();
//-- move everything from index to end of list down
int i;
for (i = m_numberOfElements - 1; i >= index; --i)
m_data [i + 1] = m_data [i];
//-- insert item into list
m_data [index] = newElement;
m_numberOfElements++;
}
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::allocateNext (void)
{
// is the list full? if so, resize it
if (m_numberOfElements == m_size)
resizeUp ();
m_numberOfElements++;
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::remove (const T& element, bool mustExist)
{
NOT_NULL (m_data);
// search the list for the element
int i;
for (i = 0; i < m_numberOfElements; i++)
{
// if we found it
if (m_data [i] == element)
{
// squish list
int j;
for (j = i; j < m_numberOfElements-1; j++)
m_data [j] = m_data [j+1];
m_numberOfElements--;
return;
}
}
UNREF (mustExist);
DEBUG_FATAL (mustExist, ("ArrayList<T>::remove - not found in list"));
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::removeIndexAndCompactList (int index)
{
NOT_NULL (m_data);
DEBUG_FATAL (index < 0 || index >= m_numberOfElements, ("index %d out of range", index));
// squish list
int j;
for (j = index; j < m_numberOfElements-1; j++)
m_data [j] = m_data [j+1];
m_numberOfElements--;
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::deleteLast (void)
{
if (m_numberOfElements > 0)
m_numberOfElements--;
}
//-------------------------------------------------------------------
template <class T>
inline bool ArrayList<T>::existsInList (const T& element) const
{
if (m_numberOfElements > 0)
{
NOT_NULL (m_data);
int i;
for (i = 0; i < m_numberOfElements; i++)
if (m_data [i] == element)
return true;
}
return false;
}
//-------------------------------------------------------------------
template <class T>
inline bool ArrayList<T>::existsInList (const T& element, int& index) const
{
if (m_numberOfElements > 0)
{
NOT_NULL (m_data);
int i;
for (i = 0; i < m_numberOfElements; i++)
if (m_data [i] == element)
{
index = i;
return true;
}
}
return false;
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::resizeUp (void)
{
// allocate new memory for the list (just double it)
int newSize = m_size ? m_size * 2 : DEFAULT_SIZE;
T* newData = new T [newSize];
// copy the contents of the old list into the new list
if (m_data)
memcpy (newData, m_data, sizeof (T) * m_size);
// increase the m_size
m_size = newSize;
// zap the old list
delete [] m_data;
// point to the new list
m_data = newData;
}
//-------------------------------------------------------------------
template <class T>
inline int ArrayList<T>::getNumberOfElements (void) const
{
return m_numberOfElements;
}
//-------------------------------------------------------------------
template <class T>
inline const T& ArrayList<T>::getElement (int index) const
{
NOT_NULL (m_data);
DEBUG_FATAL (index < 0 || index >= m_numberOfElements, ("index %d out of range", index));
return m_data [index];
}
//-------------------------------------------------------------------
template <class T>
inline const T& ArrayList<T>::getLastElement (void) const
{
NOT_NULL (m_data);
DEBUG_FATAL (m_numberOfElements == 0, ("ArrayList<T>::getLastElement - list has no elements"));
return m_data [m_numberOfElements - 1];
}
//-------------------------------------------------------------------
template <class T>
inline const T& ArrayList<T>::operator[] (int index) const
{
NOT_NULL (m_data);
DEBUG_FATAL (index < 0 || index >= m_numberOfElements, ("index %d out of range", index));
return m_data [index];
}
//-------------------------------------------------------------------
template <class T>
inline T& ArrayList<T>::getElement (int index)
{
NOT_NULL (m_data);
DEBUG_FATAL (index < 0 || index >= m_numberOfElements, ("index %d out of range", index));
return m_data [index];
}
//-------------------------------------------------------------------
template <class T>
inline T& ArrayList<T>::getLastElement (void)
{
NOT_NULL (m_data);
DEBUG_FATAL (m_numberOfElements == 0, ("ArrayList<T>::getLastElement - list has no elements"));
return m_data [m_numberOfElements - 1];
}
//-------------------------------------------------------------------
template <class T>
inline T& ArrayList<T>::operator[] (int index)
{
NOT_NULL (m_data);
DEBUG_FATAL (index < 0 || index >= m_numberOfElements, ("index %d out of range", index));
return m_data [index];
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::swap (int index1, int index2)
{
NOT_NULL (m_data);
DEBUG_FATAL (index1 < 0 || index1 >= m_numberOfElements || index2 < 0 || index2 >= m_numberOfElements, ("ArrayList<T>::swap - index1 %d or index2 %d out of range", index1, index2));
T tmp = m_data [index1];
m_data [index1] = m_data [index2];
m_data [index2] = tmp;
}
//-------------------------------------------------------------------
template <class T>
inline const T& ArrayList<T>::back () const
{
return getLastElement ();
}
//-------------------------------------------------------------------
template <class T>
inline T& ArrayList<T>::back ()
{
return getLastElement ();
}
//-------------------------------------------------------------------
template <class T>
inline int ArrayList<T>::size () const
{
return getNumberOfElements ();
}
//-------------------------------------------------------------------
template <class T>
inline bool ArrayList<T>::empty () const
{
return getNumberOfElements () == 0;
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::push_back (const T& element)
{
add (element);
}
//-------------------------------------------------------------------
template <class T>
inline void ArrayList<T>::pop_back ()
{
deleteLast ();
}
//===================================================================
#endif
@@ -0,0 +1,33 @@
// ======================================================================
//
// AutoDeltaNetworkIdPackedMap.cpp
// copyright (c) 2004 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/AutoDeltaNetworkIdPackedMap.h"
#include <stdio.h>
// ======================================================================
namespace Archive
{
/*
int countCharacter(const std::string &str, char c)
{
int result=0;
for (std::string::const_iterator i=str.begin(); i!=str.end(); ++i)
{
if (*i==c)
++result;
}
return result;
}
*/
} //namespace
// ======================================================================
@@ -0,0 +1,100 @@
// ======================================================================
//
// AutoDeltaNetworkIdPackedMap.h
// copyright (c) 2004 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_AutoDeltaNetworkIdPackedMap_H
#define INCLUDED_AutoDeltaNetworkIdPackedMap_H
// ======================================================================
#include "Archive/AutoDeltaMap.h"
#include <stdio.h>
#include "sharedFoundation/NetworkId.h"
#include "sharedFoundation/NetworkIdArchive.h"
#include "Archive/AutoDeltaPackedMap.h"
// ======================================================================
namespace Archive
{
/**
* An AutoDeltaNetworkIdPackedMap is an AutoDeltaMap that will be packed into
* a single value for storage. It functions as an AutoDeltaMap in
* all respects except that packDeltas() will send the entire map
* on the network.
*/
void AutoDeltaPackedMap<NetworkId, int>::pack(ByteStream & target, const std::string & buffer)
{
char temp[200];
AutoDeltaMap<NetworkId, int>::Command c;
Archive::put(target, countCharacter(buffer,':'));
Archive::put(target, static_cast<size_t>(0)); // baselineCommandCount
int tempPos = 0;
for (std::string::const_iterator i=buffer.begin(); i!=buffer.end(); ++i)
{
if (*i==':')
{
temp[tempPos]='\0';
sscanf(temp, "%d", &c.value);
Archive::put(target, static_cast<unsigned char>(AutoDeltaMap<NetworkId, int>::Command::ADD));
Archive::put(target, c.key);
Archive::put(target, c.value);
tempPos=0;
}
else if (*i == ' ')
{
temp[tempPos] = '\0';
c.key = NetworkId(temp);
tempPos = 0;
}
else
temp[tempPos++]=*i;
}
}
void AutoDeltaPackedMap<NetworkId, int>::unpack(ReadIterator & source, std::string & buffer)
{
char temp[200];
AutoDeltaMap<NetworkId, int>::Command c;
size_t commandCount;
size_t baselineCommandCount;
Archive::get(source, commandCount);
Archive::get(source, baselineCommandCount);
if (commandCount==0)
{
buffer=' '; // An empty map is represented as a single space, because a completely empty string is used to mean "no change"
}
else
{
for (size_t i = 0; i < commandCount; ++i)
{
Archive::get(source, c.cmd);
Archive::get(source, c.key);
Archive::get(source, c.value);
#ifdef WIN32
_snprintf(temp, sizeof(temp)-1, "%s %d:", c.key.getValueString().c_str(), c.value);
#else
snprintf(temp, sizeof(temp)-1, "%s %d:", c.key.getValueString().c_str(), c.value);
#endif
temp[sizeof(temp)-1]='\0';
buffer+=temp;
}
}
}
} //namespace
// ======================================================================
#endif
@@ -0,0 +1,72 @@
// ======================================================================
//
// Binary.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef BINARY_H
#define BINARY_H
// ======================================================================
//lint -save -e1923 // could become const variable
#define HEX_DIGIT_0000 0
#define HEX_DIGIT_0001 1
#define HEX_DIGIT_0010 2
#define HEX_DIGIT_0011 3
#define HEX_DIGIT_0100 4
#define HEX_DIGIT_0101 5
#define HEX_DIGIT_0110 6
#define HEX_DIGIT_0111 7
#define HEX_DIGIT_1000 8
#define HEX_DIGIT_1001 9
#define HEX_DIGIT_1010 a
#define HEX_DIGIT_1011 b
#define HEX_DIGIT_1100 c
#define HEX_DIGIT_1101 d
#define HEX_DIGIT_1110 e
#define HEX_DIGIT_1111 f
//line -restore
#define HEX_DIGIT(a) HEX_DIGIT_ ## a
#define BINARY1H(a) (0x ## a)
#define BINARY1I(a) BINARY1H(a)
#define BINARY1(a) BINARY1I(HEX_DIGIT(a))
#define BINARY2H(a,b) (0x ## a ## b)
#define BINARY2I(a,b) BINARY2H(a,b)
#define BINARY2(a,b) BINARY2I(HEX_DIGIT(a), HEX_DIGIT(b))
#define BINARY3H(a,b,c) (0x ## a ## b ## c)
#define BINARY3I(a,b,c) BINARY3H(a,b,c)
#define BINARY3(a,b,c) BINARY3I(HEX_DIGIT(a), HEX_DIGIT(b), HEX_DIGIT(c))
#define BINARY4H(a,b,c,d) (0x ## a ## b ## c ## d)
#define BINARY4I(a,b,c,d) BINARY4H(a,b,c,d)
#define BINARY4(a,b,c,d) BINARY4I(HEX_DIGIT(a), HEX_DIGIT(b), HEX_DIGIT(c), HEX_DIGIT(d))
#define BINARY5H(a,b,c,d,e) (0x ## a ## b ## c ## d ## e)
#define BINARY5I(a,b,c,d,e) BINARY5H(a,b,c,d,e)
#define BINARY5(a,b,c,d,e) BINARY5I(HEX_DIGIT(a), HEX_DIGIT(b), HEX_DIGIT(c), HEX_DIGIT(d), HEX_DIGIT(e))
#define BINARY6H(a,b,c,d,e,f) (0x ## a ## b ## c ## d ## e ## f)
#define BINARY6I(a,b,c,d,e,f) BINARY6H(a,b,c,d,e,f)
#define BINARY6(a,b,c,d,e,f) BINARY6I(HEX_DIGIT(a), HEX_DIGIT(b), HEX_DIGIT(c), HEX_DIGIT(d), HEX_DIGIT(e), HEX_DIGIT(f))
#define BINARY7H(a,b,c,d,e,f,g) (0x ## a ## b ## c ## d ## e ## f ## g)
#define BINARY7I(a,b,c,d,e,f,g) BINARY7H(a,b,c,d,e,f,g)
#define BINARY7(a,b,c,d,e,f,g) BINARY7I(HEX_DIGIT(a), HEX_DIGIT(b), HEX_DIGIT(c), HEX_DIGIT(d), HEX_DIGIT(e), HEX_DIGIT(f), HEX_DIGIT(g))
#define BINARY8H(a,b,c,d,e,f,g,h) (0x ## a ## b ## c ## d ## e ## f ## g ## h)
#define BINARY8I(a,b,c,d,e,f,g,h) BINARY8H(a,b,c,d,e,f,g,h)
#define BINARY8(a,b,c,d,e,f,g,h) BINARY8I(HEX_DIGIT(a), HEX_DIGIT(b), HEX_DIGIT(c), HEX_DIGIT(d), HEX_DIGIT(e), HEX_DIGIT(f), HEX_DIGIT(g), HEX_DIGIT(h))
// ======================================================================
#endif
@@ -0,0 +1,621 @@
// ======================================================================
//
// BitArray.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/BitArray.h"
#include "Archive/Archive.h"
#include "sharedFoundation/FormattedString.h"
// ======================================================================
BitArray::BitArray() :
m_arrayData(m_defaultData),
m_numAllocatedBytes(sizeof(m_defaultData)),
m_numInUseBytes(0),
m_numInUseBits(0)
{
memset(m_arrayData, 0, m_numAllocatedBytes);
}
// -----------------------------------------------------------------------
BitArray::BitArray(int numBits) :
m_arrayData(m_defaultData),
m_numAllocatedBytes(sizeof(m_defaultData)),
m_numInUseBytes(0),
m_numInUseBits(0)
{
if (numBits > (m_numAllocatedBytes << 3))
{
m_arrayData = NULL;
m_numAllocatedBytes = 0;
reserve(numBits);
m_numInUseBytes = 0;
m_numInUseBits = 0;
}
else
{
memset(m_arrayData, 0, m_numAllocatedBytes);
}
}
// -----------------------------------------------------------------------
BitArray::BitArray(const BitArray &orig) :
m_arrayData(m_defaultData),
m_numAllocatedBytes(sizeof(m_defaultData)),
m_numInUseBytes(0),
m_numInUseBits(0)
{
if (orig.m_numInUseBytes > m_numAllocatedBytes)
{
m_arrayData = new signed char[static_cast<size_t>(orig.m_numInUseBytes)];
m_numAllocatedBytes = orig.m_numInUseBytes;
}
m_numInUseBytes = orig.m_numInUseBytes;
m_numInUseBits = orig.m_numInUseBits;
if (m_numInUseBytes > 0)
{
memcpy(m_arrayData, orig.m_arrayData, m_numInUseBytes);
if (m_numAllocatedBytes > m_numInUseBytes)
memset(&(m_arrayData[m_numInUseBytes]), 0, static_cast<size_t>(m_numAllocatedBytes - m_numInUseBytes));
}
else
{
memset(m_arrayData, 0, m_numAllocatedBytes);
}
}
// -----------------------------------------------------------------------
BitArray::~BitArray()
{
if (m_arrayData != m_defaultData)
delete []m_arrayData;
}
// -----------------------------------------------------------------------
BitArray & BitArray::operator= (const BitArray &rhs)
{
if (this != &rhs)
{
// trivial case, rhs is empty
if ((rhs.m_numInUseBits <= 0) || (rhs.m_numInUseBytes <= 0))
{
clear();
return *this;
}
// char array is too small, reallocate new char array
if (m_numAllocatedBytes < rhs.m_numInUseBytes)
{
if (m_arrayData != m_defaultData)
delete []m_arrayData;
m_arrayData = new signed char[static_cast<size_t>(rhs.m_numInUseBytes)];
m_numAllocatedBytes = rhs.m_numInUseBytes;
}
// char array is large enough, no reallocation required,
// but clear out char array, if necessary
else if (m_numInUseBytes > rhs.m_numInUseBytes)
{
memset(&(m_arrayData[rhs.m_numInUseBytes]), 0, static_cast<size_t>(m_numInUseBytes - rhs.m_numInUseBytes));
}
m_numInUseBytes = rhs.m_numInUseBytes;
m_numInUseBits = rhs.m_numInUseBits;
memcpy(m_arrayData, rhs.m_arrayData, static_cast<size_t>(m_numInUseBytes));
}
return *this;
}
// -----------------------------------------------------------------------
bool BitArray::operator== (const BitArray &rhs) const
{
//-- Check for self equality
if (this == &rhs)
return true;
// compare the individual chars in the 2 array up to the number
// of chars needed to hold the smaller of the 2 m_numInUseBits
int const smallerArraySize = std::min(m_numInUseBytes, rhs.m_numInUseBytes);
for (int i = 0; i < smallerArraySize; ++i)
if (m_arrayData[i] != rhs.m_arrayData[i])
return false;
// if there are any additional set bits (i.e. non-zero char)
// in the larger of the 2 arrays, then equality is false
if (m_numInUseBytes != rhs.m_numInUseBytes)
{
signed char const * largerArrayData;
int largerArraySize;
if (m_numInUseBytes > rhs.m_numInUseBytes)
{
largerArraySize = m_numInUseBytes;
largerArrayData = m_arrayData;
}
else
{
largerArraySize = rhs.m_numInUseBytes;
largerArrayData = rhs.m_arrayData;
}
for (int j = smallerArraySize; j < largerArraySize; ++j)
if (largerArrayData[j])
return false;
}
return true;
}
// -----------------------------------------------------------------------
bool BitArray::operator!=(const BitArray &rhs) const
{
return !operator==(rhs);
}
// -----------------------------------------------------------------------
void BitArray::setBit(int const index)
{
DEBUG_FATAL(index < 0, ("BitArray::setBit index [%d] out of range", index));
if (index >= 0)
{
if (index >= m_numInUseBits)
reserve(index+1);
int const arrayPos = index >> 3; //lint !e702 shift right of signed quantity (DEBUG_FATALs if index < 0)
int const bitPos = index & 7;
m_arrayData[arrayPos] |= (1 << bitPos);
}
}
// -----------------------------------------------------------------------
void BitArray::setValue(int const beginIndex, int const endIndex, unsigned long value)
{
DEBUG_FATAL(beginIndex < 0, ("BitArray::setValue beginIndex [%d] out of range", beginIndex));
DEBUG_FATAL(endIndex < 0, ("BitArray::setValue endIndex [%d] out of range", endIndex));
DEBUG_FATAL(beginIndex > endIndex, ("BitArray::setValue beginIndex [%d] > endIndex [%d]", beginIndex, endIndex));
if ((beginIndex >= 0) && (endIndex >= 0) && (beginIndex <= endIndex))
{
int currentIndex = beginIndex;
while (currentIndex <= endIndex)
{
if (value == 0)
break;
if (value & 0x1)
setBit(currentIndex++);
else
clearBit(currentIndex++);
value >>= 1;
}
for (int i = currentIndex; i <= endIndex; ++i)
clearBit(i);
}
}
// -----------------------------------------------------------------------
void BitArray::clearBit(int const index)
{
DEBUG_FATAL(index < 0, ("BitArray::clearBit index [%d] out of range", index));
if ((index >= 0) && (index < m_numInUseBits))
{
int const arrayPos = index >> 3; //lint !e702 shift right of signed quantity (DEBUG_FATALs if index < 0)
int const bitPos = index & 7;
m_arrayData[static_cast<size_t>(arrayPos)] &= ~(1 << bitPos);
}
}
// -----------------------------------------------------------------------
bool BitArray::testBit(int const index) const
{
DEBUG_FATAL(index < 0, ("BitArray::testBit index [%d] out of range", index));
if ((index < 0) || (index >= m_numInUseBits))
return false;
int const arrayPos = index >> 3; //lint !e702 shift right of signed quantity (DEBUG_FATALs if index < 0)
int const bitPos = index & 7;
return ((m_arrayData[arrayPos] & (1 << bitPos)) != 0);
}
// -----------------------------------------------------------------------
unsigned long BitArray::getValue(int const beginIndex, int const endIndex) const
{
DEBUG_FATAL(beginIndex < 0, ("BitArray::setValue beginIndex [%d] out of range", beginIndex));
DEBUG_FATAL(endIndex < 0, ("BitArray::setValue endIndex [%d] out of range", endIndex));
DEBUG_FATAL(beginIndex > endIndex, ("BitArray::setValue beginIndex [%d] > endIndex [%d]", beginIndex, endIndex));
unsigned long value = 0;
if ((beginIndex >= 0) && (endIndex >= 0) && (beginIndex <= endIndex))
{
for (int i = endIndex; i >= beginIndex; --i)
{
if (value)
value <<= 1;
if (testBit(i))
++value;
}
}
return value;
}
// -----------------------------------------------------------------------
void BitArray::reserve(int const numBits)
{
DEBUG_FATAL(numBits < 0, ("BitArray::reserve number of bits [%d] out of range", numBits));
if (numBits > 0)
{
// if shrinking, make sure to clear all the bits between
// the new size and the old size to to maintain requirement
// that every bit past 0-based index (m_numInUseBits - 1) is
// guaranteed to be unset
if (numBits < m_numInUseBits)
{
for (int i = numBits; i < m_numInUseBits; ++i)
clearBit(i);
}
m_numInUseBits = numBits;
int const oldNumInUseBytes = m_numInUseBytes;
m_numInUseBytes = (m_numInUseBits + 7) >> 3;
if (m_numInUseBytes > m_numAllocatedBytes)
{
signed char * tmp = new signed char[static_cast<size_t>(m_numInUseBytes)];
memset(&(tmp[oldNumInUseBytes]), 0, static_cast<size_t>(m_numInUseBytes - oldNumInUseBytes));
if ((oldNumInUseBytes > 0) && (m_arrayData != NULL))
memcpy(tmp, m_arrayData, static_cast<size_t>(oldNumInUseBytes)); //lint !e671 !e670 logically, you can't enter this code block unless oldNumInUseBytes is smaller.
m_numAllocatedBytes = m_numInUseBytes;
if (m_arrayData != m_defaultData)
delete []m_arrayData;
m_arrayData = tmp;
}
}
else if (numBits == 0)
{
if (m_arrayData != m_defaultData)
delete []m_arrayData;
m_arrayData = m_defaultData;
m_numAllocatedBytes = sizeof(m_defaultData);
m_numInUseBytes = 0;
m_numInUseBits = 0;
memset(m_arrayData, 0, m_numAllocatedBytes);
}
}
// -----------------------------------------------------------------------
bool BitArray::match(BitArray const & rhs) const
{
return operator==(rhs);
}
// -----------------------------------------------------------------------
bool BitArray::matchAnyBit(BitArray const & rhs) const
{
// compare the individual chars in the 2 array up to the number
// of chars needed to hold the smaller of the 2 m_numInUseBits
int const smallerArraySize = std::min(m_numInUseBytes, rhs.m_numInUseBytes);
for (int i = 0; i < smallerArraySize; ++i)
if (m_arrayData[i] & rhs.m_arrayData[i])
return true;
return false;
}
// -----------------------------------------------------------------------
namespace Archive
{
void get(ReadIterator &source, BitArray &target)
{
int numInUseBytes;
int numInUseBits;
get(source, numInUseBytes);
get(source, numInUseBits);
// trivial case, rhs is empty
if ((numInUseBits <= 0) || (numInUseBytes <= 0))
{
target.clear();
return;
}
// char array is too small, reallocate new char array
if (target.m_numAllocatedBytes < numInUseBytes)
{
if (target.m_arrayData != target.m_defaultData)
delete []target.m_arrayData;
target.m_arrayData = new signed char[static_cast<size_t>(numInUseBytes)];
target.m_numAllocatedBytes = numInUseBytes;
}
// char array is large enough, no reallocation required,
// but clear out char array, if necessary
else if (target.m_numInUseBytes > numInUseBytes)
{
memset(&(target.m_arrayData[numInUseBytes]), 0, static_cast<size_t>(target.m_numInUseBytes - numInUseBytes));
}
target.m_numInUseBytes = numInUseBytes;
target.m_numInUseBits = numInUseBits;
for (int i = 0; i < target.m_numInUseBytes; ++i)
{
get(source, target.m_arrayData[i]);
}
}
void put(ByteStream &target, const BitArray &source)
{
put(target, source.m_numInUseBytes);
put(target, source.m_numInUseBits);
if ((source.m_numInUseBits > 0) && (source.m_numInUseBytes > 0))
{
put(target, source.m_arrayData, source.m_numInUseBytes);
}
}
}
// -----------------------------------------------------------------------
void BitArray::clear()
{
if (m_numInUseBytes > 0)
{
memset(m_arrayData, 0, static_cast<size_t>(m_numInUseBytes));
m_numInUseBytes = 0;
m_numInUseBits = 0;
}
}
// -----------------------------------------------------------------------
void BitArray::setMultipleBits(int const count)
{
if (count <= 0)
return;
if (count > m_numInUseBits)
reserve(count);
int const charCount = (count >> 3);
if (charCount)
memset(m_arrayData, static_cast<unsigned>(0xFFFFFFFF), static_cast<size_t>(charCount));
for (int i = (charCount << 3); i < count; ++i)
setBit(i);
}
// -----------------------------------------------------------------------
void BitArray::insertBit(int const index, bool const value)
{
DEBUG_FATAL(index < 0, ("BitArray::insertBit index [%d] out of range", index));
// nothing to do if inserting a new bit past
// the end and the new bit will not be set
if (!value && (index >= m_numInUseBits))
return;
// if inserting a new bit in the middle, then shift all
// bits at and after the insertion point "backward"
if (index >= 0 && index < m_numInUseBits)
{
for(int i = (m_numInUseBits - 1); i >= index; --i)
{
if (testBit(i))
setBit(i + 1);
else
clearBit(i + 1);
}
}
// set/clear the inserted bit
if (value)
setBit(index);
else
clearBit(index);
}
// -----------------------------------------------------------------------
void BitArray::removeBit(int const index)
{
DEBUG_FATAL(index < 0, ("BitArray::removeBit index [%d] out of range", index));
// shift all bits after the removal point "forward"
if (index >= 0 && index < m_numInUseBits)
{
int const lastBitIndexToShift = m_numInUseBits - 1;
for(int i = index; i < lastBitIndexToShift; ++i)
{
if (testBit(i + 1))
setBit(i);
else
clearBit(i);
}
// shrink the array by 1
reserve(m_numInUseBits - 1);
}
}
// -----------------------------------------------------------------------
int BitArray::getNumberOfSetBits() const
{
int count = 0;
for (int i = 0; i < m_numInUseBits; ++i)
if (testBit(i))
++count;
return count;
}
// -----------------------------------------------------------------------
bool BitArray::empty() const
{
for (size_t i = 0; i < static_cast<size_t>(m_numInUseBytes); ++i)
{
if (m_arrayData[i])
return false;
}
return true;
}
// -----------------------------------------------------------------------
void BitArray::getAsDbTextString(std::string &result, int const maxNibbleCount /*= 32767*/) const
{
result.clear();
static const char hexDigits[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
bool anyBitSet = false;
unsigned char nibbleIntValue;
int const nibbleCount = std::min(maxNibbleCount, (m_numInUseBytes << 1));
for (int i = (nibbleCount - 1); i >= 0; --i)
{
nibbleIntValue = static_cast<unsigned char>(m_arrayData[i >> 1]);
if (i % 2)
nibbleIntValue >>= 4;
else
nibbleIntValue &= static_cast<unsigned char>(0xF);
if (nibbleIntValue && !anyBitSet)
{
anyBitSet = true;
result.resize(i + 1);
}
if (anyBitSet)
result[i] = hexDigits[nibbleIntValue];
}
}
// -----------------------------------------------------------------------
void BitArray::setFromDbTextString(const char * text)
{
clear();
int const nibbleCount = (text ? strlen(text) : 0);
if (nibbleCount > 0)
{
bool anyBitSet = false;
unsigned char nibbleIntValue;
// set the highest index bit first to avoid constant reallocation
for (int i = (nibbleCount - 1); i >= 0; --i)
{
if ((text[i] >= '0') && (text[i] <= '9'))
nibbleIntValue = static_cast<unsigned char>(text[i] - '0');
else if ((text[i] >= 'A') && (text[i] <= 'F'))
nibbleIntValue = static_cast<unsigned char>(text[i] - 'A' + 10);
else if ((text[i] >= 'a') && (text[i] <= 'f'))
nibbleIntValue = static_cast<unsigned char>(text[i] - 'a' + 10);
else
nibbleIntValue = static_cast<unsigned char>(0);
if (nibbleIntValue)
{
if (!anyBitSet)
{
anyBitSet = true;
reserve(((i >> 1) + 1) << 3);
}
if (i % 2)
m_arrayData[i >> 1] |= static_cast<signed char>(nibbleIntValue << 4);
else
m_arrayData[i >> 1] |= static_cast<signed char>(nibbleIntValue);
}
}
}
}
// -----------------------------------------------------------------------
std::string BitArray::getDebugString() const
{
std::string s = FormattedString<512>().sprintf("%6d: ", m_numInUseBits);
int i;
for (i = 0; i < m_numInUseBits; ++i)
{
if ((i > 0) && ((i % 8) == 0))
s += " ";
if (testBit(i))
s += "1";
else
s += "0";
}
s += " (";
std::string baString;
getAsDbTextString(baString);
s += baString;
s += ") (";
for (int i = 0; i < m_numAllocatedBytes; ++i)
{
if (i > 0)
s += " ";
if (i == m_numInUseBytes)
s += " ";
s += FormattedString<512>().sprintf("%02X", static_cast<unsigned char>(m_arrayData[i]));
}
s += ")";
if (m_arrayData == m_defaultData)
s += FormattedString<512>().sprintf(" (%d/%d default storage)", m_numInUseBytes, m_numAllocatedBytes);
else
s += FormattedString<512>().sprintf(" (%d/%d heap storage)", m_numInUseBytes, m_numAllocatedBytes);
return s;
}
// ======================================================================
@@ -0,0 +1,111 @@
// ======================================================================
//
// BitArray.h
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_BitArray_H
#define INCLUDED_BitArray_H
//----------------------------------------------------------------------
class BitArray;
namespace Archive
{
class ReadIterator;
class ByteStream;
void get (ReadIterator &source, BitArray &target);
void put (ByteStream &target, const BitArray &source);
}
//----------------------------------------------------------------------
class BitArray
{
public:
BitArray ();
explicit BitArray (int numBits);
BitArray (const BitArray&);
virtual ~BitArray ();
void setBit (int index);
void setValue (int beginIndex, int endIndex, unsigned long value);
void setMultipleBits(int count);
void clearBit (int index);
bool testBit (int index) const;
unsigned long getValue (int beginIndex, int endIndex) const;
void clear();
int getNumberOfSetBits() const;
bool empty() const;
void insertBit(int const index, bool value);
void removeBit(int const index);
std::string getDebugString() const;
// Equivalent to operator==()
bool match (const BitArray &rhs) const;
// Returns true if array has any bits set which this array also has set.
bool matchAnyBit (const BitArray &rhs) const;
//operators
BitArray & operator = (const BitArray &rhs);
bool operator == (const BitArray &rhs) const;
bool operator!= (const BitArray &rhs) const;
// for DB persistence purpose, returns the BitArray as a
// std::string where each 4 bits are printed as a hex nibble;
// and the converse that takes the null-terminated string
// and converts it back into the BitArray
void getAsDbTextString(std::string &result, int maxNibbleCount = 32767) const;
void setFromDbTextString(const char * text);
friend void Archive::get (ReadIterator &source, BitArray &target);
friend void Archive::put (ByteStream &target, const BitArray &source);
private:
// *****WARNING***** *****WARNING***** *****WARNING***** *****WARNING*****
// do not expose the "size" (either m_numInUseBits, m_numInUseBytes, or
// m_numAllocatedBytes) to the outside world, since it is not guaranteed
// to be accurate in terms of what the outside world expects the "size"
// to be; for optimization, BitArray doesn't necessarily change the "size"
// value(s) if a particular bit index is not set; for example, if you do
// setBit(1000000), and then do clearBit(1000000), the "size" is not
// necessarily 1000000; the only guarantee we make here is that
// testBit(1000000) will return false; the bottom line is that BitArray
// does not maintain the "size" of the BitArray, so no function should
// ever be added to return the "size" of the BitArray
// *****WARNING***** *****WARNING***** *****WARNING***** *****WARNING*****
// to avoid constant reallocation for small BitArray, small BitArray will
// use this as storage; only when the BitArray is larger than 128 (16*8)
// will we need to allocate off the heap
signed char m_defaultData[16];
// points to the storage for the BitArray, which will be either m_defaultData
// or heap allocated storage for BitArray larger than 128 (16*8)
signed char *m_arrayData;
// how many chars allocated in m_arrayData
int m_numAllocatedBytes;
// how many chars in m_arrayData that's actually used for the BitArray;
// this will always be <= m_numAllocatedBytes;
// this will always be 0 or (m_numInUseBits+7) >> 3, but we cache it here
// so we don't constantly have to calculate (m_numInUseBits+7) >> 3
int m_numInUseBytes;
// storage (i.e. m_arrayData) may be allocated to handle more than m_numInUseBits,
// because its expensive to be constantly expanding and shrinking m_arrayData;
// however, every bit past 0-based index (m_numInUseBits - 1) is guaranteed to be unset
int m_numInUseBits;
void reserve (int numBits);
};
//----------------------------------------------------------------------
#endif
@@ -0,0 +1,63 @@
// ======================================================================
//
// Branch.cpp
//
// copyright 2005 Sony Online Entertainment
// All Rights Reserved
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/Branch.h"
//----------------------------------------------------------------------
namespace BranchNamespace
{
#ifdef _WIN32
const char * cs_win32PathSeperator = "\\";
#endif
const char * cs_pathSeperator = "/";
const char * cs_branchIdentifierString = "/src/engine/shared";
}
using namespace BranchNamespace;
//----------------------------------------------------------------------
Branch::Branch()
{
m_branchName = __FILE__;
std::string::size_type slash = 0;
#ifdef _WIN32
while ( ( slash = m_branchName.find( cs_win32PathSeperator, slash ) ) != std::string::npos )
{
m_branchName[ slash ] = *cs_pathSeperator;
}
#endif
slash = m_branchName.find( cs_branchIdentifierString );
if ( slash != std::string::npos )
{
m_branchName.resize( slash );
slash = m_branchName.rfind( cs_pathSeperator );
if ( slash != std::string::npos )
{
m_branchName = m_branchName.substr( ++slash );
}
}
}
//----------------------------------------------------------------------
const std::string & Branch::getBranchName() const
{
return m_branchName;
}
//----------------------------------------------------------------------
@@ -0,0 +1,26 @@
// ======================================================================
//
// Branch.h
// copyright 2005 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Branch_H
#define INCLUDED_Branch_H
#include <string>
class Branch
{
public:
Branch();
const std::string & getBranchName() const;
private:
std::string m_branchName;
};
// ======================================================================
#endif
@@ -0,0 +1,398 @@
// ======================================================================
//
// CalendarTime.cpp
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/CalendarTime.h"
#include <string>
// ======================================================================
std::string CalendarTime::convertEpochToTimeStringGMT(time_t epoch)
{
std::string result;
struct tm * timeinfo = ::gmtime(&epoch);
if (timeinfo == NULL)
return result;
char * asciiTime = ::asctime(timeinfo);
if (asciiTime == NULL)
return result;
static char resultBuffer[512];
char * buffer = resultBuffer;
if (strlen(asciiTime) >= sizeof(resultBuffer))
buffer = new char[strlen(asciiTime) + 1];
strcpy(buffer, asciiTime);
buffer[strcspn(buffer, "\r\n")] = '\0';
result = buffer;
if (buffer != resultBuffer)
delete[] buffer;
result += " GMT";
return result;
}
// ======================================================================
std::string CalendarTime::convertEpochToTimeStringGMT_YYYYMMDDHHMMSS(time_t epoch)
{
std::string result;
struct tm * timeinfo = ::gmtime(&epoch);
if (timeinfo == NULL)
return result;
static char resultBuffer[512];
snprintf(resultBuffer, sizeof(resultBuffer), "%d-%02d-%02d %02d:%02d:%02d GMT", (timeinfo->tm_year + 1900), (timeinfo->tm_mon + 1), timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
return std::string(resultBuffer);
}
//-----------------------------------------------------------------
std::string CalendarTime::convertEpochToTimeStringLocal(time_t epoch)
{
std::string result;
struct tm * timeinfo = ::localtime(&epoch);
if (timeinfo == NULL)
return result;
char * asciiTime = ::asctime(timeinfo);
if (asciiTime == NULL)
return result;
static char resultBuffer[512];
char * buffer = resultBuffer;
if (strlen(asciiTime) >= sizeof(resultBuffer))
buffer = new char[strlen(asciiTime) + 1];
strcpy(buffer, asciiTime);
buffer[strcspn(buffer, "\r\n")] = '\0';
result = buffer;
if (buffer != resultBuffer)
delete[] buffer;
// get local time zone string
static char buffer2[256];
if (0 < ::strftime(buffer2, sizeof(buffer2)-1, "%Z", timeinfo))
{
result += " ";
result += buffer2;
}
else
{
result += " local";
}
return result;
}
//-----------------------------------------------------------------
std::string CalendarTime::convertEpochToTimeStringLocal_YYYYMMDDHHMMSS(time_t epoch)
{
std::string result;
struct tm * timeinfo = ::localtime(&epoch);
if (timeinfo == NULL)
return result;
static char resultBuffer[512];
snprintf(resultBuffer, sizeof(resultBuffer), "%d-%02d-%02d %02d:%02d:%02d ", (timeinfo->tm_year + 1900), (timeinfo->tm_mon + 1), timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
result = resultBuffer;
if (0 < ::strftime(resultBuffer, sizeof(resultBuffer)-1, "%Z", timeinfo))
{
result += resultBuffer;
}
else
{
result += "local";
}
return result;
}
//-----------------------------------------------------------------
std::string CalendarTime::convertSecondsToDHMS(unsigned int numSeconds)
{
char buffer[128];
snprintf(buffer, sizeof(buffer)-1, "%ud:%uh:%um:%us",
numSeconds / (60 * 60 * 24),
(numSeconds % (60 * 60 * 24)) / (60 * 60),
(numSeconds % (60 * 60)) / 60,
numSeconds % 60);
buffer[sizeof(buffer)-1] = '\0';
return std::string(buffer);
}
//-----------------------------------------------------------------
std::string CalendarTime::convertSecondsToHMS(unsigned int numSeconds)
{
char buffer[128];
snprintf(buffer, sizeof(buffer)-1, "%uh:%um:%us",
numSeconds / (60 * 60),
(numSeconds % (60 * 60)) / 60,
numSeconds % 60);
buffer[sizeof(buffer)-1] = '\0';
return std::string(buffer);
}
//-----------------------------------------------------------------
std::string CalendarTime::convertSecondsToMS(unsigned int numSeconds)
{
char buffer[128];
snprintf(buffer, sizeof(buffer)-1, "%um:%us",
numSeconds / 60,
numSeconds % 60);
buffer[sizeof(buffer)-1] = '\0';
return std::string(buffer);
}
//-----------------------------------------------------------------
// given a starting Epoch GMT time, returns the Epoch GMT time when the next specified
// GMT day of week, hour, minute, and second will occur; note that the day of week, hour,
// minute, and second specified will all be interpreted in terms of GMT time
//
// returns -1 if invalid parameters are specified or there are any system errors
// in making the calculation
//
// day of week is 0=Sunday, 1=Monday, 2=Tuesday, 3=Wednesday, 4=Thursday, 5=Friday, 6=Saturday
// if you just want to find out when the next hour, minute, second will occur, specify -1 for
// day of week
//
// hour must be between 0-23
// if you just want to find out when the next minute, second will occur, specify -1 for day
// of week and -1 for hour
//
// minute must be between 0-59
//
// second must be between 0-59
time_t CalendarTime::getNextGMTTimeOcurrence(time_t const startTime, int const dayOfWeek, int const hour, int const minute, int const second)
{
// don't allow start time to be too far in the past
if (startTime < CalendarTimeNamespace::g_CalendarTimeEarliestTime)
return -1;
if ((dayOfWeek < -1) || (dayOfWeek > 6))
return -1;
if ((hour < -1) || (hour > 23))
return -1;
if ((hour == -1) && (dayOfWeek != -1))
return -1;
if ((minute < 0) || (minute > 59))
return -1;
if ((second < 0) || (second > 59))
return -1;
// convert the start time into a broken down time containing
// the year, month, day, day of week, hour, minute, second
// in GMT time
struct tm * timeinfo = ::gmtime(&startTime);
if (timeinfo == NULL)
return -1;
// get number of days until the specified day of week to search for
if (dayOfWeek >= 0)
{
int daysUntil = 0;
// calculate the Epoch GMT time for the specified start time
// at the specified hour, minute, and second
time_t startTimeAtSpecifiedHourMinuteSecond = startTime + (((hour * 60 * 60) + (minute * 60) + second) - ((timeinfo->tm_hour * 60 * 60) + (timeinfo->tm_min * 60) + timeinfo->tm_sec));
if (timeinfo->tm_wday != dayOfWeek)
{
if (timeinfo->tm_wday < dayOfWeek)
daysUntil = dayOfWeek - timeinfo->tm_wday;
else
// wraparound
daysUntil = (6 - timeinfo->tm_wday) + dayOfWeek + 1;
}
else
{
// if the specified day of week matches the start day of week, but
// the specified time has already passed, then we want go forward
// to next week
if (startTimeAtSpecifiedHourMinuteSecond <= startTime)
daysUntil = 7;
}
// the next time the that the day/time will match
startTimeAtSpecifiedHourMinuteSecond += (60 * 60 * 24 * daysUntil);
return startTimeAtSpecifiedHourMinuteSecond;
}
// dayOfWeek == -1
if (hour >= 0)
{
// calculate the Epoch GMT time for the specified start time
// at the specified hour, minute, and second
time_t startTimeAtSpecifiedHourMinuteSecond = startTime + (((hour * 60 * 60) + (minute * 60) + second) - ((timeinfo->tm_hour * 60 * 60) + (timeinfo->tm_min * 60) + timeinfo->tm_sec));
// no day of week specified, we want when the time will
// match on the day of the start time, or if the time has
// already passed for the day of the start time, then we
// when the time will match for the day following the day
// of the start time
if (startTimeAtSpecifiedHourMinuteSecond <= startTime)
startTimeAtSpecifiedHourMinuteSecond += (60 * 60 * 24);
return startTimeAtSpecifiedHourMinuteSecond;
}
// dayOfWeek == -1 and hour == -1
time_t startTimeAtSpecifiedHourMinuteSecond = startTime + (((minute * 60) + second) - ((timeinfo->tm_min * 60) + timeinfo->tm_sec));
// no day of week or hour specified, we want when the minute:second
// will match on the hour of the start time, or if the minute:second
// has already passed for the hour of the start time, then we want
// when the minute:second will match for the hour following the
// hour of the start time
if (startTimeAtSpecifiedHourMinuteSecond <= startTime)
startTimeAtSpecifiedHourMinuteSecond += (60 * 60);
return startTimeAtSpecifiedHourMinuteSecond;
}
//-----------------------------------------------------------------
// given a starting Epoch GMT time, returns the Epoch GMT time when the next specified
// GMT month, day of month, hour, minute, and second will occur; note that the month,
// day of month, hour, minute, and second specified will all be interpreted in terms
// of GMT time
//
// returns -1 if invalid parameters are specified or there are any system errors
// in making the calculation
//
// month must be between 1-12
// if you just want to find out when the next day of month, hour, minute, and second will occur,
// specify -1 for month
//
// dayOfMonth must be between 1-31
//
// hour must be between 0-23
//
// minute must be between 0-59
//
// second must be between 0-59
time_t CalendarTime::getNextGMTTimeOcurrence(time_t const startTime, int const month, int const dayOfMonth, int const hour, int const minute, int const second)
{
// don't allow start time to be too far in the past
if (startTime < CalendarTimeNamespace::g_CalendarTimeEarliestTime)
return -1;
if (month == 0)
return -1;
if ((month < -1) || (month > 12))
return -1;
if ((dayOfMonth < 1) || (dayOfMonth > 31))
return -1;
if ((hour < 0) || (hour > 23))
return -1;
if ((minute < 0) || (minute > 59))
return -1;
if ((second < 0) || (second > 59))
return -1;
// convert the start time into a broken down time containing
// the year, month, day, day of week, hour, minute, second
// in GMT time
struct tm * timeinfo = ::gmtime(&startTime);
if (timeinfo == NULL)
return -1;
// calculate the Epoch GMT time for the specified start time
// at the specified hour, minute, and second
time_t startTimeAtSpecifiedHourMinuteSecond = startTime + (((hour * 60 * 60) + (minute * 60) + second) - ((timeinfo->tm_hour * 60 * 60) + (timeinfo->tm_min * 60) + timeinfo->tm_sec));
// timeinfo uses 0-based month
int const targetMonth = ((month == -1) ? -1 : (month - 1));
// to catch infinite loop caused by stuff like "April 31", but
// make sure we loop long enough to include the next leap day "February 29"
int const maxIterations = (((month == 2) && (dayOfMonth == 29)) ? (365*4+1) : (365+1));
int sentinel = 0;
while (true)
{
if (((targetMonth == -1) || (targetMonth == timeinfo->tm_mon)) && (dayOfMonth == timeinfo->tm_mday) && (startTimeAtSpecifiedHourMinuteSecond > startTime))
break;
// start adding 1 day at a time until the target month and day of month is reached
// TODO: find a better way of doing this rather than looping 1 day at a time
startTimeAtSpecifiedHourMinuteSecond += (60 * 60 * 24);
timeinfo = ::gmtime(&startTimeAtSpecifiedHourMinuteSecond);
if (timeinfo == NULL)
return -1;
if (++sentinel > maxIterations)
return -1;
}
return startTimeAtSpecifiedHourMinuteSecond;
}
//-----------------------------------------------------------------
std::string CalendarTime::getCharacerBirthDateString(int characterBirthDate)
{
// the birth date (for characters created on live and TC clusters) is the
// number of days since 00:00:00 Jan 1st, 2001 PST
// (see the server's PlayerObject::getCurrentBornDate())
// 978336000 is the epoch value corresponding to 00:00:00 Jan 1st, 2001 PST
time_t const baseTime = 978336000 + static_cast<time_t>(characterBirthDate * 60 * 60 * 24) - (60 * 60 * 12);
struct tm const * const birthDateTimeData = ::localtime(&baseTime);
// get local time zone string
std::string timeZone("local");
char buffer[256];
if (0 < ::strftime(buffer, sizeof(buffer)-1, "%Z", birthDateTimeData))
{
timeZone = buffer;
}
snprintf(buffer, sizeof(buffer)-1, "%02d %02d %d %s", (birthDateTimeData->tm_mon + 1), birthDateTimeData->tm_mday, (birthDateTimeData->tm_year + 1900), timeZone.c_str());
buffer[sizeof(buffer)-1] = '\0';
return std::string(buffer);
}
// ======================================================================
@@ -0,0 +1,42 @@
// ======================================================================
//
// CalendarTime.h
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_CalendarTime_H
#define INCLUDED_CalendarTime_H
// ======================================================================
// Sat Jan 01 00:00:00 1980 (just an arbitrary value)
namespace CalendarTimeNamespace
{
const time_t g_CalendarTimeEarliestTime = 315550800;
};
class CalendarTime
{
private:
CalendarTime(void);
CalendarTime(const CalendarTime &);
CalendarTime &operator =(const CalendarTime &);
public:
static std::string convertEpochToTimeStringGMT(time_t epoch);
static std::string convertEpochToTimeStringGMT_YYYYMMDDHHMMSS(time_t epoch);
static std::string convertEpochToTimeStringLocal(time_t epoch);
static std::string convertEpochToTimeStringLocal_YYYYMMDDHHMMSS(time_t epoch);
static std::string convertSecondsToDHMS(unsigned int numSeconds);
static std::string convertSecondsToHMS(unsigned int numSeconds);
static std::string convertSecondsToMS(unsigned int numSeconds);
static time_t getNextGMTTimeOcurrence(time_t startTime, int dayOfWeek, int hour, int minute, int second);
static time_t getNextGMTTimeOcurrence(time_t startTime, int month, int dayOfMonth, int hour, int minute, int second);
static std::string getCharacerBirthDateString(int characterBirthDate);
};
#endif
@@ -0,0 +1,56 @@
// CallbackEntryBase.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_CallbackEntryBase_H
#define _INCLUDED_CallbackEntryBase_H
//-----------------------------------------------------------------------
class Scheduler;
//-----------------------------------------------------------------------
/** @brief Internally used class that identifies callbacks.
@see CallbackEntry
@see StaticCallbackEntry
@author Justin Randall
*/
class CallbackEntryBase
{
protected:
CallbackEntryBase(const unsigned long when);
virtual ~CallbackEntryBase() = 0;
public:
virtual void expired() = 0;
const unsigned long getExpireCount() const;
/** @brief Compare functor supplied for use with a priority queue.
*/
struct Compare
{
bool operator ()(const CallbackEntryBase * lhs, const CallbackEntryBase * rhs) const
{
return lhs->expireCount > rhs->expireCount;
}
};
protected:
friend struct Compare;
unsigned long expireCount;
};
//-----------------------------------------------------------------------
/** @return the expiration count ("time", "frame", whatever) of the callback.
*/
inline const unsigned long CallbackEntryBase::getExpireCount() const
{
return expireCount;
}
//-----------------------------------------------------------------------
#endif // _INCLUDED_CallbackEntryBase_H
@@ -0,0 +1,528 @@
// ======================================================================
//
// Clock.cpp
//
// Portions copyright 1998 Bootprint Entertainment
// Portsion copyright 2002 Sony Online Entertainment
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/Clock.h"
#include "sharedFoundation/ConfigFile.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include "sharedDebug/DebugFlags.h"
#include "sharedDebug/Profiler.h"
#include "sharedFile/TreeFile.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/Production.h"
#include "sharedDebug/RemoteDebug.h"
#include "sharedSynchronization/Mutex.h"
#include "sharedSynchronization/Semaphore.h"
#include "sharedThread/RunThread.h"
#include "sharedThread/ThreadHandle.h"
#include <string>
#ifdef PLATFORM_WIN32 //@todo code reorg
#include "sharedFoundation/WindowsWrapper.h"
#endif
// ======================================================================
real Clock::ms_lastFrameRate;
// ======================================================================
namespace ClockNamespace
{
__int64 ms_lastPoll; // the last time the clock was polled at the start of a frame
real ms_lastFrameTime; // the time (in seconds) that the last frame took
real ms_maxFrameTime; // the maximum time a frame is allowed to be. If exceeded, a warning is logged.
unsigned long ms_applicationStartTime; // the time the application was started
double ms_realTimeMilliseconds;
bool ms_useSleep;
#if PRODUCTION == 0
bool ms_debugReportFlag;
bool ms_debugReportLogFlag;
#endif
bool ms_debugReportLongFrames;
int ms_previousNumberOfFilesOpenedTotal;
int ms_previousSizeOfFilesOpenedTotal;
int ms_timeZone;
ThreadHandle ms_threadHandle;
Mutex ms_mutex;
Semaphore ms_shutdownEvent;
bool ms_shutdown = false;
unsigned int const ms_recalibrationInterval = 1000;
unsigned int const ms_recalibrationMultiplier = 1000 / ms_recalibrationInterval;
real ms_realFrequency; // periodically calibrated clock frequency, updated from clock thread
real ms_frameFrequency; // clock frequency being used during the current frame, updated from realFrequency each frame
real ms_frameRateLimit;
static const double cms_secondsPerMillisecond = 0.001;
#if PRODUCTION == 0
static void reportMinimumFrameTime();
bool ms_reportMinimumFrameTime;
bool ms_resetMinimumFrameTime;
float ms_minimumFrameTime;
bool ms_useRecalibrationThread;
bool ms_lastUseRecalibrationThread;
#endif
bool ms_longFramesWarningAllowed = true;
void threadRoutine();
}
using namespace ClockNamespace;
// ======================================================================
// Install the Clock subsystem
//
// Remarks:
//
// The Clock currently requires the use of the high performance counter in Windows.
// If the high performance counter is unavailable, this routine will call Fatal.
//
// This routine will also add Clock::remove to the ExitChain.
//
// See Also:
//
// Clock::remove()
void Clock::install(bool newUseSleep, bool useRecalibrationThread)
{
BOOL result;
ms_useSleep = newUseSleep;
#if PRODUCTION == 0
ms_useRecalibrationThread = useRecalibrationThread;
ms_lastUseRecalibrationThread = useRecalibrationThread;
#endif
ExitChain::add(Clock::remove, "Clock::remove");
__int64 frequency;
result = QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&frequency));
FATAL(!result, ("Clock::install QPF failed"));
result = QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&ms_lastPoll));
FATAL(!result, ("Clock::install QPC failed"));
ms_realFrequency = static_cast<real>(frequency);
ms_frameFrequency = ms_realFrequency;
if (ConfigSharedFoundation::getFrameRateLimit() != 0.0f)
setFrameRateLimit(ConfigSharedFoundation::getFrameRateLimit());
setMinFrameRate(ConfigSharedFoundation::getMinFrameRate());
#if PRODUCTION == 0
DebugFlags::registerFlag(ms_debugReportFlag, "SharedFoundation", "reportClock", debugReport, -1000);
DebugFlags::registerFlag(ms_reportMinimumFrameTime, "SharedFoundation", "reportMinimumFrameTime", reportMinimumFrameTime, -990);
DebugFlags::registerFlag(ms_resetMinimumFrameTime, "SharedFoundation", "resetMinimumFrameTime");
DebugFlags::registerFlag(ms_debugReportLogFlag, "SharedFoundation", "logClock");
DebugFlags::registerFlag(ms_debugReportLongFrames, "SharedFoundation", "debugReportLongFrames");
DebugFlags::registerFlag(ms_useRecalibrationThread, "SharedFoundation", "useClockRecalibrationThread");
#endif
time_t t = 0;
localtime(&t);
ms_timeZone = timezone;
if(ms_timeZone < (12 * 60 * 60))
{
ms_timeZone = -ms_timeZone;
}
ms_realTimeMilliseconds = static_cast<double>(ms_lastPoll / ms_frameFrequency * 1000.f);
ms_applicationStartTime = timeSeconds();
if (useRecalibrationThread)
{
ms_shutdown = false;
ms_threadHandle = runNamedThread("Clock", threadRoutine);
ms_threadHandle->setPriority(Thread::kCritical);
}
}
// ----------------------------------------------------------------------
/**
* Remove the clock subsystem.
*
* This routine should not be called directly by users. Clock::install() will add
* this routine onto the ExitChain.
*
* @see Clock::install()
*/
void Clock::remove(void)
{
#if PRODUCTION == 0
DebugFlags::unregisterFlag(ms_debugReportFlag);
DebugFlags::unregisterFlag(ms_debugReportLogFlag);
DebugFlags::unregisterFlag(ms_debugReportLongFrames);
#endif
if (ms_threadHandle)
{
ms_mutex.enter();
ms_shutdown = true;
ms_mutex.leave();
ms_shutdownEvent.signal();
ms_threadHandle->wait();
}
}
// ----------------------------------------------------------------------
/**
* Update the clock.
*
* This routine will recompute the amount of time the last frame took to complete.
* If this routine is not called, the values returned by Clock::frameTime() and
* Clock::framesPerSecond() will not change.
*
* @see Clock::frameTime(), Clock::framesPerSecond()
*/
void Clock::update(void)
{
__int64 newPoll;
BOOL result;
#if PRODUCTION == 0
if (ms_lastUseRecalibrationThread != ms_useRecalibrationThread)
{
if (ms_useRecalibrationThread)
{
ms_shutdown = false;
ms_threadHandle = runNamedThread("Clock", threadRoutine);
ms_threadHandle->setPriority(Thread::kCritical);
}
else
{
ms_mutex.enter();
ms_shutdown = true;
ms_mutex.leave();
ms_shutdownEvent.signal();
ms_threadHandle->wait();
}
ms_lastUseRecalibrationThread = ms_useRecalibrationThread;
}
#endif
result = QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&newPoll));
FATAL(!result, ("Clock::update QPC failed"));
// We need to consider time before this frame as having passed with a
// potentially different frequency, and also need to consider portions
// of a millisecond.
real const frameTime = static_cast<real>(newPoll - ms_lastPoll) / ms_frameFrequency;
ms_realTimeMilliseconds += static_cast<double>(frameTime*1000.f);
ms_mutex.enter();
ms_frameFrequency = ms_realFrequency;
ms_mutex.leave();
if (!Os::wasFocusLost())
{
ms_lastFrameTime = frameTime;
#if PRODUCTION == 0
float const debugReportLongFrameTime = ConfigSharedFoundation::getDebugReportLongFrameTime();
if (ms_debugReportLongFrames && ms_lastFrameTime > debugReportLongFrameTime)
{
REPORT_LOG(true, ("------------------------------------------------\n"));
REPORT_LOG(true, ("WARNING: Clock::update[%d] Last Frame took %f seconds\n", Os::getNumberOfUpdates(), ms_lastFrameTime));
REPORT_LOG(true, ("Files: %4d opened, %4d KB\n", TreeFile::getNumberOfFilesOpenedTotal() - ms_previousNumberOfFilesOpenedTotal, (TreeFile::getSizeOfFilesOpenedTotal() - ms_previousSizeOfFilesOpenedTotal) / 1024));
Profiler::setTemporaryExpandAll(true);
Profiler::printLastFrameData();
REPORT_LOG(true, ("%s\n", Profiler::getLastFrameData()));
Profiler::setTemporaryExpandAll(false);
}
#endif
if (ms_lastFrameTime > ms_maxFrameTime)
{
DEBUG_REPORT_LOG(ms_longFramesWarningAllowed, ("WARNING: Clock::update[%d] Last Frame took %f seconds\n", Os::getNumberOfUpdates(), ms_lastFrameTime));
ms_lastFrameTime = ms_maxFrameTime;
}
ms_lastFrameRate = RECIP(ms_lastFrameTime);
}
#if 0
// -qq- debugging W2K QueryPerformanceCounter
static DWORD lastTick;
DWORD newTick = GetTickCount();
DEBUG_REPORT_LOG_PRINT(true, ("Clock::update %I64d %I64d %6I64d %10d %10d %3d %6.2f=fps %6.4f=time\n", ms_lastPoll, newPoll, newPoll - ms_lastPoll, lastTick, newTick, newTick - lastTick, ms_lastFrameRate, ms_lastFrameTime));
static int bad = 0;
if (bad && ++bad > 64)
__asm int 3;
if (ms_lastFrameTime > 3.0)
bad = 1;
lastTick = newTick;
#endif
ms_lastPoll = newPoll;
#if PRODUCTION == 0
ms_previousNumberOfFilesOpenedTotal = TreeFile::getNumberOfFilesOpenedTotal();
ms_previousSizeOfFilesOpenedTotal = TreeFile::getSizeOfFilesOpenedTotal();
if (ms_resetMinimumFrameTime || ms_lastFrameTime < ms_minimumFrameTime)
{
ms_resetMinimumFrameTime = false;
ms_minimumFrameTime = ms_lastFrameTime;
}
#endif
}
// ----------------------------------------------------------------------
/**
* Display debugging information for the clock.
*/
void Clock::debugReport(void)
{
#if PRODUCTION == 0
REPORT(true, Report::RF_print | (ms_debugReportLogFlag ? Report::RF_log : 0), ("Clock %6.2f=fps %8.6f=time\n", ms_lastFrameRate, ms_lastFrameTime));
DEBUG_OUTPUT_STATIC_VIEW_BEGINFRAME("Foundation\\Clock");
DEBUG_OUTPUT_STATIC_VIEW("Foundation\\Clock", ("Clock %6.2f=fps %6.4f=time\n", ms_lastFrameRate, ms_lastFrameTime));
DEBUG_OUTPUT_STATIC_VIEW_ENDFRAME("Foundation\\Clock");
#endif
}
// ----------------------------------------------------------------------
#if PRODUCTION == 0
void ClockNamespace::reportMinimumFrameTime(void)
{
REPORT(true, Report::RF_print, ("min frame time %8.6f\n", ms_minimumFrameTime));
}
#endif
// ----------------------------------------------------------------------
// Get the amount of time the last frame took
//
// Return Value:
//
// Time, in seconds, for the last frame
//
// Remarks:
//
// This routine currently does not take in to account if the game was
// task-switched out of.
//
// See Also:
//
// Clock::framesPerSecond()
real Clock::frameTime(void)
{
return ms_lastFrameTime;
}
// ----------------------------------------------------------------------
/**
* Disable the frame rate limiter.
*
* Calling this routine will make the Clock subsystem allow the game to run at
* the fastest rate possible.
*
* @see Clock::setFrameRateLimit()
*/
void Clock::noFrameRateLimit(void)
{
ms_frameRateLimit = 0.f;
}
// ----------------------------------------------------------------------
/**
* Enable the frame rate limiter to a specific frame rate value.
*
* This routine will set the maximum number of frame-per-second that the game
* will be allowed to run. If the game could run faster than that, the Clock
* subsystem will wait when Clock::limitFrameRate() is called.
*
* @param newFrameRateLimit Frames per second for the clock to limit the game to
* @see Clock::noFrameRateLimit(), Clock::limitFrameRate()
*/
void Clock::setFrameRateLimit(real newFrameRateLimit)
{
DEBUG_FATAL(newFrameRateLimit < 1.0f, ("Clock::setFrameRateLimit can not be under 1, %f", newFrameRateLimit));
ms_frameRateLimit = newFrameRateLimit;
}
// ----------------------------------------------------------------------
/**
* Set a minimum frame rate for the game.
*
* This routine sets a minimum frame rate for the game. Any frames that take longer will
* log a warning then have the next frame time set to the given minimum value.
*
*/
void Clock::setMinFrameRate(real newMinFrameRate)
{
if (newMinFrameRate == 0)
ms_maxFrameTime = REAL_MAX;
else
ms_maxFrameTime = RECIP(newMinFrameRate);
}
// ----------------------------------------------------------------------
/**
* Wait if the game is running too fast.
*
* If the frame rate limiter has been enabled by calling Clock::setFrameRateLimit(), this
* routine will make sure that the game never exceeds the framerate specified at
* that function call.
*
* If the frame rate limiter is not enabled, or has been disabled by calling
* Clock::noFrameRateLimit(), this routine will do nothing.
*
* @see Clock::noFrameRateLimit(), Clock::setFrameRateLimit()
*/
void Clock::limitFrameRate(void)
{
BOOL result;
// check if the frame rate limiter is on
if (ms_frameRateLimit)
{
__int64 const frameRateLimitTicks = static_cast<__int64>(ms_frameFrequency / ms_frameRateLimit);
__int64 newPoll, delta;
for (;;)
{
// get the current time
result = QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&newPoll));
FATAL(!result, ("Clock::limitFrameRate QPC failed"));
// compute elapsed time
delta = newPoll - ms_lastPoll;
if (delta >= frameRateLimitTicks)
break;
//@todo it looks like if delta is huge we will sleep a looong time. shouldn't we check delta and the frameRatelimit before sleeping?
if (ms_useSleep)
{
const DWORD sleepTicks = static_cast<DWORD>(static_cast<real>((frameRateLimitTicks - delta) / ms_frameFrequency) * 1000.0f);
if (sleepTicks > 2)
Sleep(sleepTicks);
}
}
}
}
//-----------------------------------------------------------------------
const unsigned long Clock::timeMs()
{
__int64 newPoll;
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&newPoll));
double const frameTime = static_cast<double>(newPoll - ms_lastPoll) / ms_frameFrequency;
return static_cast<unsigned long>(ms_realTimeMilliseconds + frameTime*1000.f);
}
//-----------------------------------------------------------------------
const unsigned long Clock::timeSeconds()
{
__int64 newPoll;
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&newPoll));
double const frameTime = static_cast<double>(newPoll - ms_lastPoll) / ms_frameFrequency;
return static_cast<unsigned long>(ms_realTimeMilliseconds/1000.f + frameTime);
}
// ----------------------------------------------------------------------
const unsigned long Clock::getFrameStartTimeMs()
{
return static_cast<unsigned long>(ms_realTimeMilliseconds);
}
// ----------------------------------------------------------------------
double Clock::getCurrentTime()
{
__int64 newPoll;
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&newPoll));
double const frameTime = static_cast<double>(newPoll - ms_lastPoll) / ms_frameFrequency;
return getFrameStartTime() + frameTime;
}
// ----------------------------------------------------------------------
double Clock::getFrameStartTime()
{
return ms_realTimeMilliseconds * cms_secondsPerMillisecond;
}
// ----------------------------------------------------------------------
const unsigned long Clock::getSecondsSinceStart()
{
return timeSeconds() - ms_applicationStartTime;
}
// ----------------------------------------------------------------------
const int Clock::getTimeZone()
{
return ms_timeZone;
}
// ----------------------------------------------------------------------
void ClockNamespace::threadRoutine()
{
bool done = false;
while (!done)
{
__int64 startCounter, endCounter;
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&startCounter));
ms_shutdownEvent.wait(ms_recalibrationInterval);
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&endCounter));
__int64 newFrequency = (endCounter-startCounter)*ms_recalibrationMultiplier;
ms_mutex.enter();
if (ms_shutdown)
done = true;
else if (newFrequency)
ms_realFrequency = static_cast<real>(newFrequency);
ms_mutex.leave();
}
}
//----------------------------------------------------------------------
void Clock::setLongFramesWarningAllowed(bool allowed)
{
ms_longFramesWarningAllowed = allowed;
}
// ======================================================================
@@ -0,0 +1,76 @@
// ======================================================================
//
// Clock.h
//
// Portions copyright 1998 Bootprint Entertainment
// Portions copyright 2002 Sony Online Entertainment
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_Clock_H
#define INCLUDED_Clock_H
// ======================================================================
class Clock
{
private:
Clock(void);
Clock(const Clock &);
Clock &operator =(const Clock &);
private:
// the instantaneous frame rate of the last frame (1 / lastFrameTime)
static real ms_lastFrameRate;
public:
static void install(bool newUseSleep, bool useRecalibrationThread);
static void remove(void);
static void update(void);
static void debugReport();
static DLLEXPORT real frameTime(void);
static real framesPerSecond(void);
static void noFrameRateLimit(void);
static void setFrameRateLimit(real newFrameRateLimit);
static void limitFrameRate(void);
static void setMinFrameRate(real newMinFrameRate);
static const unsigned long timeMs();
static const unsigned long timeSeconds();
static const unsigned long getFrameStartTimeMs();
static double getCurrentTime();
static double getFrameStartTime();
static const unsigned long getSecondsSinceStart();
static const int getTimeZone();
static void setLongFramesWarningAllowed(bool allowed);
};
// ======================================================================
/**
* Get the instantaneous frame rate.
*
* This number is really only useful for determining game performance
*
* @return The number of frames per second for the last frame
* @see Clock::frameTime()
*/
inline real Clock::framesPerSecond(void)
{
return ms_lastFrameRate;
}
// ======================================================================
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,790 @@
// ======================================================================
//
// CommandLine.h
// Todd Fiala
//
// copyright 1999, Bootprint Entertainment
//
// ======================================================================
#ifndef COMMAND_LINE_H
#define COMMAND_LINE_H
// ======================================================================
enum OP_ListType
{
OPLT_Normal,
OPLT_MinimumMatch
};
#define OP_BEGIN_LIST() { CommandLine::OST_BeginList, static_cast<int>(OPLT_Normal), 0, 0, 0 }
#define OP_END_LIST() { CommandLine::OST_EndList, 0, 0, 0, 0 }
#define OP_BEGIN_MINIMUM_MATCH_LIST(minimumNodeCount) { CommandLine::OST_BeginList, static_cast<int>(OPLT_MinimumMatch), minimumNodeCount, 0, 0 }
#define OP_END_MINIMUM_MATCH_LIST() { CommandLine::OST_EndList, 0, 0, 0, 0 }
#define OP_BEGIN_SWITCH(oneIsRequired) { CommandLine::OST_BeginSwitch, oneIsRequired, 0, 0, 0 }
#define OP_END_SWITCH() { CommandLine::OST_EndSwitch, 0, 0, 0, 0 }
#define OP_BEGIN_LIST_NODE(multipleIsAllowed, isRequiredNode) { CommandLine::OST_BeginListNode, multipleIsAllowed, isRequiredNode, 0, 0 }
#define OP_END_LIST_NODE() { CommandLine::OST_EndListNode, 0, 0, 0, 0 }
#define OP_BEGIN_SWITCH_NODE(multipleIsAllowed) { CommandLine::OST_BeginSwitchNode, multipleIsAllowed, 0, 0, 0 }
#define OP_END_SWITCH_NODE() { CommandLine::OST_EndSwitchNode, 0, 0, 0, 0 }
#define OP_OPTION(shortName, longName, argumentPolicy) { CommandLine::OST_Option, argumentPolicy, 0, shortName, longName }
#define OP_SINGLE_LIST_NODE(shortName, longName, argMode, multipleIsAllowed, isRequiredNode) OP_BEGIN_LIST_NODE(multipleIsAllowed, isRequiredNode), OP_OPTION(shortName, longName, argMode), OP_END_LIST_NODE()
#define OP_SINGLE_SWITCH_NODE(shortName, longName, argMode, multipleIsAllowed) OP_BEGIN_SWITCH_NODE(multipleIsAllowed), OP_OPTION(shortName, longName, argMode), OP_END_SWITCH_NODE()
//lint -save -e1923 // #define could become const
#define OP_ARG_NONE 0
#define OP_ARG_REQUIRED 1
#define OP_ARG_OPTIONAL 2
#define OP_NODE_REQUIRED 1
#define OP_NODE_OPTIONAL 0
#define OP_MULTIPLE_ALLOWED 1
#define OP_MULTIPLE_DENIED 0
#define OP_SNAME_UNTAGGED 1
#define OP_LNAME_UNTAGGED static_cast<const char*>(0)
//lint -restore
// ======================================================================
class CommandLine
{
private:
enum
{
STATIC_BUFFER_SIZE = 4096
};
public:
enum MatchCode
{
MC_MATCH = 1,
MC_NO_MATCH = 0,
MC_REQUIRED_MATCH_MISSING = -1,
MC_TOO_MANY_CHILDREN_MATCHES = -2,
MC_TOO_MANY_NODE_MATCHES = -3,
MC_ARG_NOT_EXPECTED = -4,
MC_ARG_MISSING = -5,
MC_UNMATCHED_OPTIONS = -6,
MC_TOO_FEW_CHILDREN_MATCHES = -7,
// parse errors from client's command line
MC_CL_OPTION_UNKNOWN = -101,
MC_CL_PARSE_ERROR = -102,
MC_CL_EXPECTING_ARG = -103,
MC_CL_UNEXPECTED_ARG = -104,
MC_CL_UNTAGGED_ARG_DENIED = -105
};
enum OptionSpecType
{
OST_BeginList,
OST_EndList,
OST_BeginSwitch,
OST_EndSwitch,
OST_BeginListNode,
OST_EndListNode,
OST_BeginSwitchNode,
OST_EndSwitchNode,
OST_Option
};
enum
{
MAX_LONG_NAME_SIZE = 64,
MAX_ARGUMENT_SIZE = 1024
};
struct OptionSpec
{
OptionSpecType optionType;
int int1;
int int2;
char char1;
const char *charp1;
#if 0
// if this node's parent is branch head, this variable is ignored.
// if this node's parent is list head, if node is required, at least one instance of this node must be present.
bool nodeRequired;
// if this node is a list head, this variable is ignored.
// if this node is a branch head, false = 0 or 1 child may be present, true = one child must be present.
bool childrenRequired;
#endif
};
enum ArgumentPolicy
{
AP_None,
AP_Required,
AP_Optional
};
// ----------------------------------------------------------------------
// -TF- clients, don't try to use this, it is here for compiler issues
class Option
{
private:
char shortName;
char *longName;
ArgumentPolicy argumentPolicy;
protected:
// disabled
Option(void);
Option(const Option&);
Option &operator =(const Option&);
private:
Option(char newShortName, const char *newLongName, ArgumentPolicy newArgumentPolicy);
public:
~Option(void);
static bool isOptionNext(const OptionSpec *optionSpec, int optionSpecCount);
static Option *createOption(const OptionSpec **optionSpec, int *optionSpecCount);
char getShortName(void) const;
const char *getLongName(void) const;
ArgumentPolicy getArgumentPolicy(void) const;
MatchCode match(void);
};
// ----------------------------------------------------------------------
class Collection
{
public:
virtual ~Collection(void) = 0;
virtual MatchCode match(void) const = 0;
static bool isCollectionNext(const OptionSpec *optionSpec, int optionSpecCount);
static Collection *createCollection(const OptionSpec **optionSpec, int *optionSpecCount);
};
// ----------------------------------------------------------------------
private:
class List : public Collection
{
friend class Collection;
private:
class Node
{
private:
Option *option;
Collection *collection;
bool multipleIsAllowed;
bool isRequiredNode;
mutable Node *next;
private:
// disabled
Node(void);
Node(const Node&);
Node &operator =(const Node&);
public:
Node(Option *newOption, Collection *newCollection, bool newMultipleIsAllowed, bool newIsRequiredNode);
~Node(void);
const Option *getOption(void) const;
const Collection *getCollection(void) const;
bool getMultipleIsAllowed(void) const;
bool getIsRequiredNode(void) const;
const Node *getNext(void) const;
void setNext(Node *newNext) const;
MatchCode match(void) const;
static bool isNode(const OptionSpec *optionSpec, int optionCount);
static Node *createNode(const OptionSpec **optionSpec, int *optionCount);
};
private:
Node *firstNode;
OP_ListType listType;
int minimumNodeCount;
private:
// disabled
List(void);
List(const List&);
List &operator =(const List&);
private:
List(OP_ListType newListType, Node *newFirstNode);
List(OP_ListType newListType, Node *newFirstNode, int newMinimumNodeCount);
public:
virtual ~List(void);
virtual MatchCode match(void) const;
static bool isListNext(const OptionSpec *optionSpec, int optionCount);
static List *createList(const OptionSpec **optionSpec, int *optionCount);
};
// ----------------------------------------------------------------------
class Switch : public Collection
{
friend class Collection;
private:
class Node
{
private:
Option *option;
Collection *collection;
bool multipleIsAllowed;
mutable Node *next;
private:
// disabled
Node(void);
Node(const Node&);
Node &operator =(const Node&);
public:
Node(Option *newOption, Collection *newCollection, bool newMultipleIsAllowed);
~Node(void);
const Option *getOption(void) const;
const Collection *getCollection(void) const;
bool getMultipleIsAllowed(void) const;
const Node *getNext(void) const;
void setNext(Node *newNext) const;
MatchCode match(void) const;
static bool isNode(const OptionSpec *optionSpec, int optionCount);
static Node *createNode(const OptionSpec **optionSpec, int *optionCount);
};
private:
Node *firstNode;
bool oneNodeIsRequired;
private:
// disabled
Switch(void);
Switch(const Switch&);
Switch &operator =(const Switch&);
private:
Switch(Node *newFirstNode, bool newOneNodeIsRequired);
public:
virtual ~Switch(void);
virtual MatchCode match(void) const;
static bool isSwitchNext(const OptionSpec *optionSpec, int optionCount);
static Switch *createSwitch(const OptionSpec **optionSpec, int *optionCount);
};
// ----------------------------------------------------------------------
class OptionTable
{
public:
class Record
{
private:
enum
{
MAX_OCCURRENCE_COUNT = 128
};
private:
char shortName;
char *longName;
int writeCount;
int matchCount;
char *stringArray[MAX_OCCURRENCE_COUNT];
ArgumentPolicy argumentPolicy;
mutable Record *next;
private:
// disabled
Record(void);
Record(const Record&);
Record &operator =(const Record&);
public:
Record(char newShortName, const char *newLongName, ArgumentPolicy newArgumentPolicy);
~Record(void);
char getShortName(void) const;
const char *getLongName(void) const;
void addOccurrence(const char *newString);
void addMatch(void);
const char *getString(int occurrenceIndex) const;
int getWriteCount(void) const;
int getMatchCount(void) const;
const Record *getNext(void) const;
Record *getNext(void);
void setNext(Record *newNext) const;
ArgumentPolicy getArgumentPolicy(void) const;
};
private:
Record *firstRecord;
private:
// disabled
OptionTable(const OptionTable&);
OptionTable &operator =(const OptionTable&);
public:
OptionTable(void);
~OptionTable(void);
Record *createOptionRecord(char shortName, const char *longName, ArgumentPolicy newArgumentPolicy);
Record *findOptionRecord(char shortName) const;
Record *findOptionRecord(const char *longName) const;
bool getAllOptionsMatched(void) const;
};
// ----------------------------------------------------------------------
class Lexer
{
public:
enum TokenType
{
TT_Error,
TT_End,
TT_DoubleDash,
TT_ShortOption,
TT_LongOption,
TT_Equal,
TT_Argument
};
class Token
{
friend class Lexer;
private:
TokenType tokenType;
char name[MAX_LONG_NAME_SIZE];
char argument[MAX_ARGUMENT_SIZE];
private:
// disabled
Token(const Token&);
Token &operator =(const Token&);
public:
Token(void);
TokenType getTokenType(void) const;
char getShortName(void) const;
const char *getLongName(void);
const char *getArgument(void);
};
// -TF- so Token can see the TokenType enums --- this is making me puke...
friend class Token;
private:
const char *nextCharacter;
private:
// disabled
Lexer(void);
Lexer(const Lexer&);
Lexer &operator =(const Lexer&);
private:
void gobbleWhitespace(void);
bool gobbleString(bool isRequired, char *stringBuffer, int bufferSize);
public:
explicit Lexer(const char *newBuffer);
~Lexer(void);
bool getNextToken(Token *token);
const char *getNextCharacter(void);
};
// ----------------------------------------------------------------------
// needed so that option can access variable optionTable
friend class Option;
private:
static bool installed;
static bool wasParsed;
static char buffer[STATIC_BUFFER_SIZE];
static int bufferSize;
static Collection *treeRoot;
static OptionTable *optionTable;
static int absorbedStringCount;
private:
static bool findNextOccurence(char shortName, int *occurrenceIndex);
static bool findNextOccurence(const char *longName, int *occurrenceIndex);
static bool getOptionArgExists(char shortName, int occurrenceIndex);
static bool getOptionArgExists(const char *longName, int occurrenceIndex);
static void buildOptionTree(const OptionSpec *specList, int specCount);
static MatchCode parseCommandLineBuffer(void);
public:
static void install(void);
static void remove(void);
static void absorbString(const char *newString);
static void absorbStrings(const char **stringArray, int stringCount);
static const char *getPostCommandLineString(void);
static MatchCode parseOptions(const OptionSpec *optionTree, int optionSpecCount);
static bool getOptionExists(char shortName, int occurrenceIndex = 0);
static bool getOptionExists(const char *longName, int occurrenceIndex = 0);
static int getOccurrenceCount(char shortName);
static int getOccurrenceCount(const char *longName);
static const char *getOptionString(char shortName, int occurrenceIndex = 0);
static const char *getOptionString(const char *longName, int occurrenceIndex = 0);
static int getOptionInt(char shortName, int occurrenceIndex = 0);
static int getOptionInt(const char *longName, int occurrenceIndex = 0);
static int getUntaggedOccurrenceCount(void);
static const char *getUntaggedString(int occurrenceIndex = 0);
static int getUntaggedInt(int occurrenceIndex = 0);
};
// ======================================================================
inline char CommandLine::Option::getShortName(void) const
{
return shortName;
}
// ----------------------------------------------------------------------
inline const char *CommandLine::Option::getLongName(void) const
{
return longName;
}
// ----------------------------------------------------------------------
inline CommandLine::ArgumentPolicy CommandLine::Option::getArgumentPolicy(void) const
{
return argumentPolicy;
}
// ======================================================================
inline const CommandLine::Option *CommandLine::List::Node::getOption(void) const
{
return option;
}
// ----------------------------------------------------------------------
inline const CommandLine::Collection *CommandLine::List::Node::getCollection(void) const
{
return collection;
}
// ----------------------------------------------------------------------
inline bool CommandLine::List::Node::getMultipleIsAllowed(void) const
{
return multipleIsAllowed;
}
// ----------------------------------------------------------------------
inline bool CommandLine::List::Node::getIsRequiredNode(void) const
{
return isRequiredNode;
}
// ----------------------------------------------------------------------
inline const CommandLine::List::Node *CommandLine::List::Node::getNext(void) const
{
return next;
}
// ----------------------------------------------------------------------
inline void CommandLine::List::Node::setNext(Node *newNext) const
{
next = newNext;
}
// ======================================================================
inline const CommandLine::Option *CommandLine::Switch::Node::getOption(void) const
{
return option;
}
// ----------------------------------------------------------------------
inline const CommandLine::Collection *CommandLine::Switch::Node::getCollection(void) const
{
return collection;
}
// ----------------------------------------------------------------------
inline bool CommandLine::Switch::Node::getMultipleIsAllowed(void) const
{
return multipleIsAllowed;
}
// ----------------------------------------------------------------------
inline const CommandLine::Switch::Node *CommandLine::Switch::Node::getNext(void) const
{
return next;
}
// ----------------------------------------------------------------------
inline void CommandLine::Switch::Node::setNext(
Node *newNext
) const
{
next = newNext;
}
// ======================================================================
inline char CommandLine::OptionTable::Record::getShortName(void) const
{
return shortName;
}
// ----------------------------------------------------------------------
inline const char *CommandLine::OptionTable::Record::getLongName(void) const
{
return longName;
}
// ----------------------------------------------------------------------
inline void CommandLine::OptionTable::Record::addMatch(void)
{
DEBUG_FATAL(matchCount >= writeCount, ("match overflow"));
++matchCount;
}
// ----------------------------------------------------------------------
inline const char *CommandLine::OptionTable::Record::getString(
int occurrenceIndex
) const
{
DEBUG_FATAL(occurrenceIndex >= writeCount, ("index out of range: val/max %d/%d", occurrenceIndex, writeCount-1));
return stringArray[occurrenceIndex];
}
// ----------------------------------------------------------------------
inline int CommandLine::OptionTable::Record::getWriteCount(void) const
{
return writeCount;
}
// ----------------------------------------------------------------------
inline int CommandLine::OptionTable::Record::getMatchCount(void) const
{
return matchCount;
}
// ----------------------------------------------------------------------
inline const CommandLine::OptionTable::Record *CommandLine::OptionTable::Record::getNext(void) const
{
return next;
}
// ----------------------------------------------------------------------
inline CommandLine::OptionTable::Record *CommandLine::OptionTable::Record::getNext(void)
{
return next;
}
// ----------------------------------------------------------------------
inline void CommandLine::OptionTable::Record::setNext(
Record *newNext
) const
{
next = newNext;
}
// ----------------------------------------------------------------------
inline CommandLine::ArgumentPolicy CommandLine::OptionTable::Record::getArgumentPolicy(void) const
{
return argumentPolicy;
}
// ======================================================================
inline CommandLine::Lexer::TokenType CommandLine::Lexer::Token::getTokenType(void) const
{
return tokenType;
}
// ----------------------------------------------------------------------
inline char CommandLine::Lexer::Token::getShortName(void) const
{
DEBUG_FATAL(tokenType != TT_ShortOption, ("attempted to get short name for token type %d", tokenType));
return name[0];
}
// ----------------------------------------------------------------------
inline const char *CommandLine::Lexer::Token::getLongName(void)
{
DEBUG_FATAL(tokenType != TT_LongOption, ("attempted to get long name for token type %d", tokenType));
return name;
}
// ----------------------------------------------------------------------
inline const char *CommandLine::Lexer::Token::getArgument(void)
{
DEBUG_FATAL(tokenType != TT_Argument, ("attempted to get argument for token type %d", tokenType));
return argument;
}
// ======================================================================
inline const char *CommandLine::Lexer::getNextCharacter(void)
{
return nextCharacter;
}
// ----------------------------------------------------------------------
inline void CommandLine::Lexer::gobbleWhitespace(void)
{
DEBUG_FATAL(!nextCharacter, ("null nextCharacter"));
while (isspace(*nextCharacter))
++nextCharacter;
}
// ----------------------------------------------------------------------
inline int CommandLine::getUntaggedOccurrenceCount(void)
{
return getOccurrenceCount(OP_SNAME_UNTAGGED);
}
// ----------------------------------------------------------------------
inline const char *CommandLine::getUntaggedString(
int occurrenceIndex
)
{
return getOptionString(OP_SNAME_UNTAGGED, occurrenceIndex);
}
// ----------------------------------------------------------------------
inline int CommandLine::getUntaggedInt(
int occurrenceIndex
)
{
return getOptionInt(OP_SNAME_UNTAGGED, occurrenceIndex);
}
// ======================================================================
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,181 @@
// ======================================================================
//
// ConfigFile.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef CONFIG_FILE_H
#define CONFIG_FILE_H
// ======================================================================
class StringCompare;
#include "sharedFoundation/Tag.h"
// ======================================================================
/// Provide access to configuration file paramaters.
class ConfigFile
{
public:
/** Represents a single value of a key/value pair
*
* Stored as a string, but can be cast and returned as an int, bool, and float as well
*/
class Element
{
public:
Element();
explicit Element(const char *entry);
virtual ~Element(void);
Element(const Element&);
Element &operator =(const Element&);
int getAsInt(void) const;
bool getAsBool(void) const;
float getAsFloat(void) const;
const char *getAsString(void) const;
Tag getAsTag(void) const;
private:
/// a buffer holding the entry string, which may be recast to other types
char *m_entry;
};
typedef stdlist<Element *>::fwd ElementList;
// -----------------------------------------------------------------------
///Represents a single key, which may hold multiple ordered Elements as values
class Key
{
public:
Key (const char *name, const char *value, bool lazyAdd = false);
virtual ~Key(void);
const char *getName(void) const;
bool getLazyAdd(void) const;
int getAsInt(int index, int defaultValue) const;
bool getAsBool(int index, bool defaultValue) const;
float getAsFloat(int index, float defaultValue) const;
const char *getAsString(int index, const char *defaultValue) const;
Tag getAsTag(int index, Tag defaultValue) const;
int getCount(void) const;
void addValue(const char *value);
void dump(const char *keyName) const;
private:
/// disabled
Key(void);
/// disabled
Key(const Key&);
/// disabled
Key &operator =(const Key&);
private:
///A list of element values, since are elements are unique and order is important
ElementList *m_elements;
///String representation of the key's name
char* m_name;
/// track whether this was added lazily (not explicitly in the config file)
bool m_lazyAdd;
};
typedef stdmap<const char *, Key *, StringCompare>::fwd KeyMap;
// -----------------------------------------------------------------------
/** A scoping mechanism for keys
*
* All keys exist inside a section, i.e. [Section]
* a = 5
*/
class Section
{
public:
explicit Section (const char *name);
~Section(void);
const char *getName(void) const;
Key *findKey(const char *key) const;
int getKeyInt (const char *key, int index, int defaultValue = 0) const;
bool getKeyBool (const char *key, int index, bool defaultValue = false) const;
float getKeyFloat (const char *key, int index, float defaultValue = 0.f) const;
const char *getKeyString(const char *key, int index, const char *defaultValue = NULL) const;
Tag getKeyTag (const char *key, int index, Tag defaultValue = 0) const;
int getKeyCount(const char *key) const;
void addKey(const char *keyName, const char *value, bool lazyAdd = false);
void removeKey(const char *key);
void dump(void) const;
bool getKeyExists(const char *key) const;
private:
/// disabled
Section(void);
/// disabled
Section(const Section&);
/// disabled
Section &operator =(const Section&);
private:
/** A map of the keys
*
* Use a map for speed, and since keys are unique
*/
KeyMap *m_keys;
///String representation of the section's name
char* m_name;
};
typedef stdmap<const char *, Section *, StringCompare>::fwd SectionMap;
public:
//public interface
static void install(void);
static bool isInstalled(void);
static bool isEmpty();
static Section *getSection(const char *name);
static bool loadFile(char const * fileName);
static bool loadFromBuffer(char const * buffer, int length);
static bool loadFromCommandLine(const char *buffer);
static Section *createSection(const char *name);
static void removeSection(const char *name);
static void dump(void);
//accessors using indexes
static int getKeyInt (const char *section, const char *key, int index, int defaultValue);
static bool getKeyBool (const char *section, const char *key, int index, bool defaultValue);
static float getKeyFloat (const char *section, const char *key, int index, float defaultValue);
static const char *getKeyString(const char *section, const char *key, int index, const char *defaultValue);
static Tag getKeyTag (const char *section, const char *key, int index, Tag defaultValue);
//accessors defaulting to retrieving the last entered value
static DLLEXPORT int getKeyInt (const char *section, const char *key, int defaultValue, bool overrideLazyAdds = false);
static DLLEXPORT bool getKeyBool (const char *section, const char *key, bool defaultValue, bool overrideLazyAdds = false);
static float getKeyFloat (const char *section, const char *key, float defaultValue, bool overrideLazyAdds = false);
static const char *getKeyString(const char *section, const char *key, const char *defaultValue, bool overrideLazyAdds = false);
static Tag getKeyTag (const char *section, const char *key, Tag defaultValue, bool overrideLazyAdds = false);
private:
/// disabled
ConfigFile(void);
/// disabled
ConfigFile(const ConfigFile &);
/// disabled
ConfigFile &operator =(const ConfigFile &);
private:
//private functions
static void processLine(const char *line);
static void processKeys(const char *key);
static void remove(void);
private:
//private data members
static SectionMap *ms_sections;
static Section *ms_currentSection;
static const char *ms_IncludeDelimiter;
static bool ms_installed;
static bool ms_logConfigSettings;
};
// ======================================================================
#endif
@@ -0,0 +1,25 @@
// ======================================================================
//
// ConstCharCrcLowerString.cpp
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/ConstCharCrcLowerString.h"
// ======================================================================
ConstCharCrcLowerString::ConstCharCrcLowerString(const char *string)
: CrcLowerString(string, PersistentCrcString::CC_true)
{
}
// ----------------------------------------------------------------------
ConstCharCrcLowerString::~ConstCharCrcLowerString()
{
}
// ======================================================================
@@ -0,0 +1,27 @@
// ======================================================================
//
// ConstCharCrcLowerString.h
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_ConstCharCrcLowerString_H
#define INCLUDED_ConstCharCrcLowerString_H
// ======================================================================
#include "sharedFoundation/CrcLowerString.h"
// ======================================================================
class ConstCharCrcLowerString : public CrcLowerString
{
public:
ConstCharCrcLowerString(const char *string);
virtual ~ConstCharCrcLowerString();
};
// ======================================================================
#endif
@@ -0,0 +1,76 @@
// ======================================================================
//
// ConstCharCrcString.cpp
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/ConstCharCrcString.h"
// ======================================================================
ConstCharCrcString::ConstCharCrcString(const char *string)
: CrcString(),
m_buffer(string)
{
calculateCrc ();
}
// ----------------------------------------------------------------------
ConstCharCrcString::ConstCharCrcString(const char *string, uint32 crc)
: CrcString(),
m_buffer(string)
{
#ifdef _DEBUG
calculateCrc();
DEBUG_FATAL(m_crc != crc, ("calculated and specified crc values do not match"));
#endif
m_crc = crc;
}
// ----------------------------------------------------------------------
ConstCharCrcString::ConstCharCrcString(ConstCharCrcString const &rhs)
: CrcString(rhs.m_crc),
m_buffer(rhs.m_buffer)
{
}
// ----------------------------------------------------------------------
ConstCharCrcString::~ConstCharCrcString()
{
}
// ----------------------------------------------------------------------
char const * ConstCharCrcString::getString() const
{
return m_buffer;
}
// ----------------------------------------------------------------------
void ConstCharCrcString::clear()
{
DEBUG_FATAL(true, ("cannot clear a ConstCharCrcString"));
}
// ----------------------------------------------------------------------
void ConstCharCrcString::set(char const *, bool)
{
DEBUG_FATAL(true, ("cannot clear a ConstCharCrcString"));
}
// ----------------------------------------------------------------------
void ConstCharCrcString::set(char const *, uint32)
{
DEBUG_FATAL(true, ("cannot clear a ConstCharCrcString"));
}
// ======================================================================
@@ -0,0 +1,45 @@
// ======================================================================
//
// ConstCharCrcString.h
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_ConstCharCrcString_H
#define INCLUDED_ConstCharCrcString_H
// ======================================================================
#include "sharedFoundation/CrcString.h"
// ======================================================================
class ConstCharCrcString : public CrcString
{
public:
ConstCharCrcString(const char *string);
ConstCharCrcString(const char *string, uint32 crc);
ConstCharCrcString(ConstCharCrcString const &);
virtual ~ConstCharCrcString();
virtual char const * getString() const;
virtual void clear();
virtual void set(char const * string, bool applyNormalize);
virtual void set(char const * string, uint32 crc);
private:
ConstCharCrcString();
ConstCharCrcString & operator =(ConstCharCrcString const &);
private:
char const * const m_buffer;
};
// ======================================================================
#endif
@@ -0,0 +1,93 @@
// ======================================================================
//
// CrashReportInformation.cpp
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/CrashReportInformation.h"
#include "sharedFoundation/ExitChain.h"
#include <vector>
#include <algorithm>
// ======================================================================
namespace CrashReportInformationNamespace
{
typedef std::vector<char *> TextVector;
typedef std::vector<char const *> ConstTextVector;
TextVector ms_staticText;
ConstTextVector ms_dynamicText;
}
using namespace CrashReportInformationNamespace;
// ======================================================================
void CrashReportInformation::install()
{
ExitChain::add(&remove, "CrashReportInformation::remove");
}
// ----------------------------------------------------------------------
void CrashReportInformation::remove()
{
while (!ms_staticText.empty())
{
delete [] ms_staticText.back();
ms_staticText.pop_back();
}
ms_dynamicText.clear();
}
// ----------------------------------------------------------------------
void CrashReportInformation::addStaticText(char const * format, ...)
{
va_list va;
va_start(va, format);
char buffer[256];
vsnprintf(buffer, sizeof(buffer), format, va);
ms_staticText.push_back(DuplicateString(buffer));
va_end(va);
}
// ----------------------------------------------------------------------
void CrashReportInformation::addDynamicText(char const * text)
{
ms_dynamicText.push_back(text);
}
// ----------------------------------------------------------------------
void CrashReportInformation::removeDynamicText(char const * text)
{
ConstTextVector::iterator i = std::find(ms_dynamicText.begin(), ms_dynamicText.end(), text);
if (i != ms_dynamicText.end())
ms_dynamicText.erase(i);
}
// ----------------------------------------------------------------------
char const * CrashReportInformation::getEntry(int index)
{
if (index < static_cast<int>(ms_staticText.size()))
return ms_staticText[index];
index -= static_cast<int>(ms_staticText.size());
if (index < static_cast<int>(ms_dynamicText.size()))
return ms_dynamicText[index];
return NULL;
}
// ======================================================================
@@ -0,0 +1,36 @@
// ======================================================================
//
// CrashReportInformation.h
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_CrashReportInformation_H
#define INCLUDED_CrashReportInformation_H
// ======================================================================
class CrashReportInformation
{
public:
static void install();
static void remove();
static DLLEXPORT void addStaticText(char const * format, ...);
static void addDynamicText(char const * text);
static void removeDynamicText(char const * text);
static char const * getEntry(int index);
private:
CrashReportInformation();
CrashReportInformation(CrashReportInformation const &);
CrashReportInformation & operator=(CrashReportInformation const &);
};
// ======================================================================
#endif
@@ -0,0 +1,120 @@
// ======================================================================
//
// Crc.cpp
//
// adapted from Ross Williams' public domain crc code.
//
// Portions copyright 1998 Bootprint Entertainment
// Portions copyright 2002 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/Crc.h"
#include "sharedFoundation/TemporaryCrcString.h"
// ======================================================================
const uint32 Crc::crcNull = Crc::calculate ("");
// ======================================================================
static const uint32 crctable[256] =
{
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD,
0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5,
0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D,
0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA,
0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02,
0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692,
0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A,
0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A,
0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B,
0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623,
0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B,
0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C,
0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24,
0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654,
0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C,
0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C,
0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
};
const uint32 CRC_INIT = 0xFFFFFFFF;
const uint32 Crc::crcInit = CRC_INIT;
// ======================================================================
uint32 Crc::calculate(const char *string)
{
uint32 crc;
if (!string)
return 0;
for (crc = CRC_INIT; *string; ++string)
crc = crctable[((crc>>24) ^ static_cast<byte>(*string)) & 0xFF] ^ (crc << 8);
return (crc ^ CRC_INIT);
}
// ----------------------------------------------------------------------
#if 0
uint32 Crc::calculateWithToLower(const char *string)
{
uint32 crc;
if (!string)
return 0;
for (crc = CRC_INIT; *string; ++string)
crc = crctable[((crc>>24) ^ static_cast<uint32>(tolower(*string))) & 0xFF] ^ (crc << 8);
return (crc ^ CRC_INIT);
}
#endif
// ----------------------------------------------------------------------
uint32 Crc::calculate(const void *data, int length, uint32 initCrc)
{
DEBUG_FATAL(!data, ("null data arg"));
uint32 crc;
const byte *d = reinterpret_cast<const byte *>(data);
for (crc = initCrc; length; --length, ++d)
crc = crctable[((crc>>24) ^ static_cast<uint32>(*d)) & 0xFF] ^ (crc << 8);
return (crc ^ initCrc);
}
// ----------------------------------------------------------------------
uint32 Crc::normalizeAndCalculate(const char *string)
{
return TemporaryCrcString(string, true).getCrc();
}
// ======================================================================
@@ -0,0 +1,35 @@
// ======================================================================
//
// Crc.h
// ala diaz
//
// copyright 1998 Bootprint Entertainment
// copyright 2002 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Crc_H
#define INCLUDED_Crc_H
// ======================================================================
// Functions that return the CRC value of either strings or blocks of data.
class Crc
{
public:
// CRC of the empty string ("")
static const uint32 crcNull;
static const uint32 crcInit;
public:
static uint32 calculate(const char *string);
static uint32 calculate(const void *data, int len, uint32 initCrc = crcInit);
static uint32 normalizeAndCalculate(const char *string);
};
// ======================================================================
#endif
@@ -0,0 +1,224 @@
// ======================================================================
//
// CrcLowerString.cpp
// Portions copyright 1998 Bootprint Entertainment
// Portions copyright 2002 Sony Online Entertainment
// All Rights Reserved
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedFoundation/TemporaryCrcString.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/MemoryBlockManager.h"
// ======================================================================
const CrcLowerString CrcLowerString::empty("", PersistentCrcString::CC_true);
// ======================================================================
MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(CrcLowerString, true, 0, 0, 0);
// ======================================================================
// Compute the CRC for a string
//
// Return value:
//
// The CRC for the specified string
//
// Remarks:
//
// This routine is provided so that other code can calculate the CRC for
// a CrcLowerString without having to create a CrcLowerString, enabling the user
// to call the compare(const char *, uint32) function.
//
// This routine currently simply calls CRC32::calculateWithToLower() on the specified
// string.
uint32 CrcLowerString::calculateCrc(const char *newString)
{
return TemporaryCrcString(newString, true).getCrc();
}
// ======================================================================
/**
* Construct a new CrcLowerString, initialized with empty string.
*
* This function is provided to satisfy the requirements for a
* std::set<CrcLowerString> and related STL containers.
*/
CrcLowerString::CrcLowerString()
: PersistentCrcString()
{
}
// ----------------------------------------------------------------------
// Construct a new CrcLowerString
//
// Remarks:
//
// The constructor will copy its argument into local memory, and then
// call CrcLowerString::calculateCrc() on the string to compute the CRC once.
//
// See Also:
//
// CrcLowerString::calculateCrc()
CrcLowerString::CrcLowerString(const char *newString)
: PersistentCrcString(newString, true)
{
}
// ----------------------------------------------------------------------
/**
* Construct a new CrcLowerString.
*
* The constructor will copy its argument into local memory. It will
* assume that the specified CRC is correct for the string.
*
* @param newString String to generate the CRC String from
* @param newCrc CRC for the string
*/
CrcLowerString::CrcLowerString(const char *newString, uint32 newCrc)
: PersistentCrcString(newString, newCrc)
{
}
// ----------------------------------------------------------------------
/**
* Copy construct a new CrcLowerString from an existing CrcLowerString.
*
* The constructor will copy its argument into local memory.
*
* This function normally would not be present since there shouldn't
* be much need to duplicate a crc-based string. However, the need
* arose to use a CrcLowerString as a key for a std::map, so the
* copy constructor was needed.
*
* @param rhs Existing CrcLowerString to copy
*/
CrcLowerString::CrcLowerString(const CrcLowerString &rhs)
: PersistentCrcString(rhs)
{
}
// ----------------------------------------------------------------------
CrcLowerString::CrcLowerString(const char *newString, PersistentCrcString::ConstChar)
: PersistentCrcString(newString, PersistentCrcString::CC_true)
{
}
// ----------------------------------------------------------------------
/**
* Destroy a CrcLowerString.
*
* This routine will free the resources associated with this CrcLowerString.
*/
CrcLowerString::~CrcLowerString(void)
{
}
// ----------------------------------------------------------------------
/**
* Set the new string for a CrcLowerString.
*
* This routine will delete the old string and reallocate the new string.
* It will also recompute the CRC for the string.
*
* @param newString The new value of the CrcLowerString
*/
void CrcLowerString::setString(const char *newString)
{
set(newString, true);
}
// ----------------------------------------------------------------------
/**
* Compare this CrcLowerString with a string and a CRC.
*
* The return value does not indicate the lexiographic ordering of the
* strings, because they are first compared using the CRC, and only if
* the CRC's match are they compared by strcmp().
*
* @param otherString String to compare against
* @param otherCrc CRC of the string to compare against
* @return See Remarks section
*/
int CrcLowerString::compare(const char *otherString, uint32 otherCrc) const
{
NOT_NULL(otherString);
const uint32 crc = getCrc();
if (crc < otherCrc)
return -1;
if (crc > otherCrc)
return 1;
char const *string = getString();
for (int i = 0; ; ++i)
{
const int a = string[i];
const int b = tolower(otherString[i]);
if (!a || !b || a != b)
{
if (a < b)
return -1;
if (a > b)
return 1;
if (a == b)
return 0;
}
}
}
// ----------------------------------------------------------------------
/**
* Compare this CrcLowerString with another.
*
* The return value does not indicate the lexiographic ordering of the
* strings, because they are first compared using the CRC, and only if
* the CRC's match are they compared by strcmp().
*
* @param otherString CrcLowerString to compare against
* @return See Remarks section
*/
int CrcLowerString::compare(const CrcLowerString &otherString) const
{
return compare(otherString.getString(), otherString.getCrc());
}
// ----------------------------------------------------------------------
/**
*
* Perform an assignment of the CrcLowerString object.
*
* NOTE: use of this function during game runtime likely is an indication
* of a flawed design. This function was added to support tools where
* simplicity overrode efficiency concerns.
*
* @param rhs the source CrcLowerString object to copy into the left-hand-side object
*/
CrcLowerString &CrcLowerString::operator =(const CrcLowerString &rhs)
{
set(rhs.getString(), rhs.getCrc());
return *this;
}
// ======================================================================
@@ -0,0 +1,120 @@
// ======================================================================
//
// CrcLowerString.h
// Portions copyright 1998 Bootprint Entertainment
// Portions copyright 2002 Sony Online Entertainment
// All Rights Reserved
//
// ======================================================================
#ifndef INCLUDED_CrcLowerString_H
#define INCLUDED_CrcLowerString_H
// ======================================================================
#include "sharedFoundation/MemoryBlockManagerMacros.h"
#include "sharedFoundation/PersistentCrcString.h"
class MemoryBlockManager;
// ======================================================================
/**
* The CrcLowerString class is designed to permit faster case-insensitive
* string searching. The strings are first compared using CRC, and then
* compared using a lowercasing strcmp() call only if the CRC's match.
*
* Note that sorting strings by the return value of compare() will not
* sorted lexiographic manner, because the strings are first compared by
* their CRC which does not indicate lexiographic ordering of the strings.
* Even so, CRC strings may still be stored and searched upon by various
* high-performance search algorithms like a binary searches.
*/
class CrcLowerString : public PersistentCrcString
{
MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL;
public:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct LessPtrComparator
{
//-- returns true if a is less than b
bool operator ()(const CrcLowerString * a, const CrcLowerString * b) const;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
* Provide a predicate that compares CrcLowerString instances based on
* the underlying string lexicographical comparison (case sensitive).
*
* The standard CrcLowerString operator < compares efficiently based
* on the Crc value. Typically this is what you want, for presumably
* the user is using CrcLowerString instances to speed up comparisons.
* However, in the case where you want to sort CrcLowerString instances
* based on the lexicographical (ABC) ordering, use this function object.
* Sorts identically to strcmp().
*
* Can be used as a predicate object (functor) in STL routines.
*/
struct LessAbcOrderReferenceComparator
{
bool operator ()(const CrcLowerString &a, const CrcLowerString &b) const;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public:
static uint32 calculateCrc(const char *newString);
public:
CrcLowerString();
explicit CrcLowerString(const char *newString);
CrcLowerString(const char *newString, uint32 newCrc);
CrcLowerString(const CrcLowerString &rhs);
virtual ~CrcLowerString(void);
void setString(const char *newString);
int compare(const char *otherString, uint32 otherCrc) const;
int compare(const CrcLowerString &otherString) const;
CrcLowerString &operator =(const CrcLowerString &rhs);
public:
/**
* A CrcLowerString representation of the empty string (i.e. "").
*/
static const CrcLowerString empty;
protected:
CrcLowerString(const char *newString, PersistentCrcString::ConstChar);
};
// ======================================================================
// class CrcLowerString::LessPtrComparator
// ======================================================================
inline bool CrcLowerString::LessPtrComparator::operator () (const CrcLowerString * a, const CrcLowerString * b) const
{
return *a < *b;
}
// ======================================================================
// class CrcLowerString::LessAbcOrderReferenceComparator
// ======================================================================
inline bool CrcLowerString::LessAbcOrderReferenceComparator::operator ()(const CrcLowerString &a, const CrcLowerString &b) const
{
return (strcmp(a.getString(), b.getString()) < 0);
}
// ======================================================================
#endif
@@ -0,0 +1,157 @@
// ======================================================================
//
// CrcString.cpp
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/CrcString.h"
#include "sharedFoundation/Crc.h"
// ======================================================================
/**
* Normalize a string.
*
* This function will clean up a string. All alpha characters will be
* changed to lower case, all backslashes will be converted to forward
* slashes, all dots following a slash will be removed, and consecutive
* slashes will be converted into a single slash.
*/
void CrcString::normalize(char *output, const char *input)
{
bool previousIsSlash = true;
for ( ; *input; ++input)
{
const char c = *input;
if (c == '\\' || c == '/')
{
if (!previousIsSlash)
{
// convert all backslashes to forward slashes and disallow multiple slashes in a row
*(output++) = '/';
previousIsSlash = true;
}
}
else
if (c == '.')
{
// disallow dots after slashes. this will also handle multiple dots, and slashes following the dots
if (!previousIsSlash)
*(output++) = '.';
}
else
{
// lowercase all other characters
*(output++) = static_cast<char>(tolower(c));
previousIsSlash = false;
}
}
*output = '\0';
}
// ======================================================================
CrcString::CrcString()
: m_crc(Crc::crcNull)
{
}
// ----------------------------------------------------------------------
CrcString::CrcString(uint32 crc)
: m_crc(crc)
{
}
// ----------------------------------------------------------------------
CrcString::~CrcString()
{
}
// ----------------------------------------------------------------------
void CrcString::calculateCrc()
{
m_crc = Crc::calculate(getString());
}
// ----------------------------------------------------------------------
bool CrcString::isEmpty() const
{
const char * const str = getString ();
return !str || str[0] == '\0';
}
// ----------------------------------------------------------------------
void CrcString::set(CrcString const & rhs)
{
if (this == &rhs)
return;
if (rhs.isEmpty())
clear();
else
set(rhs.getString(), rhs.getCrc());
}
// ----------------------------------------------------------------------
bool CrcString::operator ==(CrcString const & rhs) const
{
return !(*this != rhs);
}
// ----------------------------------------------------------------------
bool CrcString::operator !=(CrcString const & rhs) const
{
return m_crc != rhs.m_crc || strcmp(getString(), rhs.getString()) != 0;
}
// ----------------------------------------------------------------------
bool CrcString::operator < (CrcString const & rhs) const
{
if (m_crc < rhs.m_crc)
return true;
if (m_crc > rhs.m_crc)
return false;
return strcmp(getString(), rhs.getString()) < 0;
}
// ----------------------------------------------------------------------
bool CrcString::operator <=(CrcString const & rhs) const
{
return !(*this > rhs);
}
// ----------------------------------------------------------------------
bool CrcString::operator > (CrcString const & rhs) const
{
if (m_crc > rhs.m_crc)
return true;
if (m_crc < rhs.m_crc)
return false;
return strcmp(getString(), rhs.getString()) > 0;
}
// ----------------------------------------------------------------------
bool CrcString::operator >=(CrcString const & rhs) const
{
return !(*this < rhs);
}
// ======================================================================
@@ -0,0 +1,66 @@
// ======================================================================
//
// CrcString.h
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_CrcString_H
#define INCLUDED_CrcString_H
// ======================================================================
class CrcString
{
public:
static void normalize(char *output, const char *input);
public:
virtual ~CrcString();
bool isEmpty() const;
uint32 getCrc() const;
bool operator ==(CrcString const & rhs) const;
bool operator !=(CrcString const & rhs) const;
bool DLLEXPORT operator < (CrcString const & rhs) const;
bool operator <=(CrcString const & rhs) const;
bool operator > (CrcString const & rhs) const;
bool operator >=(CrcString const & rhs) const;
virtual char const * getString() const = 0;
virtual void clear() = 0;
virtual void set(char const * string, bool applyNormalize) = 0;
virtual void set(char const * string, uint32 crc) = 0;
void set(CrcString const & rhs);
protected:
CrcString();
CrcString(uint32 crc);
void calculateCrc();
private:
CrcString & operator =(CrcString const &);
CrcString(CrcString const &);
protected:
uint32 m_crc;
};
// ======================================================================
inline uint32 CrcString::getCrc() const
{
return m_crc;
}
// ======================================================================
#endif
@@ -0,0 +1,195 @@
// ======================================================================
//
// CrcStringTable.cpp
// Copyright 2003, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/CrcStringTable.h"
#include "sharedFile/Iff.h"
#include "sharedFoundation/Crc.h"
#include "sharedFoundation/ConstCharCrcString.h"
#include <vector>
// ======================================================================
namespace CrcStringTableNamespace
{
const Tag TAG_CSTB = TAG(C,S,T,B);
const Tag TAG_CRCT = TAG(C,R,C,T);
const Tag TAG_STNG = TAG(S,T,N,G);
const Tag TAG_STRT = TAG(S,T,R,T);
}
using namespace CrcStringTableNamespace;
// ======================================================================
CrcStringTable::CrcStringTable()
:
m_numberOfEntries(0),
m_crcTable(NULL),
m_stringsOffsetTable(NULL),
m_strings(NULL)
{
}
// ----------------------------------------------------------------------
CrcStringTable::CrcStringTable(char const * fileName)
:
m_numberOfEntries(0),
m_crcTable(NULL),
m_stringsOffsetTable(NULL),
m_strings(NULL)
{
load(fileName);
}
// ----------------------------------------------------------------------
CrcStringTable::~CrcStringTable()
{
delete [] m_crcTable;
delete [] m_stringsOffsetTable;
delete [] m_strings;
}
//----------------------------------------------------------------------
void CrcStringTable::load(char const * fileName)
{
Iff iff;
bool result = iff.open(fileName, true);
if(!result)
{
if(fileName)
DEBUG_WARNING(true, ("Could not load CrcStringTable %s", fileName));
else
DEBUG_WARNING(true, ("Could not load CrcStringTable, NULL file given"));
return;
}
load(iff);
#ifdef _DEBUG
for (int i = 0; i < m_numberOfEntries; ++i)
{
const char *string = m_strings + m_stringsOffsetTable[i];
uint32 crc = Crc::calculate(string);
DEBUG_FATAL(m_crcTable[i] != crc, ("Crcs do not match for %s: %08x %08x", string, m_crcTable[i], crc));
}
#endif
}
// ----------------------------------------------------------------------
void CrcStringTable::load(Iff &iff)
{
iff.enterForm(TAG_CSTB);
switch (iff.getCurrentName())
{
case TAG_0000:
load_0000(iff);
break;
default:
{
char buffer[256];
iff.formatLocation(buffer, sizeof(buffer));
DEBUG_FATAL(true, ("Unknown crc string table version in %s", buffer));
}
break;
}
iff.exitForm(TAG_CSTB);
}
// ----------------------------------------------------------------------
void CrcStringTable::load_0000(Iff &iff)
{
iff.enterForm(TAG_0000);
iff.enterChunk(TAG_DATA);
m_numberOfEntries = iff.read_int32();
iff.exitChunk(TAG_DATA);
iff.enterChunk(TAG_CRCT);
m_crcTable = iff.read_uint32(m_numberOfEntries);
iff.exitChunk(TAG_CRCT);
iff.enterChunk(TAG_STRT);
m_stringsOffsetTable = iff.read_int32(m_numberOfEntries);
iff.exitChunk(TAG_STRT);
iff.enterChunk(TAG_STNG);
m_strings = iff.readRest_char();
iff.exitChunk(TAG_STNG);
for (int i = 0; i < m_numberOfEntries; ++i)
m_crcTable[i] = Crc::calculate(m_strings + m_stringsOffsetTable[i]);
iff.exitForm(TAG_0000);
}
// ----------------------------------------------------------------------
ConstCharCrcString const CrcStringTable::lookUp(const char * string) const
{
return lookUp(Crc::calculate(string));
}
// ----------------------------------------------------------------------
ConstCharCrcString const CrcStringTable::lookUp(uint32 crc) const
{
int low = 0;
int high = m_numberOfEntries - 1;
while (low <= high)
{
int const mid = (low + high) / 2;
uint32 const entry = m_crcTable[mid];
if (crc == entry)
return ConstCharCrcString(m_strings + m_stringsOffsetTable[mid], crc);
else
if (crc > entry)
low = mid + 1;
else
high = mid - 1;
}
return ConstCharCrcString("", 0);
}
// ----------------------------------------------------------------------
void CrcStringTable::getAllStrings(stdvector<const char *>::fwd & strings) const
{
strings.reserve(strings.size() + m_numberOfEntries);
for (int i = 0; i < m_numberOfEntries; ++i)
strings.push_back(m_strings + m_stringsOffsetTable[i]);
}
// ----------------------------------------------------------------------
int CrcStringTable::getNumberOfStrings() const
{
return m_numberOfEntries;
}
// ----------------------------------------------------------------------
ConstCharCrcString const CrcStringTable::getString(int const index) const
{
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getNumberOfStrings());
return ConstCharCrcString(m_strings + m_stringsOffsetTable[index]);
}
// ======================================================================
@@ -0,0 +1,55 @@
// ======================================================================
//
// CrcStringTable.h
// Copyright 2003, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_CrcStringTable_H
#define INCLUDED_CrcStringTable_H
// ======================================================================
class ConstCharCrcString;
class Iff;
// ======================================================================
class CrcStringTable
{
public:
CrcStringTable();
CrcStringTable(const char * fileName);
~CrcStringTable();
void load(const char * fileName);
void load(Iff &iff);
ConstCharCrcString const lookUp(const char * string) const;
ConstCharCrcString const lookUp(uint32 crc) const;
void getAllStrings(stdvector<const char *>::fwd & strings) const;
int getNumberOfStrings() const;
ConstCharCrcString const getString(int index) const;
private:
CrcStringTable(CrcStringTable const &);
CrcStringTable & operator =(CrcStringTable const &);
void load_0000(Iff &iff);
private:
int m_numberOfEntries;
uint32 * m_crcTable;
int32 * m_stringsOffsetTable;
char * m_strings;
};
// ======================================================================
#endif
@@ -0,0 +1,69 @@
// ======================================================================
//
// DataResource.cpp - base class for template and other classes.
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/DataResource.h"
#include "sharedFoundation/PersistentCrcString.h"
// ======================================================================
DataResource::DataResource(const char* const filename) :
m_name(filename, true),
m_referenceCount(0)
{
}
// ----------------------------------------------------------------------
DataResource::~DataResource()
{
}
// ----------------------------------------------------------------------
const char *DataResource::getName() const
{
return m_name.getString();
}
// ----------------------------------------------------------------------
int DataResource::getReferenceCount() const
{
return m_referenceCount;
}
// ----------------------------------------------------------------------
void DataResource::addReference() const
{
++m_referenceCount;
}
// ----------------------------------------------------------------------
void DataResource::releaseReference() const
{
DEBUG_FATAL(m_referenceCount <= 0, ("DataResource::releaseReference - reference count is already 0\n"));
if (m_referenceCount > 0 && --m_referenceCount == 0)
release();
}
// ----------------------------------------------------------------------
void DataResource::preloadAssets () const
{
}
// ----------------------------------------------------------------------
void DataResource::garbageCollect () const
{
}
// ======================================================================
@@ -0,0 +1,62 @@
// ======================================================================
//
// DataResource.h - base class for template and other classes.
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_DataResource_H
#define INCLUDED_DataResource_H
// ======================================================================
#include "sharedFoundation/PersistentCrcString.h"
// ======================================================================
class DataResource
{
public:
explicit DataResource(const char* filename);
virtual ~DataResource() = 0;
const char *getName() const;
const CrcString &getCrcName() const;
int getReferenceCount() const;
virtual void addReference() const;
virtual void releaseReference() const;
virtual void preloadAssets () const;
virtual void garbageCollect () const;
protected:
virtual void release() const = 0;
private:
DataResource ();
DataResource(const DataResource &source);
DataResource &operator =(const DataResource &source);
private:
// resource name
const PersistentCrcString m_name;
// how many times this resource has been loaded
mutable int m_referenceCount;
};
// ----------------------------------------------------------------------
inline const CrcString &DataResource::getCrcName() const
{
return m_name;
}
// ======================================================================
#endif
@@ -0,0 +1,423 @@
//========================================================================
//
// DataResourceList.h - factory method for creating classes derived from
// DataResource.
//
// copyright 2001 Sony Online Entertainment
//
//========================================================================
#ifndef _INCLUDED_DataResourceList_H
#define _INCLUDED_DataResourceList_H
#include "sharedDebug/DataLint.h"
#include "sharedFile/Iff.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include "sharedFoundation/CrcString.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/LessPointerComparator.h"
#include "sharedFoundation/Tag.h"
#include "sharedFoundation/TemporaryCrcString.h"
#include <map>
#include <string>
//========================================================================
// T should be derived from class DataResource
template <typename T>
class DataResourceList
{
public:
// DataResource registration function
typedef T * (*CreateDataResourceFunc)(const std::string & filename);
static void registerTemplate(Tag id, CreateDataResourceFunc createFunc);
// functions to create a new DataResource
static T * fetch(Tag id);
static const T * fetch(Iff & source);
static const T * fetch(const CrcString & filename);
static const T * fetch(const std::string & filename);
static const T * fetch(const char * filename);
static const bool isLoaded(const std::string & fileName);
// function to reload a data resource with new data
static T * reload(Iff & source);
// functions to reassign Tag->DataResource binding
static CreateDataResourceFunc assignBinding(Tag id, CreateDataResourceFunc createFunc);
static CreateDataResourceFunc removeBinding(Tag tag);
static void install(void);
static void remove(void);
// function to delete a DataResource
static void release(const T & dataResource);
static void logLoadedResources(char const * classType);
static void garbageCollect ();
private:
typedef std::map<Tag, CreateDataResourceFunc> CreateDataResourceMap;
static CreateDataResourceMap *ms_bindings;
typedef std::map<const CrcString*, const T*, LessPointerComparator> LoadedDataResourceMap;
static LoadedDataResourceMap *ms_loaded;
private:
// no copying templates
DataResourceList(void);
DataResourceList(const DataResourceList &source);
DataResourceList & operator =(const DataResourceList &source);
};
//----------------------------------------------------------------------
/**
* Sets up the maps to keep track of resources.
*/
template <typename T>
inline void DataResourceList<T>::install()
{
if (ms_bindings == NULL)
{
ms_bindings = new CreateDataResourceMap();
ms_loaded = new LoadedDataResourceMap();
ExitChain::add (remove, "DataResourceList::remove");
}
} // DataResourceList<T>::install
//----------------------------------------------------------------------
/**
* Frees up memory associated with the list, and checks for resources still
* allocated.
*/
template <typename T>
inline void DataResourceList<T>::remove(void)
{
if (ms_loaded != NULL)
{
#ifdef _DEBUG
if (!ms_loaded->empty())
{
DEBUG_REPORT_LOG (true, ("Data resources still allocated:\n"));
for (typename LoadedDataResourceMap::const_iterator i = ms_loaded->begin (); i != ms_loaded->end (); ++i)
{
const T * const dataResource = (*i).second;
const int users = dataResource->getReferenceCount ();
const char* const name = dataResource->getName ();
DEBUG_REPORT_LOG (true, (" %3d %s\n", users, name));
UNREF (users);
UNREF (name);
}
DEBUG_WARNING (true, ("Data resources still allocated"));
return;
}
#endif // _DEBUG
delete ms_loaded;
ms_loaded = NULL;
}
if (ms_bindings != NULL)
{
delete ms_bindings;
ms_bindings = NULL;
}
} // DataResourceList<T>::remove
//----------------------------------------------------------------------
/**
* Maps a template Tag id to a function used to create a template.
*
* @param createFunc template creation function
* @param id id of the template
*/
template <typename T>
inline void DataResourceList<T>::registerTemplate(Tag id,
CreateDataResourceFunc createFunc)
{
if (ms_bindings == NULL)
install();
#ifdef _DEBUG
// Added to help debug
char text[256];
ConvertTagToString(id, text);
#endif // _DEBUG
// check if that id was already registered and print a warning if it was
if (ms_bindings->find(id) != ms_bindings->end())
{
char buffer[5];
ConvertTagToString(id, buffer);
DEBUG_WARNING(true, ("DataResourceList::registerTemplate: re-installing tag %s!", buffer));
}
(*ms_bindings)[id] = createFunc;
} // DataResourceList<T>::registerTemplate
//----------------------------------------------------------------------
/**
* Changes the default tag->create function binding.
*
* @param id the tag to change
* @param createFunc the creation function to associate with the id
*
* @return the old creation function associated with the tag
*/
template <typename T>
inline typename DataResourceList<T>::CreateDataResourceFunc DataResourceList<T>::assignBinding(
Tag id, CreateDataResourceFunc createFunc)
{
NOT_NULL(ms_bindings);
CreateDataResourceFunc oldFunc = (*ms_bindings)[id];
(*ms_bindings)[id] = createFunc;
return oldFunc;
} // DataResourceList<T>::assignBinding
//----------------------------------------------------------------------
/**
* Removes the default tag->create function binding.
*
* @param id the tag to remove
*
* @return the old creation function associated with the tag
*/
template <typename T>
inline typename DataResourceList<T>::CreateDataResourceFunc DataResourceList<T>::removeBinding(
Tag id)
{
NOT_NULL(ms_bindings);
CreateDataResourceFunc oldFunc = (*ms_bindings)[id];
ms_bindings->erase(id);
return oldFunc;
} // DataResourceList<T>::removeBinding
//----------------------------------------------------------------------
template <typename T>
inline const T * DataResourceList<T>::fetch(const std::string & filename)
{
return fetch(TemporaryCrcString(filename.c_str(), true));
} // DataResourceList<T>::fetch(const std::string &)
//----------------------------------------------------------------------
template <typename T>
inline const T * DataResourceList<T>::fetch(const char * filename)
{
return fetch(TemporaryCrcString(filename, true));
} // DataResourceList<T>::fetch(const char *)
//----------------------------------------------------------------------
/**
* Creates a data resource from a registered data resource id. The caller is
* responsible for deleting the data resource.
*
* @param id the iff tag for the data resource
*
* @return the blank data resource
*/
template <class T>
inline T * DataResourceList<T>::fetch(Tag id)
{
NOT_NULL(ms_bindings);
typename CreateDataResourceMap::iterator iter = ms_bindings->find(id);
if (iter == ms_bindings->end())
return NULL;
return (*(*iter).second)("");
} // DataResourceList<T>::fetch(Tag)
//----------------------------------------------------------------------
/**
* Loads a data resource from an iff file/buffer.
*
* @param source iff source to read from
*
* @return the data resource
*/
template <typename T>
inline const T * DataResourceList<T>::fetch(Iff &source)
{
NOT_NULL(ms_bindings);
#ifdef _DEBUG
DataLint::pushAsset(source.getFileName());
#endif // _DEBUG
// read the 1st form; based on the form id, create the template
Tag id = source.getCurrentName();
typename CreateDataResourceMap::iterator createIter = ms_bindings->find(id);
if (createIter == ms_bindings->end())
{
char buffer[5];
ConvertTagToString(id, buffer);
DEBUG_WARNING(true, ("DataResourceList::fetch Iff: trying to fetch resource for unknown tag %s!", buffer));
return NULL;
}
T *newDataResource = (*(*createIter).second)(source.getFileName());
if (newDataResource != NULL)
{
// initialize the data resource
newDataResource->loadFromIff(source);
}
#ifdef _DEBUG
DataLint::popAsset();
#endif // _DEBUG
return newDataResource;
} // DataResourceList<T>::fetch(Iff &)
//----------------------------------------------------------------------
/**
* Loads a data resource from an iff file.
*
* @param filename the file to load from
*
* @return the data resource
*/
template <typename T>
inline const T * DataResourceList<T>::fetch(const CrcString &filename)
{
NOT_NULL(ms_loaded);
// see if we already have loaded the template
typename LoadedDataResourceMap::iterator iter = ms_loaded->find(&filename);
if (iter != ms_loaded->end())
{
(*iter).second->addReference();
return (*iter).second;
}
// load the template
Iff iff;
if (!iff.open(filename.getString(), true))
return NULL;
// put the template in the loaded list
const T * const newDataResource = fetch(iff);
if (newDataResource != NULL)
{
newDataResource->addReference();
ms_loaded->insert(std::make_pair(&newDataResource->getCrcName (), newDataResource));
}
// clean up
iff.close();
return newDataResource;
}
//----------------------------------------------------------------------
/**
* Checks the reference count of a resource, if it is 0, deletes it.
*
* @param dataResource the data resource to release
*/
template <typename T>
inline void DataResourceList<T>::release(const T & dataResource)
{
NOT_NULL(ms_loaded);
if (ms_loaded != NULL && dataResource.getReferenceCount() == 0)
{
typename LoadedDataResourceMap::iterator iter = ms_loaded->find(&dataResource.getCrcName());
if (iter != ms_loaded->end())
{
const T * const temp = (*iter).second;
(*iter).second = NULL;
ms_loaded->erase(iter);
delete temp;
}
}
} // DataResourceList<T>::release
//----------------------------------------------------------------------
/**
* Reloads a data resource from an iff file/buffer.
*
* @param source iff source to read from
*
* @return the data resource
*/
template <typename T>
inline T * DataResourceList<T>::reload(Iff &source)
{
NOT_NULL(ms_loaded);
const TemporaryCrcString sourceCrcString (source.getFileName(), true);
typename LoadedDataResourceMap::iterator iter = ms_loaded->find(&sourceCrcString);
if (iter == ms_loaded->end())
{
DEBUG_WARNING(true, ("DataResourceList::reload: trying to reload unloaded resource %s!", source.getFileName()));
return NULL;
}
T * const dataResource = const_cast<T *>((*iter).second);
if (dataResource != NULL)
{
// initialize the data resource
dataResource->loadFromIff(source);
}
return dataResource;
} // DataResourceList<T>::reload(Iff &)
//-----------------------------------------------------------------------
template<typename T>
inline const bool DataResourceList<T>::isLoaded(const std::string & source)
{
NOT_NULL(ms_loaded);
const TemporaryCrcString sourceCrcString (source.c_str (), true);
typename LoadedDataResourceMap::iterator iter = ms_loaded->find(&sourceCrcString);
return (iter != ms_loaded->end());
}
//-----------------------------------------------------------------------
template<typename T>
void DataResourceList<T>::logLoadedResources(char const * classType)
{
UNREF(classType); //necessary for release build
typename LoadedDataResourceMap::iterator const iterEnd = ms_loaded->end();
DEBUG_REPORT_LOG_PRINT(true, ("Begin log of loaded %s\n", classType));
for (typename LoadedDataResourceMap::iterator iter = ms_loaded->begin(); iter != iterEnd; ++iter)
DEBUG_REPORT_LOG_PRINT(true, (" %d %s\n", iter->second->getReferenceCount(), iter->second->getName()));
DEBUG_REPORT_LOG_PRINT(true, ("End log of loaded %s\n", classType));
}
//----------------------------------------------------------------------
template<typename T>
void DataResourceList<T>::garbageCollect ()
{
typename LoadedDataResourceMap::iterator end = ms_loaded->end ();
typename LoadedDataResourceMap::iterator iter = ms_loaded->begin ();
for (; iter != end; ++iter)
const_cast<T*> (iter->second)->garbageCollect ();
}
//----------------------------------------------------------------------
#endif // _INCLUDED_DataResourceList_H
@@ -0,0 +1,127 @@
// ======================================================================
//
// DebugInfoManager.cpp
// Copyright 2005 Sony Online Entertainment Inc
// All Rights Reserved
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/DebugInfoManager.h"
#include "sharedMath/Transform.h"
#include "sharedMath/Vector.h"
#include "UnicodeUtils.h"
#include <map>
// ======================================================================
namespace DebugInfoManagerNamespace
{
char ms_buffer[256];
Unicode::String const cms_emptyQuotes(Unicode::narrowToWide("\"\""));
}
using namespace DebugInfoManagerNamespace;
// ======================================================================
void DebugInfoManager::addProperty(DebugInfoManager::PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, int const propertyValue)
{
_itoa(propertyValue, ms_buffer, 10);
addProperty(propertyMap, section, propertyName, Unicode::narrowToWide(ms_buffer));
}
// ----------------------------------------------------------------------
void DebugInfoManager::addProperty(DebugInfoManager::PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, float const propertyValue)
{
sprintf(ms_buffer, "%.2f", propertyValue);
addProperty(propertyMap, section, propertyName, Unicode::narrowToWide(ms_buffer));
}
// ----------------------------------------------------------------------
void DebugInfoManager::addProperty(DebugInfoManager::PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, unsigned int const propertyValue)
{
sprintf(ms_buffer, "%u", propertyValue);
addProperty(propertyMap, section, propertyName, Unicode::narrowToWide(ms_buffer));
}
// ----------------------------------------------------------------------
void DebugInfoManager::addProperty(DebugInfoManager::PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, unsigned long const propertyValue)
{
sprintf(ms_buffer, "%lu", propertyValue);
addProperty(propertyMap, section, propertyName, Unicode::narrowToWide(ms_buffer));
}
// ----------------------------------------------------------------------
void DebugInfoManager::addProperty(DebugInfoManager::PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, bool const propertyValue)
{
addProperty(propertyMap, section, propertyName, Unicode::narrowToWide(propertyValue ? "true" : "false"));
}
// ----------------------------------------------------------------------
void DebugInfoManager::addProperty(DebugInfoManager::PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, std::string const & propertyValue)
{
addProperty(propertyMap, section, propertyName, Unicode::narrowToWide(propertyValue));
}
// ----------------------------------------------------------------------
void DebugInfoManager::addProperty(DebugInfoManager::PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, char const * const propertyValue)
{
if(propertyValue)
addProperty(propertyMap, section, propertyName, Unicode::narrowToWide(propertyValue));
else
addProperty(propertyMap, section, propertyName, Unicode::narrowToWide(""));
}
// ----------------------------------------------------------------------
void DebugInfoManager::addProperty(DebugInfoManager::PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, Vector const & propertyValue)
{
sprintf(ms_buffer, "(%.2f, %.2f, %.2f)", propertyValue.x, propertyValue.y, propertyValue.z);
addProperty(propertyMap, section, propertyName, Unicode::narrowToWide(ms_buffer));
}
// ----------------------------------------------------------------------
void DebugInfoManager::addProperty(DebugInfoManager::PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, Transform const & propertyValue)
{
Transform::matrix_t const & matrix = propertyValue.getMatrix();
sprintf(ms_buffer, "\n\t\t[[%.2f, %.2f, %.2f, %.2f]\n\t\t[%.2f, %.2f, %.2f, %.2f]\n\t\t[%.2f, %.2f, %.2f, %.2f]]", matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3], matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3], matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3]);
addProperty(propertyMap, section, propertyName, Unicode::narrowToWide(ms_buffer));
}
// ----------------------------------------------------------------------
void DebugInfoManager::addProperty(DebugInfoManager::PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, Unicode::String const & propertyValue)
{
//okay to create entry if the section doesn't exist;
PropertySection sectionMap = propertyMap[section];
if(sectionMap.find(propertyName) == sectionMap.end())
{
if(!propertyValue.empty())
sectionMap[propertyName] = propertyValue;
else
sectionMap[propertyName] = cms_emptyQuotes;
}
else
{
if(!propertyValue.empty())
sectionMap[propertyName + "_a"] = propertyValue;
else
sectionMap[propertyName + "_a"] = cms_emptyQuotes;
}
propertyMap[section] = sectionMap;
}
// ======================================================================
@@ -0,0 +1,46 @@
// ======================================================================
//
// DebugInfoManager.h
// Copyright 2004 Sony Online Entertainment Inc
// All Rights Reserved
//
// ======================================================================
#ifndef INCLUDED_DebugInfoManager_H
#define INCLUDED_DebugInfoManager_H
// ======================================================================
class Transform;
class Vector;
// ======================================================================
class DebugInfoManager
{
public:
typedef stdmap<std::string, Unicode::String>::fwd PropertySection;
typedef stdmap<std::string, PropertySection>::fwd PropertyMap;
public:
static void addProperty(PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, int propertyValue);
static void addProperty(PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, unsigned int propertyValue);
static void addProperty(PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, unsigned long propertyValue);
static void addProperty(PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, float propertyValue);
static void addProperty(PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, bool propertyValue);
static void addProperty(PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, std::string const & propertyValue);
static void addProperty(PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, char const * propertyValue);
static void addProperty(PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, Transform const & propertyValue);
static void addProperty(PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, Vector const & propertyValue);
static void addProperty(PropertyMap & propertyMap, std::string const & section, std::string const & propertyName, Unicode::String const & propertyValue);
private:
DebugInfoManager();
~DebugInfoManager();
DebugInfoManager(DebugInfoManager const &);
DebugInfoManager & operator=(DebugInfoManager const &);
};
// ======================================================================
#endif
@@ -0,0 +1,271 @@
// ======================================================================
//
// ExitChain.cpp
// copyright 1998 Bootprint Entertainment
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedDebug/DebugFlags.h"
#include "sharedFoundation/PerThreadData.h"
// ======================================================================
#ifdef _DEBUG
bool ExitChain::ms_debugReportFlag;
bool ExitChain::ms_debugLogFlag;
#endif
// ======================================================================
void ExitChain::install()
{
#ifdef _DEBUG
DebugFlags::registerFlag(ms_debugReportFlag, "SharedFoundation", "reportExitChain", &ExitChain::debugReport);
DebugFlags::registerFlag(ms_debugLogFlag, "SharedFoundation", "logExitChain");
#endif
}
// ----------------------------------------------------------------------
void ExitChain::quit()
{
run();
}
// ======================================================================
// Check if the ExitChain is running or not
//
// Return value:
//
// True if ExitChain::quit() or ExitChain::fatal() has been called
//
// Remarks:
//
// If the result is true, the application is terminating.
//
// See Also:
//
// ExitChain::quit(), ExitChain:fatal(), ExitChain::isFataling()
bool ExitChain::isRunning(void)
{
return PerThreadData::getExitChainRunning();
}
// ----------------------------------------------------------------------
/**
* Check if the ExitChain is fataling or not.
*
* If the ExitChain is fataling, minimal cleanup work should be done to restore the users system to a usable
* state. If this routine returns true, ExitChain::isRunning() will also return true.
*
* @return True if the ExitChain::fatal() has been called
* @see ExitChain::isRunning()
*/
bool ExitChain::isFataling(void)
{
return PerThreadData::getExitChainFataling();
}
// ----------------------------------------------------------------------
/**
* Add a function to the ExitChain to be called when the game exits.
*
* The order of the function calls depends on priority and the order in which they are added to the
* ExitChain. See the main ExitChain documentation for more details.
*
* @param function The function to call
* @param debugName Text description of the function (for debugging purposes only)
* @param priority Priority of the function for proper shutdown ordering
* @param critical Flag to indicate the function should be called even when fataling
* @see ExitChain
*/
void ExitChain::add(Function function, const char *debugName, int priority, bool critical)
{
#ifdef _DEBUG
//-- Verify that the entry doesn't already exist in the ExitChain
{
for (Entry * entry = PerThreadData::getExitChainFirstEntry(); entry; entry = entry->next)
{
if (entry->function == function)
{
DEBUG_WARNING(true, ("ExitChain::add: %s is already in the list", debugName));
entry->m_callStack.debugLog();
}
}
}
#endif
Entry *entry, *back, *front;
// create the new ExitChain entry
entry = new Entry;
entry->function = function;
entry->name = debugName;
entry->priority = priority;
entry->critical = critical;
#ifdef _DEBUG
entry->m_callStack.sample();
#endif
// linked list traversal with a back pointer
for (back = NULL, front = PerThreadData::getExitChainFirstEntry(); front && front->priority > priority; back = front, front = front->next)
;
// hook it into the linked list
entry->next = front;
if (back)
back->next = entry;
else
PerThreadData::setExitChainFirstEntry(entry);
}
// ----------------------------------------------------------------------
/**
* Remove a function from the ExitChain.
*
* The ExitChain will automatically remove a function from the ExitChain when it calls the function, so an
* exit function should not attempt to remove itself from the ExitChain.
*
* Calling this routine with a NULL pointer will cause this routine to call Fatal in debug compilations.
*
* Calling this routine with a function that is not on the ExitChain will cause this routine to call
* Fatal in debug compilations.
*
* @param function The function to remove from the ExitChain list
*/
void ExitChain::remove(Function function)
{
Entry *back, *front;
if (function == NULL)
{
DEBUG_FATAL(true, ("ExitChain::remove NULL function"));
return; //lint !e527 // Warning -- Unreachable
}
// linked list traversal with a back pointer
for (back = NULL, front = PerThreadData::getExitChainFirstEntry(); front && front->function != function; back = front, front = front->next)
;
// make sure it was found
if (!front)
{
DEBUG_FATAL(true, ("ExitChain::remove function not found %p", function));
return; //lint !e527 // Warning -- Unreachable
}
// remove from the linked list
if (back)
back->next = front->next;
else
PerThreadData::setExitChainFirstEntry(front->next);
// free the memory associated with this entry
delete front;
}
// ----------------------------------------------------------------------
/**
* Process the exit chain.
*
* This routine is protected against re-entry so that the ExitChain routines can call Fatal and behave
* properly.
*
* @see Fatal()
*/
void ExitChain::run(void)
{
Entry *entry;
if (isRunning())
return;
PerThreadData::setExitChainRunning(true);
while ((entry = PerThreadData::getExitChainFirstEntry()) != NULL)
{
// remove the first entry off the ExitChain
PerThreadData::setExitChainFirstEntry(entry->next);
// call the function if it's critical or we're not fataling
if (entry->critical || !isFataling())
{
DEBUG_REPORT_LOG_PRINT(ms_debugLogFlag, ("ExitChain::run >> %s\n", entry->name));
DEBUG_OUTPUT_CHANNEL("Foundation\\Exitchain", ("ExitChain::run >> %s\n", entry->name));
entry->function();
DEBUG_REPORT_LOG_PRINT(ms_debugLogFlag, ("ExitChain::run << %s\n", entry->name));
DEBUG_OUTPUT_CHANNEL("Foundation\\Exitchain", ("ExitChain::run << %s\n", entry->name));
}
// free the memory if we're not fataling
if (!isFataling())
delete entry;
}
}
// ----------------------------------------------------------------------
/**
* Clean up the game due to an abnormal condition.
*
* This routine should only be called by Fatal(). It is not intended for any other use.
*
* @see ExitChain::quit(), Fatal()
*/
void ExitChain::fatal(void)
{
if (PerThreadData::isThreadInstalled())
{
PerThreadData::setExitChainFataling(true);
run();
}
}
// ----------------------------------------------------------------------
/**
* Dump the contents of the ExitChain to the DebugMonitor.
*
* This routine is for debugging only.
*
* @param logMessage Log to the debugger as well
*/
void ExitChain::debugReport(bool logMessage)
{
UNREF(logMessage);
#ifdef _DEBUG
DEBUG_OUTPUT_STATIC_VIEW_BEGINFRAME("Foundation\\Exitchain");
for (Entry *entry = PerThreadData::getExitChainFirstEntry(); entry; entry = entry->next)
{
DEBUG_REPORT(true, Report::RF_print | (logMessage ? Report::RF_log : 0), ("%4d=pri %d=crit %p=func %s\n", entry->priority, static_cast<int>(entry->critical), entry->function, entry->name));
DEBUG_OUTPUT_STATIC_VIEW("Foundation\\Exitchain", ("%4d=pri %d=crit %p=func %s\n", entry->priority, static_cast<int>(entry->critical), entry->function, entry->name));
}
DEBUG_OUTPUT_STATIC_VIEW_ENDFRAME("Foundation\\Exitchain");
#endif
}
// ----------------------------------------------------------------------
/**
* Dump the contents of the ExitChain to the DebugMonitor.
*
* This routine is for debugging only.
*/
void ExitChain::debugReport()
{
debugReport(false);
}
// ======================================================================
@@ -0,0 +1,84 @@
// ======================================================================
//
// ExitChain.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// Maintains a list of functions to call at game exit time for cleanup.
//
// Functions are first in order of priority, with the higher interger priority functions being called
// first. For functions with the same priority, they are called in the opposite order that they were
// added to the ExitChain, in a last-in-first-out (LIFO) manner.
//
// When the ExitChain is running because fatal() was called, only the entries that have their critical flag
// set true will be called.
//
// ======================================================================
#ifndef EXIT_CHAIN_H
#define EXIT_CHAIN_H
// ======================================================================
#include "sharedDebug/CallStack.h"
// ======================================================================
class ExitChain
{
public:
typedef void (*Function)(void);
struct Entry
{
Entry *next;
Function function;
const char *name;
int priority;
bool critical;
#ifdef _DEBUG
CallStack m_callStack;
#endif
};
protected:
// disabled
ExitChain(void);
ExitChain(const ExitChain &);
ExitChain &operator =(const ExitChain &);
private:
static void run(void);
private:
#ifdef _DEBUG
static bool ms_debugReportFlag;
static bool ms_debugLogFlag;
#endif
public:
static void install();
static void quit();
static void fatal();
static void add(Function function, const char *debugName, int priority=0, bool critical=false);
static void remove(Function function);
static bool isRunning(void);
static DLLEXPORT bool isFataling(void);
static void debugReport();
static void debugReport(bool log);
};
// ======================================================================
#endif
@@ -0,0 +1,382 @@
// ======================================================================
//
// Fatal.cpp
// copyright 1998 Bootprint Entertainment
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/Fatal.h"
#include "sharedDebug/DataLint.h"
#include "sharedDebug/DebugHelp.h"
#include "sharedDebug/PixCounter.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include "sharedFoundation/Crc.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/PerThreadData.h"
#include "sharedFoundation/SetupSharedFoundation.h"
#include "sharedSynchronization/Mutex.h"
#include <cstdio>
#include <string>
// ======================================================================
namespace FatalNamespace
{
Mutex ms_criticalSection;
char ms_buffer[32 * 1024];
bool ms_throwExceptions;
int ms_numberOfWarnings = 0;
bool ms_strict = false;
WarningCallback s_warningCallback = NULL;
#if PRODUCTION == 0
PixCounter::ResetInteger ms_numberOfWarningsThisFrame;
#endif
}
using namespace FatalNamespace;
// ======================================================================
void FatalInstall()
{
#if PRODUCTION == 0
ms_numberOfWarningsThisFrame.bindToCounter("Warnings");
#endif
}
// ======================================================================
static void formatMessage(char *buffer, int bufferLength, int stackDepth, const char *type, const char *format, va_list va)
{
const int callStackOffset = 4;
const int maxStackDepth = 64;
if (stackDepth > maxStackDepth)
stackDepth = maxStackDepth;
// look up the call stack information
const int callStackSize = callStackOffset + stackDepth;
uint32 callStack[callStackOffset + maxStackDepth];
// allow complete disable of the call stack lookup
if (stackDepth < 0)
memset(callStack, 0, sizeof(callStack));
else
DebugHelp::getCallStack(callStack, callStackOffset + stackDepth);
// make sure the buffer is always null terminated
buffer[--bufferLength] = '\0';
// look up the caller's file and line
if (callStack[callStackOffset])
{
char lib[4 * 1024] = { '\0' };
char file[4 * 1024] = { '\0' };
int line = 0;
if (ConfigSharedFoundation::getLookUpCallStackNames() && DebugHelp::lookupAddress(callStack[callStackOffset], lib, file, sizeof(file), line))
snprintf(buffer, bufferLength, "%s(%d) : %s %08x: ", file, line, type, static_cast<int>(Crc::calculate(format)));
else
snprintf(buffer, bufferLength, "unknown(0x%08X) : %s %08x: ", static_cast<int>(callStack[callStackOffset]), type, static_cast<int>(Crc::calculate(format)));
}
else
{
snprintf(buffer, bufferLength, "unknown location : %s %08x: ", type, static_cast<int>(Crc::calculate(format)));
}
{
const int length = strlen(buffer);
buffer += length;
bufferLength -= length;
}
// add the user message
vsnprintf(buffer, bufferLength, format, va);
{
const int length = strlen(buffer);
buffer += length;
bufferLength -= length;
}
// add the newline
if (bufferLength)
{
*buffer = '\n';
++buffer;
--bufferLength;
*buffer = '\0';
}
if (stackDepth >= 0)
{
// add the call stack
for (int i = callStackOffset+1; i < callStackSize; ++i)
if (callStack[i])
{
char lib[1024];
char file[1024];
int line = 0;
if (ConfigSharedFoundation::getLookUpCallStackNames() && DebugHelp::lookupAddress(callStack[i], lib, file, sizeof(file), line))
snprintf(buffer, bufferLength, " %s(%d) : caller %d\n", file, line, i-callStackOffset);
else
snprintf(buffer, bufferLength, " unknown(0x%08X) : caller %d\n", static_cast<int>(callStack[i]), i-callStackOffset);
const int length = strlen(buffer);
buffer += length;
bufferLength -= length;
}
}
if (bufferLength == 0)
{
buffer[-2] = '+';
buffer[-1] = '\n';
}
}
// ----------------------------------------------------------------------
/**
* Terminate the game due to an abnormal condition.
*
* This routine does not return.
*
* This routine will call ExitChain::fatal() to clean up the system as appropriate.
*
* @param format printf-style formatting string
* @see PreFatal()
*/
static void InternalFatal(const char *format, va_list va)
{
// if the per-thread-data isn't installed, then we know we're single-threaded and can use the static buffer
ms_criticalSection.enter();
const int bufferSize = sizeof(ms_buffer);
const int length = strlen(ms_buffer);
formatMessage(ms_buffer+length, bufferSize-length, ConfigSharedFoundation::getFatalCallStackDepth(), "FATAL", format, va);
ms_criticalSection.leave();
REPORT(true, Report::RF_print | Report::RF_log | Report::RF_fatal, ("%s", ms_buffer));
IGNORE_RETURN(Os::copyTextToClipboard(ms_buffer));
if (ms_throwExceptions)
throw FatalException(ms_buffer, FatalException::ZeroSourceString); //lint !e1549 // Function not declared to throw
#ifdef _WIN32
{
__asm int 3;
}
#endif
DEBUG_OUTPUT_CHANNEL("Foundation\\Fatal", ("%s", ms_buffer));
ExitChain::fatal();
REPORT(true, Report::RF_fatal | Report::RF_dialog, ("%s", ms_buffer));
Os::abort();
}
// ----------------------------------------------------------------------
static void InternalWarning(const char *format, int extraFlags, va_list va, int stackDepth = ConfigSharedFoundation::getWarningCallStackDepth())
{
#if PRODUCTION == 0
++ms_numberOfWarningsThisFrame;
#endif
char buffer[4 * 1024];
if (NULL != s_warningCallback)
{
strcpy(buffer, "WARNING: ");
vsnprintf(buffer + 9, sizeof(buffer) - 9, format, va);
strcat(buffer, "\n");
s_warningCallback(buffer);
}
formatMessage(buffer, sizeof(buffer), stackDepth, "WARNING", format, va);
#ifdef _DEBUG
if (DataLint::isInstalled())
{
DataLint::logWarning(buffer);
return;
}
#endif
++ms_numberOfWarnings;
REPORT(true, Report::RF_print | Report::RF_log | Report::RF_warning | extraFlags, ("%s", buffer));
DEBUG_OUTPUT_CHANNEL("Foundation\\Warning", ("%s", buffer));
}
//----------------------------------------------------------------------
void SetWarningCallback(WarningCallback warningCallback)
{
s_warningCallback = warningCallback;
}
// ======================================================================
FatalException::FatalException(char *newMessage, Zero zero)
: message(DuplicateString(newMessage))
{
UNREF(zero);
if (newMessage)
newMessage[0] = '\0';
}
// ----------------------------------------------------------------------
FatalException::FatalException(const FatalException &fatalException)
: message(DuplicateString(fatalException.message))
{
}
// ----------------------------------------------------------------------
FatalException::~FatalException(void)
{
delete [] message;
}
// ----------------------------------------------------------------------
FatalException &FatalException::operator =(const FatalException &fatalException)
{
if (&fatalException != this)
{
delete [] message;
message = DuplicateString(fatalException.message);
}
return *this;
}
// ----------------------------------------------------------------------
const char *FatalException::getMessage(void) const
{
return message;
}
// ======================================================================
void FatalSetVersionString(const char *string)
{
strcat(ms_buffer, string);
}
// ----------------------------------------------------------------------
void FatalSetThrowExceptions(bool throwExceptions)
{
ms_throwExceptions = throwExceptions;
}
// ----------------------------------------------------------------------
int GetNumberOfWarnings()
{
return ms_numberOfWarnings;
}
// ----------------------------------------------------------------------
void Fatal(const char *format, ...)
{
va_list va;
va_start(va, format);
InternalFatal(format, va);
va_end(va);
}
// ----------------------------------------------------------------------
#ifdef _DEBUG
void DebugFatal(const char *format, ...)
{
va_list va;
va_start(va, format);
InternalFatal(format, va);
va_end(va);
}
#endif
// ----------------------------------------------------------------------
void Warning(const char *format, ...)
{
va_list va;
va_start(va, format);
InternalWarning(format, 0, va);
va_end(va);
}
// ----------------------------------------------------------------------
void WarningStackDepth(int stackDepth, const char *format, ...)
{
va_list va;
va_start(va, format);
InternalWarning(format, 0, va, stackDepth);
va_end(va);
}
// ----------------------------------------------------------------------
void ConsoleWarning(const char *format, ...)
{
va_list va;
va_start(va, format);
InternalWarning(format, Report::RF_console, va);
va_end(va);
}
// ----------------------------------------------------------------------
void SetWarningStrictFatal(bool strict)
{
ms_strict = strict;
}
// ----------------------------------------------------------------------
bool GetWarningStrictFatal()
{
return ms_strict;
}
// ----------------------------------------------------------------------
void WarningStrictFatal(const char *format, ...)
{
va_list va;
va_start(va, format);
if (ms_strict)
InternalFatal(format, va);
else
InternalWarning(format, 0, va);
va_end(va);
}
// ======================================================================
@@ -0,0 +1,162 @@
// ======================================================================
//
// Fatal.h
// copyright 1998 Bootprint Entertainment
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Fatal_H
#define INCLUDED_Fatal_H
// ======================================================================
void FatalInstall();
void FatalSetVersionString(const char *string);
void FatalSetThrowExceptions(bool throwExceptions);
DLLEXPORT void Fatal(const char *format, ...);
DLLEXPORT void DebugFatal(const char *format, ...);
int GetNumberOfWarnings(void);
DLLEXPORT void Warning(const char *format, ...);
DLLEXPORT void WarningStackDepth(int stackDepth, const char *format, ...);
DLLEXPORT void ConsoleWarning(const char *format, ...);
void SetWarningStrictFatal(bool fatal);
bool GetWarningStrictFatal();
DLLEXPORT void WarningStrictFatal(const char *format, ...);
typedef void (*WarningCallback) (char const * const);
void SetWarningCallback(WarningCallback);
// ======================================================================
#define FATAL(a, b) ((a) ? Fatal b : NOP)
#ifdef _DEBUG
#define DEBUG_FATAL(a, b) ((a) ? DebugFatal b : NOP)
#else
#define DEBUG_FATAL(a, b) NOP
#endif
#define WARNING(a, b) ((a) ? Warning b : NOP)
#define WARNING_STACK_DEPTH(a, b) ((a) ? WarningStackDepth b : NOP)
#ifdef _DEBUG
#define DEBUG_WARNING(a, b) WARNING(a, b)
#else
#define DEBUG_WARNING(a, b) NOP
#endif
#define CONSOLE_WARNING(a, b) ((a) ? ConsoleWarning b : NOP)
#ifdef _DEBUG
#define DEBUG_CONSOLE_WARNING(a, b) CONSOLE_WARNING(a, b)
#else
#define DEBUG_CONSOLE_WARNING(a, b) NOP
#endif
#ifdef _DEBUG
#define WARNING_DEBUG_FATAL(a, b) DEBUG_FATAL(a, b)
#else
#define WARNING_DEBUG_FATAL(a, b) WARNING(a, b)
#endif
#define WARNING_STRICT_FATAL(a, b) ((a) ? WarningStrictFatal b : NOP)
#ifdef _DEBUG
template <class T>
inline T *NonNull(T *pointer, const char *name)
{
FATAL(!pointer, ("%s pointer is null", name));
return pointer;
}
#define NON_NULL(a) NonNull(a, #a)
#define NOT_NULL(a) FATAL(!a, ("%s pointer is null", #a))
// FATAL if the specified pointer is not NULL (i.e. assert that the pointer is null, the opposite of NOT_NULL).
#define IS_NULL(a) FATAL(a, ("%s pointer is not null, unexpected.", #a))
#else
#define NON_NULL(a) (a)
#define NOT_NULL(a) UNREF(a)
#define IS_NULL(a) UNREF(a)
#endif
// ======================================================================
/**
* Fatal if the specified var does not satisfy (low <= var < high).
*
* The parameter types must be integral and must be convertable to
* an int.
*/
template <class T>
inline void ValidateRangeInclusiveExclusive(const T &low, const T &var, const T &high, const char *varName)
{
FATAL(low > high, ("range check low [%d] > high [%d]", static_cast<int>(low), static_cast<int>(high)));
FATAL( (var < low) || (var >= high), ("%s [%d] out of valid range [%d..%d)", varName, static_cast<int>(var), static_cast<int>(low), static_cast<int>(high)));
}
#ifdef _DEBUG
#define VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(low, var, high) ValidateRangeInclusiveExclusive(low, var, high, #var)
#else
#define VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(low, var, high) NOP
#endif
// ======================================================================
/**
* Fatal if the specified var does not satisfy (low <= var <= high).
*
* The parameter types must be integral and must be convertable to
* an int.
*/
template <class T>
inline void ValidateRangeInclusiveInclusive(const T &low, const T &var, const T &high, const char *varName)
{
FATAL(low > high, ("range check low [%d] > high [%d]", static_cast<int>(low), static_cast<int>(high)));
FATAL( (var < low) || (var > high), ("%s [%d] out of valid range [%d..%d]", varName, static_cast<int>(var), static_cast<int>(low), static_cast<int>(high)));
}
#ifdef _DEBUG
#define VALIDATE_RANGE_INCLUSIVE_INCLUSIVE(low, var, high) ValidateRangeInclusiveInclusive(low, var, high, #var)
#else
#define VALIDATE_RANGE_INCLUSIVE_INCLUSIVE(low, var, high) NOP
#endif
// ======================================================================
class FatalException
{
public:
enum Zero
{
ZeroSourceString
};
private:
char *message;
public:
FatalException(char *newMessage, Zero zero);
FatalException(const FatalException &fatalException);
~FatalException(void);
FatalException &operator =(const FatalException &fatalException);
const char *getMessage(void) const;
};
struct _EXCEPTION_POINTERS;
// ======================================================================
#endif
@@ -0,0 +1,86 @@
// ======================================================================
//
// FirstSharedFoundation.h
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_FirstSharedFoundation_H
#define INCLUDED_FirstSharedFoundation_H
// ======================================================================
// Set the different build debug levels
#define DEBUG_LEVEL_RELEASE 0
#define DEBUG_LEVEL_OPTIMIZED 1
#define DEBUG_LEVEL_DEBUG 2
#define _CRT_SECURE_NO_DEPRECATE 1
#ifndef DEBUG_LEVEL
#ifdef _DEBUG
#define DEBUG_LEVEL DEBUG_LEVEL_DEBUG
#else
#define DEBUG_LEVEL DEBUG_LEVEL_RELEASE
#endif
#endif
#if (DEBUG_LEVEL != DEBUG_LEVEL_RELEASE) && (DEBUG_LEVEL != DEBUG_LEVEL_OPTIMIZED) && (DEBUG_LEVEL != DEBUG_LEVEL_DEBUG)
#error DEBUG_LEVEL is not valid
#endif
// ======================================================================
// things we really have to have
#include "sharedFoundationTypes/FoundationTypes.h"
#include "sharedFoundation/FirstPlatform.h"
#include "sharedMemoryManager/MemoryManager.h"
// ======================================================================
#include <cfloat>
// ======================================================================
// deprecated stuff that should eventually go away
typedef float real;
#define CONST_REAL(a) static_cast<float>(a)
#define RECIP(a) (1.0f / (a))
const float REAL_MIN = FLT_MIN;
const float REAL_MAX = FLT_MAX;
// ======================================================================
#ifndef NULL
#define NULL 0
#endif
// @todo codereorg
#ifndef MAX_PATH
#define MAX_PATH 260
#endif
// ======================================================================
// things that are useful just about everywhere
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "sharedFoundation/MacroFoundation.h"
#include "sharedFoundation/Binary.h"
#include "sharedFoundation/Fatal.h"
#include "sharedFoundation/StlForwardDeclaration.h"
#include "sharedFoundation/Misc.h"
#include "sharedDebug/RemoteDebug.h"
#include "sharedDebug/Report.h"
#include "sharedFoundation/FloatMath.h"
#include "sharedFoundation/SafeCast.h"
// ======================================================================
#endif
@@ -0,0 +1,167 @@
// ======================================================================
//
// FloatMath.h
// Portions Copyright 1998 Bootprint Entertainment
// Portions Copyright 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_FloatMath_H
#define INCLUDED_FloatMath_H
// ======================================================================
float const PI = 3.14159265358979323846f;
float const PI_TIMES_2 = PI * 2.0f;
float const PI_OVER_2 = PI / 2.0f;
float const PI_OVER_3 = PI / 3.0f;
float const PI_OVER_4 = PI / 4.0f;
float const PI_OVER_6 = PI / 6.0f;
float const PI_OVER_8 = PI / 8.0f;
float const PI_OVER_12 = PI / 12.0f;
float const PI_OVER_16 = PI / 16.0f;
float const PI_OVER_180 = PI / 180.0f;
float const E = 2.7182818284590452f;
// ======================================================================
#ifdef PLATFORM_WIN32
#if _MSC_VER < 1300
inline float abs(float f)
{
return fabsf(f);
}
inline float sqrt(float f)
{
return sqrtf(f);
}
inline float sin(float f)
{
return sinf(f);
}
inline float cos(float f)
{
return cosf(f);
}
inline float tan(float f)
{
return tanf(f);
}
inline float asin(float f)
{
return asinf(f);
}
inline float acos(float f)
{
return acosf(f);
}
inline float atan2(float y, float x)
{
return atan2f(y, x);
}
inline float pow(float x, float y)
{
return powf(x, y);
}
#endif // _MSC_VER < 1300
#else
// @todo check standard, if cmath.h will not be deprecated,
// include cmath.h here and get rid of the redundant inlines.
#include <cmath>
#ifndef LINUX
// The Linux setup defines this in PlatformGlue.h
inline float abs(float f)
{
return std::abs(f);
}
#endif
inline float sqrt(float f)
{
return std::sqrt(f);
}
inline float sin(float f)
{
return std::sin(f);
}
inline float cos(float f)
{
return std::cos(f);
}
inline float tan(float f)
{
return std::tan(f);
}
inline float asin(float f)
{
return std::asin(f);
}
inline float acos(float f)
{
return std::acos(f);
}
inline float atan2(float y, float x)
{
return std::atan2(y, x);
}
inline float pow(float x, float y)
{
return std::pow(x, y);
}
#endif
// ======================================================================
inline float convertDegreesToRadians (real degrees)
{
return degrees * PI / 180.0f;
}
inline float convertRadiansToDegrees (real radians)
{
return radians * 180.0f / PI;
}
inline float cot(float f)
{
return RECIP(tanf(f));
}
inline float GaussianDistribution(float variate, float standardDeviation, float mean)
{
// equation from http://mathworld.wolfram.com/NormalDistribution.html
return (1.0f / (standardDeviation * sqrt(2.0f * PI))) * pow(E, -(sqr(variate - mean) / (2.0f * sqr(standardDeviation))));
}
inline float withinEpsilon(float const rhs, float const lhs, float const epsilon = 1.0e-3f)
{
return ((lhs - epsilon) <= rhs) && (rhs <= (lhs + epsilon));
}
// ======================================================================
#endif
@@ -0,0 +1,83 @@
// ======================================================================
//
// FormattedString.h
// Copyright 2004 Sony Online Entertainment, Inc.
//
// ======================================================================
#ifndef INCLUDED_FormattedString_H
#define INCLUDED_FormattedString_H
// ----------------------------------------------------------------------
template <int bufferSize>
class FormattedString
{
public:
FormattedString();
char const * sprintf(char const * format, ...);
char const * vsprintf(char const * format, va_list const & va);
private:
char m_text[bufferSize];
// Disabled
FormattedString(FormattedString const &);
FormattedString & operator =(FormattedString const &);
};
// ----------------------------------------------------------------------
template <int bufferSize>
inline FormattedString<bufferSize>::FormattedString()
{
m_text[0] = '\0';
}
//-----------------------------------------------------------------------------
template <int bufferSize>
inline char const * FormattedString<bufferSize>::sprintf(char const * const format, ...)
{
char const * result = NULL;
va_list va;
va_start(va, format);
{
result = vsprintf(format, va);
}
va_end(va);
return result;
}
// ----------------------------------------------------------------------
template <int bufferSize>
inline char const * FormattedString<bufferSize>::vsprintf(char const * const format, va_list const & va)
{
// Format the string
int const lastIndex = sizeof(m_text) - 1;
int const charactersWritten = vsnprintf(m_text, lastIndex, format, va);
// vsnprintf returns the number of characters written, not including
// the terminating null character, or a negative value if an output error occurs.
// If the number of characters to write exceeds count, then count characters are
// written and -1 is returned.
// Handle overflow
if ( (charactersWritten == lastIndex)
|| (charactersWritten == -1))
{
m_text[lastIndex - 1] = '+';
m_text[lastIndex] = '\0';
}
return m_text;
}
#endif // INCLUDED_FormattedString_H
// ======================================================================
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,42 @@
//
// GameControllerMessage.h
// asommers 2-24-99
//
// copyright 1999, bootprint entertainment
//
// data files should be including GameControllerMessage.def
// code files should be including GameControllerMessage.h
#ifndef GAMECONTROLLERMESSAGE_H
#define GAMECONTROLLERMESSAGE_H
namespace GameControllerMessageFlags
{
const uint32 NONE = 0x00000000;
const uint32 SEND = 0x00000001; // send should always be combined with one of the dest flags below
const uint32 RELIABLE = 0x00000002;
const uint32 SOURCE_REMOTE_SERVER = 0x00000004;
const uint32 DEST_AUTH_CLIENT = 0x00000008;
const uint32 DEST_PROXY_CLIENT = 0x00000010;
const uint32 DEST_AUTH_SERVER = 0x00000020;
const uint32 DEST_PROXY_SERVER = 0x00000040;
const uint32 DEST_SERVER = 0x00000080;
const uint32 SOURCE_REMOTE_CLIENT = 0x00000100;
const uint32 DEST_ALL_CLIENT = DEST_AUTH_CLIENT | DEST_PROXY_CLIENT;
const uint32 DEST_ALL_SERVER = DEST_AUTH_SERVER | DEST_PROXY_SERVER;
const uint32 DEST_ALL = DEST_ALL_CLIENT | DEST_ALL_SERVER;
const uint32 SOURCE_REMOTE = SOURCE_REMOTE_SERVER | SOURCE_REMOTE_CLIENT;
//@todo remove DESTINATIONS and DEST_SERVER
const uint32 DESTINATIONS = DEST_AUTH_CLIENT |
DEST_PROXY_CLIENT |
DEST_AUTH_SERVER |
DEST_PROXY_SERVER |
DEST_SERVER;
}
#include "sharedFoundation/GameControllerMessage.def"
#endif
@@ -0,0 +1,132 @@
// ======================================================================
//
// LabelHash.cpp
//
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/LabelHash.h"
#include <map>
#include <string>
#include "sharedFoundation/Crc.h"
typedef std::map< uint32, std::string > THashToStringMap;
typedef THashToStringMap::value_type THashEntry;
typedef std::map< std::string, THashToStringMap > TDomainMap;
typedef TDomainMap::value_type TDomainEntry;
TDomainMap gs_allDomains;
void LabelHash::addLabel ( char const * const domain, char const * const label )
{
uint32 actualHash = Crc::calculate(label);
checkLabel(domain,label,actualHash);
}
uint32 LabelHash::hashLabel ( char const * const domain, char const * const label )
{
uint32 actualHash = Crc::calculate(label);
checkLabel(domain,label,actualHash);
return actualHash;
}
uint32 LabelHash::checkLabel( char const * const domain, char const * const label, uint32 hashValue )
{
// First things first - make sure the label actually hashes to the given value
uint32 actualHash = Crc::calculate(label);
FATAL(actualHash != hashValue, ("LabelHash::checkLabel - Label [%s] hashes to [%d] and not [%d]\n",label,actualHash,hashValue));
// ----------
std::string domainString(domain);
std::string labelString(label);
// Find the hash-to-label map for the given domain, or
// create a new one if there isn't one already.
TDomainMap::iterator domainIt = gs_allDomains.find(domainString);
if(domainIt == gs_allDomains.end())
{
// Domain not found, create entry for it containing the label
THashToStringMap newDomainMap;
newDomainMap.insert( THashEntry(hashValue,labelString) );
gs_allDomains.insert( TDomainEntry(domainString,newDomainMap) );
}
else
{
// Domain found, check for existing hash value
THashToStringMap & domainLabels = (*domainIt).second;
THashToStringMap::iterator labelIt = domainLabels.find(hashValue);
if(labelIt == domainLabels.end())
{
// Hash value not found, add it to the domain
domainLabels.insert( THashEntry(hashValue,labelString) );
}
else
{
// Hash value found, fatal if the string mapped to it doesn't match
// the given string
std::string & currentLabel = (*labelIt).second;
FATAL( currentLabel != labelString, ("LabelHash::checkLabel - Found a hash collision for domain [%s], label [%s] - two labels hashed to the same value\n",domain,label));
}
}
// All is good, hash is OK.
return hashValue;
};
const char * LabelHash::findLabel( char const * const domain, uint32 hashValue )
{
std::string domainString(domain);
TDomainMap::iterator domainIt = gs_allDomains.find(domainString);
if(domainIt == gs_allDomains.end())
{
// Domain not found
return NULL;
}
// ----------
// Domain found, check for existing hash value
THashToStringMap & domainLabels = (*domainIt).second;
THashToStringMap::iterator hashIt = domainLabels.find(hashValue);
if(hashIt != domainLabels.end())
{
return (*hashIt).second.c_str();
}
// ----------
// String not found
return NULL;
}
@@ -0,0 +1,50 @@
// ======================================================================
//
// LabelHash.h
//
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_LabelHash_H
#define INCLUDED_LabelHash_H
// ----------------------------------------------------------------------
class LabelHash
{
public:
typedef uint32 Id;
static void addLabel ( char const * const domain, char const * const label );
static Id hashLabel ( char const * const domain, char const * const label );
static Id checkLabel ( char const * const domain, char const * const label, Id hashValue );
static const char * findLabel ( char const * const domain, Id hashValue );
};
// ----------
//#define LABEL_HASH(domain,label) (LabelHash::hashLabel(#domain,#label))
// ----------
#if DEBUG_LEVEL == DEBUG_LEVEL_DEBUG
// the ##u is so that the compiler interprets the value as an unsigned integer constant
#define LABEL_HASH(domain,label,value) (LabelHash::checkLabel(#domain,#label,value##u))
#else
#define LABEL_HASH(domain,label,value) (value##u)
#endif
// ----------------------------------------------------------------------
#endif // #ifndef INCLUDED_LabelHash_H
@@ -0,0 +1,36 @@
// ======================================================================
//
// LessPointerComparator.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef LESS_POINTER_COMPARATOR_H
#define LESS_POINTER_COMPARATOR_H
// ======================================================================
class LessPointerComparator
{
public:
template <typename PointerType>
bool operator ()(PointerType lhs, PointerType rhs) const
{
return *lhs < *rhs;
}
};
//----------------------------------------------------------------------
template <typename T> class LessPointerComparatorStatic
{
public:
static bool compare(T * a, T * b)
{
return *a < *b;
}
};
// ======================================================================
#endif
@@ -0,0 +1,28 @@
// ======================================================================
//
// MacroFoundation.h
// copyright (c) 1998 Bootprint Entertainment
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_MacroFoundation_H
#define INCLUDED_MacroFoundation_H
// ======================================================================
// No-operation
#define NOP (static_cast<void>(0)) //lint !e1923 //could become const variable
// To prevent "Unreference" compiler warning
#define UNREF(a) (static_cast<void>(a))
// To prevent "Ignoring return value" lint warnings
#define IGNORE_RETURN(a) (static_cast<void>(a))
// int version of the sizeof operator
#define isizeof(a) static_cast<int>(sizeof(a))
// ======================================================================
#endif
@@ -0,0 +1,339 @@
// ======================================================================
//
// Md5.cpp
//
// Portions copyright 2003 Sony Online Entertainment
// Portions derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
// Portions derived from Dan Gorman's implementation
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/Md5.h"
#include <stdio.h>
// ======================================================================
Md5::Value::Value()
{
memset(m_data, 0, sizeof(m_data));
}
// ----------------------------------------------------------------------
Md5::Value::Value(Value const &rhs)
{
memcpy(m_data, rhs.m_data, sizeof(m_data));
}
// ----------------------------------------------------------------------
bool Md5::Value::operator ==(Value const &rhs) const
{
return memcmp(m_data, rhs.m_data, sizeof(m_data)) == 0;
}
// ----------------------------------------------------------------------
bool Md5::Value::operator !=(Value const &rhs) const
{
return !(*this == rhs);
}
// ----------------------------------------------------------------------
void Md5::Value::format(char *buffer, int bufferLength) const
{
//not referenced in release build
UNREF(bufferLength);
DEBUG_FATAL(bufferLength < 33, ("PB: buffer must be at least 33 characters"));
sprintf(buffer, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", m_data[0], m_data[1], m_data[2], m_data[3], m_data[4], m_data[5], m_data[6], m_data[7], m_data[8], m_data[9], m_data[10], m_data[11], m_data[12], m_data[13], m_data[14], m_data[15]);
}
// ======================================================================
Md5::Value Md5::calculate(const char *string)
{
return calculate(string, strlen(string));
}
// ----------------------------------------------------------------------
Md5::Value Md5::calculate(void const *data, int length)
{
Md5 md5;
md5.update(data, length);
md5.finish();
return md5.getValue();
}
// ======================================================================
Md5::Md5()
:
m_bufferedBytes(0),
m_totalLength(0),
m_finished(false)
{
reset();
}
// ----------------------------------------------------------------------
void Md5::reset()
{
m_data[0] = 0x67452301;
m_data[1] = 0xefcdab89;
m_data[2] = 0x98badcfe;
m_data[3] = 0x10325476;
m_bufferedBytes = 0;
m_totalLength = 0;
m_finished = false;
}
// ----------------------------------------------------------------------
void Md5::update(void const *data, int length)
{
m_totalLength += length;
byte const * byteData = reinterpret_cast<byte const *>(data);
while (length > 0)
{
// if there's no bytes pending from last time and we have a full block incoming transform it directly to avoid the copy
if (m_bufferedBytes == 0 && length >= BUFFER_SIZE)
{
transformBlock(byteData);
byteData += BUFFER_SIZE;
length -= BUFFER_SIZE;
}
else
{
// figure out how many bytes to copy into the temp buffer
int bytesToCopy = BUFFER_SIZE - m_bufferedBytes;
if (length < bytesToCopy)
bytesToCopy = length;
// copy the data into the temp buffer
memmove(m_buffer + m_bufferedBytes, byteData, bytesToCopy);
m_bufferedBytes += bytesToCopy;
byteData += bytesToCopy;
length -= bytesToCopy;
// if we've managed to fill the temp buffer, transform it
if (m_bufferedBytes == BUFFER_SIZE)
{
transformBlock(m_buffer);
m_bufferedBytes = 0;
}
}
}
}
// ----------------------------------------------------------------------
void Md5::wordsToBytes(const uint32* words, size_t wordCnt, uint8* bytes)
{
const int bytesPerWord = sizeof(*words)/sizeof(*bytes);
while ((wordCnt--) > 0)
{
uint32 wd = *(words++);
int cnt = bytesPerWord;
while (cnt-- > 0)
{
*(bytes++) = static_cast<uint8>(wd & 0x0ff);
wd >>= 8;
}
}
}
// ----------------------------------------------------------------------
void Md5::bytesToWords(const uint8* bytes, size_t byteCnt, uint32* words)
{
const int bytesPerWord = sizeof(*words)/sizeof(*bytes);
size_t wdcnt = byteCnt/bytesPerWord;
while (wdcnt-- > 0)
{
uint32 wd = 0;
int cnt = bytesPerWord;
int shft = 0;
while (cnt-- > 0)
{
wd |= static_cast<uint32>(*(bytes++) & 0x0ff) << shft;
shft += 8;
}
*(words++) = wd;
byteCnt -= bytesPerWord;
}
}
// ----------------------------------------------------------------------
inline uint32 Md5::rotate_left(uint32 ival, uint32 shft)
{
return ((ival << shft) | (ival >> (32-shft)));
}
// ----------------------------------------------------------------------
inline uint32 Md5::round1(uint32 i, uint32 j, uint32 k, uint32 l, uint32 i1, uint32 j1, uint32 k1)
{
i += ((j & k) | (~j & l)) + i1 + k1;
return rotate_left(i, j1) + j;
}
// ----------------------------------------------------------------------
inline uint32 Md5::round2(uint32 i, uint32 j, uint32 k, uint32 l, uint32 i1, uint32 j1, uint32 k1)
{
i += ((j & l) | (k & ~l)) + i1 + k1;
return rotate_left(i, j1) + j;
}
// ----------------------------------------------------------------------
inline uint32 Md5::round3(uint32 i, uint32 j, uint32 k, uint32 l, uint32 i1, uint32 j1, uint32 k1)
{
i += (j ^ k ^ l) + i1 + k1;
return rotate_left(i, j1) + j;
}
// ----------------------------------------------------------------------
inline uint32 Md5::round4(uint32 i, uint32 j, uint32 k, uint32 l, uint32 i1, uint32 j1, uint32 k1)
{
i += (k ^ (j | ~l)) + i1 + k1;
return rotate_left(i, j1) + j;
}
// ----------------------------------------------------------------------
void Md5::transformBlock(void const * data)
{
// pack the bytes into 32-bit little endian words
uint32 work[64 / 4];
bytesToWords(reinterpret_cast<byte const *>(data), 64, work);
//uint32 const * work = reinterpret_cast<uint32 const *>(data);
uint32 j = m_data[0];
uint32 k = m_data[1];
uint32 l = m_data[2];
uint32 m = m_data[3];
j = round1(j, k, l, m, work[0], 7, 0xd76aa478);
m = round1(m, j, k, l, work[1], 12, 0xe8c7b756);
l = round1(l, m, j, k, work[2], 17, 0x242070db);
k = round1(k, l, m, j, work[3], 22, 0xc1bdceee);
j = round1(j, k, l, m, work[4], 7, 0xf57c0faf);
m = round1(m, j, k, l, work[5], 12, 0x4787c62a);
l = round1(l, m, j, k, work[6], 17, 0xa8304613);
k = round1(k, l, m, j, work[7], 22, 0xfd469501);
j = round1(j, k, l, m, work[8], 7, 0x698098d8);
m = round1(m, j, k, l, work[9], 12, 0x8b44f7af);
l = round1(l, m, j, k, work[10], 17, 0xffff5bb1);
k = round1(k, l, m, j, work[11], 22, 0x895cd7be);
j = round1(j, k, l, m, work[12], 7, 0x6b901122);
m = round1(m, j, k, l, work[13], 12, 0xfd987193);
l = round1(l, m, j, k, work[14], 17, 0xa679438e);
k = round1(k, l, m, j, work[15], 22, 0x49b40821);
j = round2(j, k, l, m, work[1], 5, 0xf61e2562);
m = round2(m, j, k, l, work[6], 9, 0xc040b340);
l = round2(l, m, j, k, work[11], 14, 0x265e5a51);
k = round2(k, l, m, j, work[0], 20, 0xe9b6c7aa);
j = round2(j, k, l, m, work[5], 5, 0xd62f105d);
m = round2(m, j, k, l, work[10], 9, 0x02441453);
l = round2(l, m, j, k, work[15], 14, 0xd8a1e681);
k = round2(k, l, m, j, work[4], 20, 0xe7d3fbc8);
j = round2(j, k, l, m, work[9], 5, 0x21e1cde6);
m = round2(m, j, k, l, work[14], 9, 0xc33707d6);
l = round2(l, m, j, k, work[3], 14, 0xf4d50d87);
k = round2(k, l, m, j, work[8], 20, 0x455a14ed);
j = round2(j, k, l, m, work[13], 5, 0xa9e3e905);
m = round2(m, j, k, l, work[2], 9, 0xfcefa3f8);
l = round2(l, m, j, k, work[7], 14, 0x676f02d9);
k = round2(k, l, m, j, work[12], 20, 0x8d2a4c8a);
j = round3(j, k, l, m, work[5], 4, 0xfffa3942);
m = round3(m, j, k, l, work[8], 11, 0x8771f681);
l = round3(l, m, j, k, work[11], 16, 0x6d9d6122);
k = round3(k, l, m, j, work[14], 23, 0xfde5380c);
j = round3(j, k, l, m, work[1], 4, 0xa4beea44);
m = round3(m, j, k, l, work[4], 11, 0x4bdecfa9);
l = round3(l, m, j, k, work[7], 16, 0xf6bb4b60);
k = round3(k, l, m, j, work[10], 23, 0xbebfbc70);
j = round3(j, k, l, m, work[13], 4, 0x289b7ec6);
m = round3(m, j, k, l, work[0], 11, 0xeaa127fa);
l = round3(l, m, j, k, work[3], 16, 0xd4ef3085);
k = round3(k, l, m, j, work[6], 23, 0x04881d05);
j = round3(j, k, l, m, work[9], 4, 0xd9d4d039);
m = round3(m, j, k, l, work[12], 11, 0xe6db99e5);
l = round3(l, m, j, k, work[15], 16, 0x1fa27cf8);
k = round3(k, l, m, j, work[2], 23, 0xc4ac5665);
j = round4(j, k, l, m, work[0], 6, 0xf4292244);
m = round4(m, j, k, l, work[7], 10, 0x432aff97);
l = round4(l, m, j, k, work[14], 15, 0xab9423a7);
k = round4(k, l, m, j, work[5], 21, 0xfc93a039);
j = round4(j, k, l, m, work[12], 6, 0x655b59c3);
m = round4(m, j, k, l, work[3], 10, 0x8f0ccc92);
l = round4(l, m, j, k, work[10], 15, 0xffeff47d);
k = round4(k, l, m, j, work[1], 21, 0x85845dd1);
j = round4(j, k, l, m, work[8], 6, 0x6fa87e4f);
m = round4(m, j, k, l, work[15], 10, 0xfe2ce6e0);
l = round4(l, m, j, k, work[6], 15, 0xa3014314);
k = round4(k, l, m, j, work[13], 21, 0x4e0811a1);
j = round4(j, k, l, m, work[4], 6, 0xf7537e82);
m = round4(m, j, k, l, work[11], 10, 0xbd3af235);
l = round4(l, m, j, k, work[2], 15, 0x2ad7d2bb);
k = round4(k, l, m, j, work[9], 21, 0xeb86d391);
m_data[0] += j;
m_data[1] += k;
m_data[2] += l;
m_data[3] += m;
}
// ----------------------------------------------------------------------
void Md5::finish()
{
DEBUG_FATAL(m_finished, ("PB: MD5 already finished"));
uint64 messageLengthInBits = m_totalLength * 8;
// we always have to append a trailing bit
{
byte append = 0x80;
update(&append, 1);
}
// how much to pad to existing bytes to come out to an even 64 byte multiple, yet leave room at the end for the count.
while (m_bufferedBytes != (BUFFER_SIZE - 8))
{
byte append = 0x00;
update(&append, 1);
}
// append the length of the source message in bits
uint8 countAsBytes[8];
wordsToBytes(reinterpret_cast<const uint32*>(&(messageLengthInBits)), 2, countAsBytes);
update(countAsBytes, 8);
m_finished = true;
}
// ----------------------------------------------------------------------
Md5::Value Md5::getValue() const
{
DEBUG_FATAL(!m_finished, ("PB: did not finish MD5 before calling getValue"));
Value v;
wordsToBytes(m_data, 4, v.m_data);
return v;
}
// ======================================================================
@@ -0,0 +1,99 @@
// ======================================================================
//
// Md5.h
//
// copyright 2003 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Md5_H
#define INCLUDED_Md5_H
// ======================================================================
class Md5
{
public:
class Value
{
friend class Md5;
public:
enum
{
cms_dataSize = 16
};
public:
Value();
Value(Value const &rhs);
bool operator ==(Value const &rhs) const;
bool operator !=(Value const &rhs) const;
void format(char *buffer, int bufferLength) const;
void *getData();
private:
uint8 m_data[cms_dataSize];
};
public:
static Value calculate(const char *string);
static Value calculate(const void *data, int len);
public:
Md5();
void reset();
void update(void const *data, int len);
void finish();
Value getValue() const;
private:
static void wordsToBytes(const uint32* words, size_t wordCnt, uint8* bytes);
static void bytesToWords(const uint8* bytes, size_t byteCnt, uint32* words);
static uint32 rotate_left(uint32 ival, uint32 shft);
static uint32 round1(uint32 i, uint32 j, uint32 k, uint32 l, uint32 i1, uint32 j1, uint32 k1);
static uint32 round2(uint32 i, uint32 j, uint32 k, uint32 l, uint32 i1, uint32 j1, uint32 k1);
static uint32 round3(uint32 i, uint32 j, uint32 k, uint32 l, uint32 i1, uint32 j1, uint32 k1);
static uint32 round4(uint32 i, uint32 j, uint32 k, uint32 l, uint32 i1, uint32 j1, uint32 k1);
void transformBlock(void const *data);
private:
enum
{
BUFFER_SIZE = 64
};
uint32 m_data[4];
byte m_buffer[BUFFER_SIZE];
int m_bufferedBytes;
int m_totalLength;
bool m_finished;
public:
Md5(Md5 const &);
Md5 & operator =(Md5 const &);
};
// ======================================================================
inline void * Md5::Value::getData()
{
return m_data;
}
// ======================================================================
#endif
@@ -0,0 +1,636 @@
// ======================================================================
//
// MemoryBlockManager.cpp
// copyright 1998 Bootprint Entertainment
// copyright 2002 Sony Online Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/MemoryBlockManager.h"
#include "sharedDebug/DebugFlags.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/ConfigSharedFoundation.h"
#include "sharedSynchronization/Mutex.h"
#include <map>
#include <vector>
#define PASS_THROUGH_TO_GLOBAL_MEMORY_MANAGER 0
// ======================================================================
class MemoryBlockManager::Allocator
{
public:
Allocator(int elementSize);
Allocator(int elementSize, int elementsPerBlock, int minimumBlocks, int maximumNumberOfBlocks);
~Allocator();
int getElementSize();
void fetch();
bool release();
int getReferenceCount();
bool isFull() const;
int getNumberOfAllocatedElements();
void *allocate();
void free(void *pointer);
#ifdef _DEBUG
void debugDump () const;
#endif
private:
struct Block
{
Block *next;
byte *data;
};
struct Element
{
Element *next;
};
void *realAlloc();
void realFree(void *pointer);
void placeOnFreeList(Element *element);
void allocateNewBlock();
private:
Allocator();
Allocator(Allocator const &);
Allocator &operator =(Allocator const &);
private:
int m_referenceCount;
// first block on the allocated block list
Block *m_firstBlock;
// first free element
Element *m_firstFreeElement;
// size of each element
int m_elementSize;
// number of elements per block
int m_elementsPerBlock;
// current number of blocks in existance
int m_currentNumberOfBlocks;
// current number of blocks that are allowed to exist, 0 for unliminted
int m_maximumNumberOfBlocks;
// number of outstanding allocations
int m_numberOfAllocatedElements;
#ifdef _DEBUG
int m_lifetimeAllocatedElements;
#endif
};
// ======================================================================
namespace MemoryBlockManagerNamespace
{
bool ms_debugDumpOnRemove = false;
bool ms_forceAllNonShared = false;
#ifdef _DEBUG
bool ms_debugReport = false;
int ms_debugNumberOfAllocations = 0;
int ms_debugNumberOfBytes = 0;
bool ms_debugDumpAllNextFrame = false;
typedef std::vector<MemoryBlockManager*> MemoryBlockManagerList;
MemoryBlockManagerList ms_memoryBlockManagerList;
#endif
typedef std::map<int, MemoryBlockManager::Allocator *> Allocators;
Allocators ms_allocators;
Mutex ms_globalCriticalSection;
#ifdef _DEBUG
bool m_usingMemoryBlockManager = false;
#endif
void remove();
#ifdef _DEBUG
void debugReport();
void debugDumpAll ();
#endif
}
using namespace MemoryBlockManagerNamespace;
// ======================================================================
MemoryBlockManager::Allocator::Allocator(const int elementSize)
:
m_referenceCount(0),
m_firstBlock(NULL),
m_firstFreeElement(NULL),
m_elementSize(elementSize),
m_elementsPerBlock(64),
m_currentNumberOfBlocks(0),
m_maximumNumberOfBlocks(0),
m_numberOfAllocatedElements(0)
#ifdef _DEBUG
,
m_lifetimeAllocatedElements(0)
#endif
{
}
// ----------------------------------------------------------------------
MemoryBlockManager::Allocator::Allocator(int elementSize, int elementsPerBlock, int minimumBlocks, int maximumNumberOfBlocks)
:
m_referenceCount(0),
m_firstBlock(NULL),
m_firstFreeElement(NULL),
m_elementSize(elementSize),
m_elementsPerBlock(elementsPerBlock),
m_currentNumberOfBlocks(0),
m_maximumNumberOfBlocks(maximumNumberOfBlocks),
m_numberOfAllocatedElements(0)
#ifdef _DEBUG
,
m_lifetimeAllocatedElements(0)
#endif
{
for (int i = 0; i < minimumBlocks; ++i)
allocateNewBlock();
}
// ----------------------------------------------------------------------
MemoryBlockManager::Allocator::~Allocator()
{
if (ExitChain::isFataling())
return;
while (m_firstBlock)
{
Block * block = m_firstBlock;
m_firstBlock = m_firstBlock->next;
delete [] block->data;
delete block;
}
m_firstBlock = NULL;
m_firstFreeElement = NULL;
}
// ----------------------------------------------------------------------
void MemoryBlockManager::Allocator::fetch()
{
++m_referenceCount;
}
// ----------------------------------------------------------------------
bool MemoryBlockManager::Allocator::release()
{
if (--m_referenceCount <= 0)
{
DEBUG_FATAL(m_referenceCount < 0, ("reference count went negative"));
return true;
}
return false;
}
// ----------------------------------------------------------------------
inline int MemoryBlockManager::Allocator::getElementSize()
{
return m_elementSize;
}
// ----------------------------------------------------------------------
int MemoryBlockManager::Allocator::getReferenceCount()
{
return m_referenceCount;
}
// ----------------------------------------------------------------------
bool MemoryBlockManager::Allocator::isFull() const
{
return m_maximumNumberOfBlocks && m_numberOfAllocatedElements >= m_elementsPerBlock * m_maximumNumberOfBlocks;
}
// ----------------------------------------------------------------------
int MemoryBlockManager::Allocator::getNumberOfAllocatedElements()
{
return m_numberOfAllocatedElements;
}
// ----------------------------------------------------------------------
void *MemoryBlockManager::Allocator::allocate()
{
void *result = 0;
// check if there are any free elements
if (!m_firstFreeElement)
allocateNewBlock();
result = m_firstFreeElement;
m_firstFreeElement = m_firstFreeElement->next;
++m_numberOfAllocatedElements;
#ifdef _DEBUG
m_lifetimeAllocatedElements += 1;
ms_debugNumberOfAllocations += 1;
ms_debugNumberOfBytes += getElementSize();
#endif
return result;
}
// ----------------------------------------------------------------------
void MemoryBlockManager::Allocator::free(void *pointer)
{
DEBUG_FATAL(m_numberOfAllocatedElements <= 0, ("freeing an element when already empty"));
Element *element = reinterpret_cast<Element *>(pointer);
placeOnFreeList(element);
--m_numberOfAllocatedElements;
}
// ----------------------------------------------------------------------
/**
* Places an element on the free element list
*/
void MemoryBlockManager::Allocator::placeOnFreeList(Element *element)
{
NOT_NULL(element);
element->next = m_firstFreeElement;
m_firstFreeElement = element;
}
// ----------------------------------------------------------------------
/**
* Get a new block and put its elements on the free list.
*
* Will not allocate a new block if the maximum number of blocks has already
* been reached.
*/
void MemoryBlockManager::Allocator::allocateNewBlock()
{
// allocate a new block
Block *block = new Block;
block->data = new byte[static_cast<size_t>(m_elementSize * m_elementsPerBlock)];
// put the block on the block list
block->next = m_firstBlock;
m_firstBlock = block;
// put all the new block elements on the free list
{
int i;
byte *data;
for (i = m_elementsPerBlock, data = block->data; i; --i, data += m_elementSize)
placeOnFreeList(reinterpret_cast<Element *>(data)); //lint !e826 // suspicious pointer conversion (area too small)
}
// count the new block
++m_currentNumberOfBlocks;
}
// ----------------------------------------------------------------------
#ifdef _DEBUG
void MemoryBlockManager::Allocator::debugDump() const
{
const int currentUsageInKilobytes = m_numberOfAllocatedElements * m_elementSize / 1024;
const int totalUsageInKilobytes = (m_currentNumberOfBlocks * m_elementsPerBlock * m_elementSize) / 1024;
const int percent = totalUsageInKilobytes ? ((currentUsageInKilobytes * 100) / totalUsageInKilobytes) : 0;
DEBUG_REPORT_LOG(true, ("MBMA elementSize=%d elements=%d elementsPerBlock=%d blocks=%d mem=%dk full=%d%%\n", m_elementSize, m_numberOfAllocatedElements, m_elementsPerBlock, m_currentNumberOfBlocks, totalUsageInKilobytes, percent));
}
#endif
// ======================================================================
void MemoryBlockManager::install(bool debugDumpOnRemove)
{
ms_debugDumpOnRemove = debugDumpOnRemove;
#if PASS_THROUGH_TO_GLOBAL_MEMORY_MANAGER
DEBUG_WARNING(true, ("MemoryBlockManager enabled PASS_THROUGH_TO_GLOBAL_MEMORY_MANAGER"));
#endif
#ifdef _DEBUG
m_usingMemoryBlockManager = ConfigSharedFoundation::getUseMemoryBlockManager();
#endif
#if PASS_THROUGH_TO_GLOBAL_MEMORY_MANAGER
m_usingMemoryBlockManager = false;
#endif
DebugFlags::registerFlag(ms_forceAllNonShared, "SharedFoundation", "memoryBlockManagerForceAllNonShared");
REPORT_LOG(ms_forceAllNonShared, ("MemoryBlockManager enabled memoryBlockManagerForceAllNonShared\n"));
#ifdef _DEBUG
DebugFlags::registerFlag(ms_debugReport, "SharedFoundation", "reportMemoryBlockManager", debugReport);
DebugFlags::registerFlag(ms_debugDumpAllNextFrame, "SharedFoundation", "memoryBlockManagerDebugDumpAllNextFrame", debugDumpAll);
#endif
ExitChain::add(MemoryBlockManagerNamespace::remove, "MemoryBlockManager::remove");
}
// ----------------------------------------------------------------------
void MemoryBlockManagerNamespace::remove()
{
ms_globalCriticalSection.enter();
Allocators::iterator iEnd = ms_allocators.end();
for (Allocators::iterator i = ms_allocators.begin(); i != iEnd; ++i)
{
DEBUG_WARNING(true, ("Unfreed MBM %d=size %d=ref %d=items", i->second->getElementSize(), i->second->getReferenceCount(), i->second->getNumberOfAllocatedElements()));
}
#ifdef _DEBUG
if (ms_debugDumpOnRemove)
{
debugDumpAll();
}
#endif
ms_globalCriticalSection.leave();
}
// ----------------------------------------------------------------------
#ifdef _DEBUG
void MemoryBlockManagerNamespace::debugReport()
{
ms_globalCriticalSection.enter();
int const numberOfAllocations = ms_debugNumberOfAllocations;
ms_debugNumberOfAllocations = 0;
int const numberOfBytes = ms_debugNumberOfBytes;
ms_debugNumberOfBytes = 0;
ms_globalCriticalSection.leave();
DEBUG_REPORT_PRINT(true, ("mbm %d=alloc %d=bytes\n", numberOfAllocations, numberOfBytes));
}
#endif
// ----------------------------------------------------------------------
#ifdef _DEBUG
void MemoryBlockManagerNamespace::debugDumpAll ()
{
{
// dump the memory block managers and their private allocators
uint i;
for (i = 0; i < ms_memoryBlockManagerList.size (); ++i)
ms_memoryBlockManagerList [i]->debugDump ();
}
{
// dump the shared allocators
ms_globalCriticalSection.enter();
Allocators::iterator iEnd = ms_allocators.end();
for (Allocators::iterator i = ms_allocators.begin(); i != iEnd; ++i)
i->second->debugDump();
ms_globalCriticalSection.leave();
}
ms_debugDumpAllNextFrame = false;
}
#endif
// ======================================================================
MemoryBlockManager::MemoryBlockManager(char const * name, bool shared, int elementSize, int elementsPerBlock, int minimumNumberOfBlocks, int maximumNumberOfBlocks)
: m_name(name),
m_shared(shared),
m_currentNumberOfElements(0),
m_allocator(NULL)
{
//-- Handle config option where we force all MemoryBlockManagers to be non-shared.
if (shared && ms_forceAllNonShared)
{
m_shared = false;
shared = false;
if (elementsPerBlock <= 0)
{
//-- Adjust elements per block: caller specified as 0 because it thought it was going to be shared.
elementsPerBlock = 100;
}
}
if (elementSize < isizeof(void*))
elementSize = isizeof(void*);
if (m_shared)
{
DEBUG_FATAL(elementsPerBlock, ("elementsPerBlock must be 0 if shared"));
DEBUG_FATAL(minimumNumberOfBlocks, ("minimumNumberOfBlocks must be 0 if shared"));
DEBUG_FATAL(maximumNumberOfBlocks, ("maximumNumberOfBlocks must be 0 if shared"));
ms_globalCriticalSection.enter();
Allocators::iterator i = ms_allocators.find(elementSize);
if (i == ms_allocators.end())
{
// construct it and put it on the map
i = ms_allocators.insert(Allocators::value_type(elementSize, new Allocator(elementSize))).first;
}
m_allocator = i->second;
m_allocator->fetch();
ms_globalCriticalSection.leave();
}
else
{
ms_globalCriticalSection.enter();
DEBUG_FATAL(elementsPerBlock == 0, ("elementsPerBlock may not be 0 if shared"));
m_allocator = new Allocator(elementSize, elementsPerBlock, minimumNumberOfBlocks, maximumNumberOfBlocks);
m_allocator->fetch();
ms_globalCriticalSection.leave();
}
#ifdef _DEBUG
{
ms_globalCriticalSection.enter();
ms_memoryBlockManagerList.push_back (this);
ms_globalCriticalSection.leave();
}
#endif
}
// ----------------------------------------------------------------------
MemoryBlockManager::~MemoryBlockManager()
{
if (ExitChain::isFataling())
return;
ms_globalCriticalSection.enter();
#ifdef _DEBUG
{
MemoryBlockManagerList::iterator iter = std::find (ms_memoryBlockManagerList.begin (), ms_memoryBlockManagerList.end (), this);
if (iter != ms_memoryBlockManagerList.end ())
ms_memoryBlockManagerList.erase (iter);
}
#endif
if (m_currentNumberOfElements)
{
DEBUG_WARNING(!ConfigSharedFoundation::getDemoMode(), ("MemoryBlockManager::~ %d elements still allocated in %s", m_currentNumberOfElements, m_name));
ms_globalCriticalSection.leave();
return;
}
if (m_allocator->release())
{
if (m_shared)
{
Allocators::iterator i = ms_allocators.find(getElementSize());
DEBUG_FATAL(i == ms_allocators.end(), ("Allocator not found"));
DEBUG_FATAL(i->second != m_allocator, ("wrong allocator"));
ms_allocators.erase(i);
}
delete m_allocator;
}
ms_globalCriticalSection.leave();
m_allocator = 0;
m_name = 0;
}
// ----------------------------------------------------------------------
#ifdef _DEBUG
void MemoryBlockManager::debugDump() const
{
DEBUG_REPORT_LOG(true, ("MBM %s: size=%d elements=%d\n", m_name ? m_name : "<unnamed>", m_allocator->getElementSize(), m_currentNumberOfElements));
if (!m_shared)
m_allocator->debugDump();
}
#endif
// ----------------------------------------------------------------------
int MemoryBlockManager::getElementSize() const
{
return m_allocator->getElementSize();
}
// ----------------------------------------------------------------------
int MemoryBlockManager::getElementCount() const
{
#ifdef _DEBUG
if(!m_usingMemoryBlockManager)
{
return 0;
}
#endif
ms_globalCriticalSection.enter();
int const result = m_currentNumberOfElements;
ms_globalCriticalSection.leave();
return result;
}
// ----------------------------------------------------------------------
bool MemoryBlockManager::isFull() const
{
#ifdef _DEBUG
if(!m_usingMemoryBlockManager)
{
return false;
}
#endif
ms_globalCriticalSection.enter();
const bool result = m_allocator->isFull();
ms_globalCriticalSection.leave();
return result;
}
// ----------------------------------------------------------------------
void *MemoryBlockManager::allocate(bool returnNullOnFailure)
{
UNREF(returnNullOnFailure);
#ifdef _DEBUG
if(!m_usingMemoryBlockManager)
{
return operator new(getElementSize());
}
#endif
ms_globalCriticalSection.enter();
if (m_allocator->isFull())
{
ms_globalCriticalSection.leave();
DEBUG_FATAL(!returnNullOnFailure, ("MBM %s is full %d", m_name, m_currentNumberOfElements));
return NULL;
}
++m_currentNumberOfElements;
void * result = m_allocator->allocate();
ms_globalCriticalSection.leave();
return result;
}
// ----------------------------------------------------------------------
void MemoryBlockManager::free(void *pointer)
{
if (pointer)
{
#ifdef _DEBUG
if(!m_usingMemoryBlockManager)
{
operator delete(pointer);
return;
}
#endif
ms_globalCriticalSection.enter();
if (--m_currentNumberOfElements < 0)
DEBUG_FATAL(true, ("MBM %s number of allocated elements went negative", m_name));
m_allocator->free(pointer);
ms_globalCriticalSection.leave();
}
}
// ======================================================================
@@ -0,0 +1,69 @@
// ======================================================================
//
// MemoryBlockManager.h
//
// Portions copyright 1998 Bootprint Entertainment
// Portions copyright 2000-2002 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_MemoryBlockManager_H
#define INCLUDED_MemoryBlockManager_H
// ======================================================================
class MemoryBlockManager
{
public:
static void install(bool debugDumpOnRemove);
public:
DLLEXPORT MemoryBlockManager(char const * name, bool shared, int elementSize, int elementsPerBlock, int minimumNumberOfBlocks, int maximumNumberOfBlocks);
DLLEXPORT ~MemoryBlockManager();
const char * getName() const;
bool isFull() const;
DLLEXPORT int getElementSize() const;
int getElementCount() const;
DLLEXPORT void * allocate(bool returnNullOnFailure=false);
DLLEXPORT void free(void * pointer);
public:
#ifdef _DEBUG
void debugDump() const;
#endif
protected:
// disable these routines
MemoryBlockManager();
MemoryBlockManager(const MemoryBlockManager &);
MemoryBlockManager &operator =(const MemoryBlockManager &);
public:
class Allocator;
private:
char const * m_name;
bool m_shared;
int m_currentNumberOfElements;
Allocator * m_allocator;
};
// ======================================================================
inline char const * MemoryBlockManager::getName() const
{
return m_name;
}
// ======================================================================
#endif
@@ -0,0 +1,107 @@
// ======================================================================
//
// MemoryBlockManagerMacros.h
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_MemoryBlockManagerMacros_H
#define INCLUDED_MemoryBlockManagerMacros_H
// ======================================================================
class MemoryBlockManager;
// ======================================================================
#define MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL \
public: \
static void install(); \
static void * operator new(size_t size); \
static void * operator new(size_t size, void * placement); \
static void operator delete(void * pointer); \
private: \
static void remove(); \
static MemoryBlockManager * ms_memoryBlockManager
// ----------------------------------------------------------------------
#define MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(className, shared, elementsPerBlock, minimumNumberOfBlocks, maximumNumberOfBlocks) \
void className::install() \
{ \
ms_memoryBlockManager = new MemoryBlockManager( #className " memoryBlockManager", shared, sizeof(className), elementsPerBlock, minimumNumberOfBlocks, maximumNumberOfBlocks); \
ExitChain::add(&remove, #className "::remove"); \
} \
void className::remove() \
{ \
DEBUG_FATAL(!ms_memoryBlockManager,(#className " is not installed")); \
delete ms_memoryBlockManager; \
ms_memoryBlockManager = 0; \
} \
void * className::operator new(size_t size) \
{ \
UNREF(size); \
DEBUG_FATAL(size != sizeof(className),("Incorrect allocation size for class " #className ": %d/%d", size, sizeof(className))); \
DEBUG_FATAL(!ms_memoryBlockManager, (#className " is not installed")); \
return ms_memoryBlockManager->allocate(); \
} \
void * className::operator new(size_t, void * placement) \
{ \
return placement; \
}\
void className::operator delete(void * pointer) \
{ \
DEBUG_FATAL(!ms_memoryBlockManager,(#className " is not installed")); \
if (pointer) \
ms_memoryBlockManager->free(pointer); \
} \
MemoryBlockManager * className::ms_memoryBlockManager
// ======================================================================
#define MEMORY_BLOCK_MANAGER_INTERFACE_WITHOUT_INSTALL \
public: \
static void * operator new(size_t size); \
static void * operator new(size_t size, void * placement); \
static void operator delete(void * pointer); \
private: \
static void installMemoryBlockManager(); \
static void removeMemoryBlockManager(); \
static MemoryBlockManager * ms_memoryBlockManager
// ----------------------------------------------------------------------
#define MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITHOUT_INSTALL(className, shared, elementsPerBlock, minimumNumberOfBlocks, maximumNumberOfBlocks) \
void className::installMemoryBlockManager() \
{ \
ms_memoryBlockManager = new MemoryBlockManager( #className " memoryBlockManager", shared, sizeof(className), elementsPerBlock, minimumNumberOfBlocks, maximumNumberOfBlocks); \
} \
void className::removeMemoryBlockManager() \
{ \
DEBUG_FATAL(!ms_memoryBlockManager,(#className " is not installed")); \
delete ms_memoryBlockManager; \
ms_memoryBlockManager = 0; \
} \
void * className::operator new(size_t size) \
{ \
UNREF(size); \
DEBUG_FATAL(size != sizeof(className),("Incorrect allocation size for class " #className ": %d/%d", size, sizeof(className))); \
DEBUG_FATAL(!ms_memoryBlockManager, (#className " is not installed")); \
return ms_memoryBlockManager->allocate(); \
} \
void * className::operator new(size_t, void * placement) \
{ \
return placement; \
}\
void className::operator delete(void * pointer) \
{ \
DEBUG_FATAL(!ms_memoryBlockManager,(#className " is not installed")); \
if (pointer) \
ms_memoryBlockManager->free(pointer); \
} \
MemoryBlockManager * className::ms_memoryBlockManager
// ======================================================================
#endif
@@ -0,0 +1,319 @@
// ======================================================================
//
// MessageQueue.cpp
// Portions copyright 1998 Bootprint Entertainment.
// Portions copyright 2000-2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/MessageQueue.h"
#include <vector>
// ======================================================================
// PUBLIC MessageQueue::Data
// ======================================================================
MessageQueue::Data::Data()
{
}
// ----------------------------------------------------------------------
MessageQueue::Data::~Data()
{
}
// ======================================================================
// PUBLIC MessageQueue::Notification
// ======================================================================
MessageQueue::Notification::Notification()
{
}
// ----------------------------------------------------------------------
MessageQueue::Notification::~Notification()
{
}
// ======================================================================
// PRIVATE MessageQueue::Message
// ======================================================================
MessageQueue::Message::Message() :
m_message(0),
m_value(0),
m_data(0),
m_flags(0)
{
}
//----------------------------------------------------------------------
MessageQueue::Message::~Message()
{
m_data = 0;
}
// ======================================================================
// PUBLIC MessageQueue
// ======================================================================
MessageQueue::MessageQueue(const int initialSize) :
m_messageQueue1(new MessageList),
m_messageQueue2(new MessageList),
m_messageQueueRead(m_messageQueue1),
m_messageQueueWrite(m_messageQueue2),
m_notification(0)
{
DEBUG_WARNING(initialSize < 0, ("initialSize < 0"));
m_messageQueue1->reserve(static_cast<uint>(std::max(initialSize, 0)));
m_messageQueue2->reserve(static_cast<uint>(std::max(initialSize, 0)));
}
// ----------------------------------------------------------------------
/**
* Destroy the MessageQueue.
*/
MessageQueue::~MessageQueue()
{
clearDataFromMessageList(*m_messageQueue1, true);
clearDataFromMessageList(*m_messageQueue2, true);
delete m_messageQueue1;
delete m_messageQueue2;
m_messageQueueRead = 0;
m_messageQueueWrite = 0;
m_notification = 0;
}
// ----------------------------------------------------------------------
void MessageQueue::clearDataFromMessageList(MessageList &messageList, bool destructor)
{
UNREF(destructor);
MessageList::iterator iEnd = messageList.end();
for (MessageList::iterator i = messageList.begin(); i != iEnd; ++i)
{
Message & message = *i;
if (message.m_data)
{
DEBUG_WARNING(!destructor, ("clearing message data from beginFrame"));
delete message.m_data;
message.m_data = NULL;
}
}
}
// ----------------------------------------------------------------------
/**
* Get a message from the MessageQueue.
*
* The message index ranges from 0 to getNumberOfMessages()-1.
*
* @param index [In ] The index of the message to retrieve
* @param message [Out] The message received
* @param value [Out] Argument for the message
* @param flags [Out] User flags for this message
* @see MessageQueue::getNumberOfMessages()
*/
void MessageQueue::getMessage(const int index, int *const message, float *const value, uint32 *const flags) const
{
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getNumberOfMessages());
NOT_NULL(message);
NOT_NULL(value);
NOT_NULL(m_messageQueueRead);
const Message &currentMessage = (*m_messageQueueRead)[static_cast<uint>(index)];
*message = currentMessage.m_message;
*value = currentMessage.m_value;
if (flags)
*flags = currentMessage.m_flags;
}
// ----------------------------------------------------------------------
/**
* Get a message from the MessageQueue.
*
* The message index ranges from 0 to getNumberOfMessages()-1.
*
* @param index [In ] The index of the message to retrieve
* @param message [Out] The message received
* @param value [Out] Argument for the message
* @param data [Out] Data for the message
* @param flags [Out] User flags for this message
* @see MessageQueue::getNumberOfMessages()
*/
void MessageQueue::getMessage(const int index, int *const message, float *const value, Data **const data, uint32 *const flags) const
{
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getNumberOfMessages());
NOT_NULL(message);
NOT_NULL(value);
NOT_NULL(data);
NOT_NULL(m_messageQueueRead);
const Message & currentMessage = (*m_messageQueueRead)[static_cast<uint>(index)];
*message = currentMessage.m_message;
*value = currentMessage.m_value;
*data = currentMessage.m_data;
if (flags)
*flags = currentMessage.m_flags;
}
// ----------------------------------------------------------------------
/**
* Sets message flags in the MessageQueue.
*
* The message index ranges from 0 to getNumberOfMessages()-1.
*
* @see MessageQueue::getNumberOfMessages()
*/
void MessageQueue::setMessageFlags(const int index, const uint32 flags)
{
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getNumberOfMessages());
(*m_messageQueueRead)[static_cast<uint>(index)].m_flags = flags;
}
// ----------------------------------------------------------------------
/**
* Clear a message in the MessageQueue.
*
* The message index ranges from 0 to getNumberOfMessages()-1.
*
* @param index [In] The index of the message to clear
* @see MessageQueue::getNumberOfMessages()
*/
void MessageQueue::clearMessage(const int index)
{
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getNumberOfMessages());
Message& message = (*m_messageQueueRead)[static_cast<uint>(index)];
DEBUG_WARNING(message.m_data, ("MessageQueue::clearMessage - clearing message with non-null data"));
message.m_message = 0;
}
// ----------------------------------------------------------------------
/**
* Clear a message in the MessageQueue.
*
* The message index ranges from 0 to getNumberOfMessages()-1.
*
* @param index [In] The index of the message data to clear
* @see MessageQueue::getNumberOfMessages()
*/
void MessageQueue::clearMessageData(const int index)
{
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getNumberOfMessages());
Message& message = (*m_messageQueueRead)[static_cast<uint>(index)];
message.m_data = 0;
}
// ----------------------------------------------------------------------
/**
* Append a new message to the MessageQueue.
*
* The message will not be retrievable until the next call to endFrame().
*
* @param message [In] Message to add to the MessageQueue
* @param value [In] Value to be associated with the message
* @param data [In] Data to be associated with the message
* @param flags [In] User flags for this message
*/
void MessageQueue::appendMessage(const int message, const float value, Data *const data, const uint32 flags)
{
if (message == 0)
{
WARNING_STRICT_FATAL(true, ("bad message"));
return;
}
#ifdef _DEBUG
//-- check to see if any message with data is already in the list
if (data)
{
for (MessageList::iterator iter = m_messageQueueWrite->begin(); iter != m_messageQueueWrite->end(); ++iter)
WARNING_STRICT_FATAL(iter->m_data == data, ("message queue data already in message queue"));
}
#endif
Message newMessage;
newMessage.m_message = message;
newMessage.m_value = value;
newMessage.m_data = data;
newMessage.m_flags = flags;
m_messageQueueWrite->push_back(newMessage);
if (m_notification)
m_notification->onChanged();
}
// ----------------------------------------------------------------------
/**
* Append a new message to the MessageQueue.
*
* The message will not be retrievable until the next call to endFrame().
*
* @param message [In] Message to add to the MessageQueue
* @param value [In] Value to be associated with the message
* @param flags [In] User flags for this message
*/
void MessageQueue::appendMessage(const int message, const float value, const uint32 flags)
{
appendMessage(message, value, 0, flags);
}
// ----------------------------------------------------------------------
// Get the number of messages in the current frame
//
// Return value:
//
// The number of messages in the current frame for the MessageQueue.
//
// Remarks:
//
// getMessage() will take as indices the values from 0 the value returned
// by this routine inclusive.
//
// See also:
//
// MessageQueue::getMessage()
int MessageQueue::getNumberOfMessages() const
{
return static_cast<int>(m_messageQueueRead->size());
}
// ----------------------------------------------------------------------
void MessageQueue::beginFrame()
{
//-- swap read and write
std::swap (m_messageQueueRead, m_messageQueueWrite);
//-- clear write
clearDataFromMessageList(*m_messageQueueWrite, false);
m_messageQueueWrite->clear ();
}
// ----------------------------------------------------------------------
void MessageQueue::setNotification(Notification* notification)
{
m_notification = notification;
}
// ======================================================================
@@ -0,0 +1,97 @@
// ======================================================================
//
// MessageQueue.h
// Portions copyright 1998 Bootprint Entertainment.
// Portions copyright 2000-2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_MessageQueue_H
#define INCLUDED_MessageQueue_H
// ======================================================================
class MessageQueue
{
public:
class Data
{
public:
Data();
virtual ~Data()=0;
};
class Notification
{
public:
Notification();
virtual ~Notification()=0;
virtual void onChanged() const=0;
};
public:
explicit MessageQueue(int initialSize=0);
~MessageQueue();
int getNumberOfMessages() const;
void getMessage(int index, int *message, float *value, uint32 *flags=0) const;
void getMessage(int index, int *message, float *value, Data **data, uint32 *flags=0) const;
void setMessageFlags(int index, uint32 flags);
void clearMessage(int index);
void clearMessageData(int index);
void appendMessage(int message, float value, uint32 flags=0);
void appendMessage(int message, float value, Data *data, uint32 flags=0);
void beginFrame();
void setNotification(Notification* notification);
private:
struct Message
{
public:
Message();
~Message();
public:
int m_message;
float m_value;
Data *m_data;
uint32 m_flags;
};
private:
typedef stdvector<Message>::fwd MessageList;
private:
MessageQueue(const MessageQueue &);
MessageQueue &operator =(const MessageQueue &);
void clearDataFromMessageList(MessageList &messageList, bool destructor);
private:
MessageList *const m_messageQueue1;
MessageList *const m_messageQueue2;
MessageList *m_messageQueueRead;
MessageList *m_messageQueueWrite;
Notification *m_notification;
};
// ======================================================================
#endif
@@ -0,0 +1,18 @@
//======================================================================
//
// MessageQueueDataTemplate.cpp
// copyright (c) 2002 Sony Online Entertainment
//
//======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/MessageQueueDataTemplate.h"
#include <string>
//======================================================================
MessageQueueDataTemplate<int> it;
MessageQueueDataTemplate<std::string> st;
//======================================================================
@@ -0,0 +1,57 @@
//======================================================================
//
// MessageQueueDataTemplate.h
// copyright (c) 2002 Sony Online Entertainment
//
//======================================================================
#ifndef INCLUDED_MessageQueueDataTemplate_H
#define INCLUDED_MessageQueueDataTemplate_H
#include "sharedFoundation/MessageQueue.h"
//======================================================================
template <typename T> class MessageQueueDataTemplate :
public MessageQueue::Data
{
public:
MessageQueueDataTemplate () :
MessageQueue::Data (),
m_data ()
{
}
explicit MessageQueueDataTemplate (const T & t) :
MessageQueue::Data (),
m_data (t)
{
}
const T & getData () const
{
return m_data;
}
T & getData ()
{
return m_data;
}
void setData (const T & t) const
{
m_data = t;
}
private:
MessageQueueDataTemplate (const MessageQueueDataTemplate & rhs);
MessageQueueDataTemplate & operator= (const MessageQueueDataTemplate & rhs);
T m_data;
};
//======================================================================
#endif
@@ -0,0 +1,394 @@
// ======================================================================
//
// Misc.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef MISC_H
#define MISC_H
// ======================================================================
/**
* Return the square of a number.
*
* This routine is templated, and implemented in terms of the * operator.
*
* @return The square of its argument
*/
template<class T>
inline T sqr(
const T &t // The number to square
)
{
return (t * t);
}
// ----------------------------------------------------------------------
/**
* Make sure value is between two values.
*
* This routine is templated, and implemented in terms of the > and > operators.
*
* @param minT Minimum variable
* @param t Variable to clamp against min and max
* @param maxT Minimum variable
* @return If t is less than min, return min; if t is greater than max, return max
* otherwise, return t
*/
template<class T>inline const T clamp(const T &minT, const T &t, const T &maxT)
{
DEBUG_FATAL(maxT < minT, ("clamp error: max value is less than min value"));
return (t < minT) ? minT : ((t > maxT) ? maxT : t);
}
// ----------------------------------------------------------------------
/**
* returns whether a value is within a given range, including the range end points.
*
* This routine will fatal in debug builds if max is less than min.
*
* @return True if value falls within the range min .. max, including min and max,
* false otherwise.
*/
template<class T>inline bool WithinRangeInclusiveInclusive(const T &rangeMin, const T &value, const T &rangeMax)
{
DEBUG_FATAL(rangeMax < rangeMin, ("range error: max value is less than min value"));
return (value >= rangeMin) && (value <= rangeMax);
}
// ----------------------------------------------------------------------
/**
* returns whether a value is within a given range, excluding the range end points.
*
* This routine will fatal in debug builds if max is less than min.
*
* @return True if value falls within the range min .. max, not including min and max,
* false otherwise.
*/
template<class T>inline bool WithinRangeExclusiveExclusive(const T &rangeMin, const T &value, const T &rangeMax)
{
DEBUG_FATAL(rangeMax < rangeMin, ("range error: max value is less than min value"));
return (value > rangeMin) && (value < rangeMax);
}
// ----------------------------------------------------------------------
/**
* returns true if a value falls within the range (base - epsilon) .. (base + epsilon),
* including range endpoints.
*
* This routine will fatal during debug builds if epsilon is less than zero.
*
* @return true if value is within the range (base - epsilon) .. (base + epsilon), including
* the range endpoints. Otherwise returns false.
*/
template<class T>inline bool WithinEpsilonInclusive(const T &base, const T &value, const T &epsilon)
{
DEBUG_FATAL(epsilon < static_cast<T>(0), ("error: epsilon is less than zero"));
return (value >= base - epsilon) && (value <= base + epsilon);
}
// ----------------------------------------------------------------------
/**
* returns true if a value falls within the range (base - epsilon) .. (base + epsilon),
* excluding range endpoints.
*
* This routine will fatal during debug builds if epsilon is less than zero.
*
* @return true if value is within the range (base - epsilon) .. (base + epsilon), including
* the range endpoints. Otherwise returns false.
*/
template<class T>inline bool WithinEpsilonExclusive(const T &base, const T &value, const T &epsilon)
{
DEBUG_FATAL(epsilon < static_cast<T>(0), ("error: epsilon is less than zero"));
return (value > base - epsilon) && (value < base + epsilon);
}
// ----------------------------------------------------------------------
/**
* Zero out an object.
*
* This routine is templated.
*
* This routine will byte-zero fill the object which is passed to it.
*
* @param t The object to zero out
*/
template<class T>inline void Zero(T &t)
{
memset(&t, 0, sizeof(t));
}
// ----------------------------------------------------------------------
/**
* Duplicate a string.
*
* This routine allocates memory for a copy of its argument, copies
* the source string into the new memory, and then returns a pointer to
* the new memory.
*
* This routine will return NULL if called with NULL.
*
* @param source The string to copy
* @return A pointer to a copy of the source argument
*/
inline char *DuplicateString(const char *source)
{
if (!source)
return NULL;
const uint length = strlen(source)+1;
char *result = NON_NULL (new char[length]);
memcpy(result, source, length);
return result;
}
// ----------------------------------------------------------------------
/**
* Duplicate a string.
*
* This routine allocates memory for a copy of its argument, copies
* the source string into the new memory, and then returns a pointer to
* the new memory.
*
* This routine will return NULL if called with NULL.
*
* @param source The string to copy
* @return A pointer to a copy of the source argument
*/
inline char *DuplicateStringWithToLower(const char *source)
{
if (!source)
return NULL;
const uint length = strlen(source)+1;
char *result = NON_NULL (new char[length]);
for (uint i = 0; i < length; ++i)
result[i] = static_cast<char>(tolower(source[i]));
return result;
}
// ----------------------------------------------------------------------
/**
* memset with a integer length.
*
* This routine will
*
* @param data Location to fill at
* @param value Vvalue to fill with
* @param length Number of bytes to fill
*/
inline void imemset(void *data, int value, int length)
{
DEBUG_FATAL(!data, ("null data arg"));
memset(data, value, static_cast<uint>(length));
}
// ----------------------------------------------------------------------
/**
* memcpy with a integer length.
*
* This routine will
*
* @param destination Location to copy to
* @param source Location to copy from
* @param length Number of bytes to copy
*/
inline void imemcpy(void *destination, const void *source, int length)
{
DEBUG_FATAL(!destination, ("null destination arg"));
DEBUG_FATAL(!source, ("null source arg"));
memcpy(destination, source, static_cast<uint>(length));
}
// ----------------------------------------------------------------------
/**
* memmove with a integer length.
*
* This routine will
*
* @param destination Location to copy to
* @param source Location to copy from
* @param length Number of bytes to copy
*/
inline void *memmove(void *destination, const void *source, int length)
{
DEBUG_FATAL(!destination, ("null destination arg"));
DEBUG_FATAL(!source, ("null source arg"));
return memmove(destination, source, static_cast<uint>(length));
}
// ----------------------------------------------------------------------
/**
* Returns the length of the string as an int.
*
* @param string String to compute the length
* @return The length of the string as an int
*/
inline int istrlen(const char *string)
{
DEBUG_FATAL(!string, ("null string arg"));
return static_cast<int>(strlen(string));
}
// ----------------------------------------------------------------------
/**
* Determine if a number is a power of two.
*
* This routine runs in O(1) time.
*
* @param value Value to see if it is a power of two
* @return True if the value is a power of two, otherwise false
*/
template<class T> inline bool IsPowerOfTwo(T value)
{
return ((value - 1) & (value)) == 0;
}
// ----------------------------------------------------------------------
/**
* Returns the number of bits set in an integral type.
*
* Type T must provide integral-type bitwise operations and semantics.
*
* @param value Value to count the number of bits
*/
template<class T> inline int GetBitCount(T value)
{
int count = 0;
while (value)
{
value &= (value-1);
++count;
}
return count;
}
// ----------------------------------------------------------------------
/**
* Returns the index of the first bit set in an integral type.
*
* Type T must provide integral-type bitwise operations and semantics.
*
* @param value Value to find the first set bit
* @return Returns the zero-based index of the first bit set in an
* integral type, with the least significant byte being index 0.
*
* Returns -1 if no bits are set in the value.
*/
template<class T>inline int GetFirstBitSet(T value)
{
if (!value)
return -1;
int count;
for (count = 0; !(value & static_cast<T>(0x01)); ++count, value >>= 1)
{}
return count;
}
// ----------------------------------------------------------------------
/**
* Calculate the factorial of the specified value.
*
* This routine takes O(n) time to compute.
*
* @param number The number to compute the factorial of
* @return The factorial of the specified value
*/
inline int factorial(int number)
{
int i, result;
for (result = 1, i = 2; i <= number; ++i)
result *= i;
return result;
}
// ----------------------------------------------------------------------
/**
* Calculate the number of combinations of i elements taken from a set of n elements.
*
* This routine computes: n! / (i! * (n-i)!).
*
* @param n Number of elements in the set
* @param i Number of elements to pick from the set
* @return The number of distinct combinations
*/
inline int choose(int n, int i)
{
return factorial(n) / (factorial(i) * factorial(n - i));
}
// ----------------------------------------------------------------------
/**
* Linear interpolate from start to end along t, where t is from 0..1.
*
* t must be from 0..1
*
* @return A value from start to end
*/
template<class T> const T linearInterpolate (const T& start, const T& end, const real t)
{
return static_cast<T>((end - start) * t) + start;
}
// ----------------------------------------------------------------------
/**
* A non-linear, smooth interpolation from start to end along t, where t is from 0..1.
*
* (-2 * (end - start) * t^3) + (3 * (end - start) * t^2) + start
*
* t must be from 0..1
*
* @return A value from start to end
*/
template<class T> const T cubicInterpolate(const T& start, const T& end, const real t)
{
real const tSquared = sqr(t);
real const tCubed = tSquared * t;
T const & diff = end - start;
return static_cast<T>((diff * (tCubed * static_cast<real>(-2))) + (diff * (tSquared * static_cast<real>(3))) + start);
}
// ----------------------------------------------------------------------
/**
* A lint-friendly boolean compare.
*
* @return A value from start to end
*/
inline bool boolEqual(bool const lhs, bool const rhs)
{
return (lhs && rhs) || (!lhs && !rhs);
}
// ======================================================================
#endif
@@ -0,0 +1,110 @@
// ======================================================================
//
// NetworkId.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/NetworkId.h"
#include <string>
#include <cstdio>
// ======================================================================
const NetworkId NetworkId::cms_invalid(static_cast<NetworkIdType>(0));
// buildout network id occupies the sign bit in the 8 byte signed NetworkId (i.e. buildout network id is negative)
// 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
// client side fake network id (in ClientObject.cpp) occupies the highest non-sign bit location in the 8 byte signed NetworkId
// 01000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
// the 8 bit cluster id occupies these bit locations in the 8 byte NetworkId
// 00111111 11000000 00000000 00000000 00000000 00000000 00000000 00000000
// other network id will occupy the remaining bits
// 00000000 00111111 11111111 11111111 11111111 11111111 11111111 11111111
const NetworkId::NetworkIdType NetworkId::cms_maxNetworkIdWithoutClusterId(0x3FFFFFFFFFFFFFll);
const NetworkId::NetworkIdType NetworkId::cms_networkIdWithoutClusterIdMask(0x403FFFFFFFFFFFFFll);
const NetworkId::NetworkIdType NetworkId::cms_clusterIdMask(0x3FC0000000000000ll);
// ======================================================================
NetworkId::NetworkId() :
m_value(0)
{
}
// -----------------------------------------------------------------------
NetworkId::NetworkId(NetworkIdType value) :
m_value(value)
{
}
// -----------------------------------------------------------------------
NetworkId::NetworkId(const NetworkId& source) :
m_value(source.getValue())
{
}
// -----------------------------------------------------------------------
NetworkId::~NetworkId()
{
}
// -----------------------------------------------------------------------
std::string NetworkId::getValueString() const
{
char tmp[256];
sprintf(tmp,INT64_FORMAT_SPECIFIER,m_value);
return tmp;
}
// ----------------------------------------------------------------------
NetworkId::NetworkId(const std::string &value) :
m_value(0)
{
sscanf(value.c_str(),INT64_FORMAT_SPECIFIER,&m_value);
}
// ----------------------------------------------------------------------
NetworkId::NetworkIdType NetworkId::getValueWithClusterId(uint8 const clusterId, NetworkIdType const validForConversionMin, NetworkIdType const validForConversionMax) const
{
if ((m_value < validForConversionMin) || (m_value > validForConversionMax) || (clusterId == 0) || (m_value == 0))
return m_value;
uint64 const uint64ClusterId = static_cast<uint64>(clusterId);
return static_cast<NetworkId::NetworkIdType>((uint64ClusterId << 54) | static_cast<uint64>(m_value));
}
// ----------------------------------------------------------------------
NetworkId::NetworkIdType NetworkId::getValueWithoutClusterId() const
{
if (m_value <= cms_maxNetworkIdWithoutClusterId)
return m_value;
return static_cast<NetworkId::NetworkIdType>(static_cast<uint64>(cms_networkIdWithoutClusterIdMask) & static_cast<uint64>(m_value));
}
// ----------------------------------------------------------------------
uint8 NetworkId::getValueClusterId() const
{
if (m_value <= cms_maxNetworkIdWithoutClusterId)
return 0;
return static_cast<uint8>((static_cast<uint64>(cms_clusterIdMask) & static_cast<uint64>(m_value)) >> 54);
}
// ======================================================================
@@ -0,0 +1,168 @@
// ======================================================================
//
// NetworkId.h
// Portions copyright 1999 Bootprint Entertainment
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_NetworkId_H
#define INCLUDED_NetworkId_H
namespace DB
{
class BindableNetworkId;
}
// ======================================================================
class NetworkId
{
public:
typedef int64 NetworkIdType;
static const NetworkId cms_invalid;
static const NetworkIdType cms_maxNetworkIdWithoutClusterId;
static const NetworkIdType cms_networkIdWithoutClusterIdMask;
static const NetworkIdType cms_clusterIdMask;
struct Hash;
friend struct NetworkId::Hash;
public:
NetworkId();
explicit NetworkId(NetworkIdType value);
explicit NetworkId(const std::string &value);
NetworkId(const NetworkId&);
~NetworkId();
NetworkIdType getValueWithClusterId(uint8 clusterId, NetworkIdType validForConversionMin, NetworkIdType validForConversionMax) const;
NetworkIdType getValueWithoutClusterId() const;
uint8 getValueClusterId() const;
NetworkIdType getValue() const;
std::string getValueString() const;
NetworkId& operator= (const NetworkId&);
bool operator< (const NetworkId& rhs) const;
bool operator== (const NetworkId& rhs) const;
bool operator!= (const NetworkId& rhs) const;
size_t getHashValue() const;
bool isValid() const;
bool operator !() const;
struct Hash
{
size_t operator()(const NetworkId & source) const
{
return source.getHashValue(); //TODO: make better hash function
};
};
private:
NetworkIdType m_value;
friend class DB::BindableNetworkId;
private:
explicit NetworkId(int value); // catch people who incorrectly try to construct one of these from an int
// also makes constructing one of these from any other incorrect numeric type ambiguous
};
// -----------------------------------------------------------------------
inline NetworkId::NetworkIdType NetworkId::getValue() const
{
return m_value;
}
// -----------------------------------------------------------------------
inline NetworkId& NetworkId::operator= (const NetworkId& rhs)
{
m_value = rhs.m_value;
return *this;
}
// -----------------------------------------------------------------------
inline bool NetworkId::operator< (const NetworkId& rhs) const
{
return m_value < rhs.m_value;
}
// -----------------------------------------------------------------------
inline bool NetworkId::operator== (const NetworkId& rhs) const
{
return m_value == rhs.m_value;
}
// -----------------------------------------------------------------------
inline bool NetworkId::operator!= (const NetworkId& rhs) const
{
return m_value != rhs.m_value;
}
// -----------------------------------------------------------------------
inline bool NetworkId::isValid () const
{
return m_value != 0;
}
// -----------------------------------------------------------------------
inline bool NetworkId::operator! () const
{
return m_value == 0;
}
//------------------------------------------------------------------------
inline size_t NetworkId::getHashValue () const
{
static uint32 const cs_randomValues[] =
{
0x904618ec,
0x95c2f264,
0xe55c30fe,
0x2c92d2d1,
0x8376930b,
0x17662d70,
0x2a785b31,
0x1e7c7281,
0x60bc4645,
0x9a0cdf8f,
0xa9bc133d,
0x0e9a17ec,
0xcd768a0d,
0xe03e104f,
0xecfab1bd,
0x764a3a6f
};
uint32 a = static_cast< uint32 >( m_value >> 32 );
uint32 b = static_cast< uint32 >( m_value & 0xffffffff );
return ( ( b * 0x10001 ) ^ a ) ^ cs_randomValues[ b & 0xf ] ; // multiply lower 32 by a large prime then XOR a then XOR some random value from table
}
// -----------------------------------------------------------------------
// STL standard hash function
namespace std
{
template <>
struct hash<NetworkId> // stl standard hash
{
size_t operator()(const NetworkId &x) const { return x.getHashValue(); }
};
}
#endif
@@ -0,0 +1,69 @@
// ======================================================================
//
// NetworkIdArchive.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/NetworkIdArchive.h"
#include "Archive/ByteStream.h"
#include "sharedFoundation/NetworkId.h"
// ======================================================================
namespace Archive
{
//-----------------------------------------------------------------------
void get(ReadIterator & source, uint64 & target)
{
source.get(&target, 8);
}
//-----------------------------------------------------------------------
void put(ByteStream & target, const uint64 & source)
{
target.put(&source, 8);
}
//-----------------------------------------------------------------------
void get(ReadIterator & source, int64 & target)
{
source.get(&target, 8);
}
//-----------------------------------------------------------------------
void put(ByteStream & target, const int64 & source)
{
target.put(&source, 8);
}
//-----------------------------------------------------------------------
void get(ReadIterator & source, NetworkId & target)
{
int64 id; // Using int64 instead of NetworkIdType so that we get a compile error if we change it
//source.get(&id,8); // because this line hard-codes the size
get(source, id);
target = NetworkId(id);
}
//-----------------------------------------------------------------------
void put(ByteStream & target, const NetworkId & source)
{
//uint64 tmp = source.getValue();
put(target, source.getValue());
//target.put(&tmp,8);
}
//-----------------------------------------------------------------------
}
// ======================================================================
@@ -0,0 +1,33 @@
// ======================================================================
//
// NetworkIdArchive.h
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_NetworkIdArchive_H
#define INCLUDED_NetworkIdArchive_H
// ======================================================================
class NetworkId;
// ======================================================================
namespace Archive
{
class ReadIterator;
class ByteStream;
void get(ReadIterator & source, uint64 & target);
void put(ByteStream & target, const uint64 & source);
void get(ReadIterator & source, int64 & target);
void put(ByteStream & target, const int64 & source);
void get(ReadIterator & source, NetworkId & target);
void put(ByteStream & target, const NetworkId & source);
}
// ======================================================================
#endif
@@ -0,0 +1,259 @@
// ======================================================================
//
// PersistentCrcString.cpp
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/PersistentCrcString.h"
#include "sharedFoundation/Crc.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/MemoryBlockManager.h"
#include "sharedFoundation/Os.h"
// ======================================================================
namespace PersistentCrcStringNamespace
{
void remove();
MemoryBlockManager * ms_fakeConstCharMemoryBlockManager = reinterpret_cast<MemoryBlockManager *>(0x01);
MemoryBlockManager * ms_memoryBlockManager8;
MemoryBlockManager * ms_memoryBlockManager16;
MemoryBlockManager * ms_memoryBlockManager32;
MemoryBlockManager * ms_memoryBlockManager48;
MemoryBlockManager * ms_memoryBlockManager64;
}
using namespace PersistentCrcStringNamespace;
// ======================================================================
PersistentCrcString const PersistentCrcString::empty("", CC_true);
// ======================================================================
void PersistentCrcString::install()
{
ms_memoryBlockManager8 = new MemoryBlockManager("PersistentCrcString8", true, 8, 0, 0, 0);
ms_memoryBlockManager16 = new MemoryBlockManager("PersistentCrcString16", true, 16, 0, 0, 0);
ms_memoryBlockManager32 = new MemoryBlockManager("PersistentCrcString32", true, 32, 0, 0, 0);
ms_memoryBlockManager48 = new MemoryBlockManager("PersistentCrcString48", true, 48, 0, 0, 0);
ms_memoryBlockManager64 = new MemoryBlockManager("PersistentCrcString64", true, 64, 0, 0, 0);
ExitChain::add(PersistentCrcStringNamespace::remove, "PersistentCrcStringNamespace::remove");
}
// ----------------------------------------------------------------------
void PersistentCrcStringNamespace::remove()
{
delete ms_memoryBlockManager8;
ms_memoryBlockManager8 = NULL;
delete ms_memoryBlockManager16;
ms_memoryBlockManager16 = NULL;
delete ms_memoryBlockManager32;
ms_memoryBlockManager32 = NULL;
delete ms_memoryBlockManager48;
ms_memoryBlockManager48 = NULL;
delete ms_memoryBlockManager64;
ms_memoryBlockManager64 = NULL;
}
// ======================================================================
PersistentCrcString::PersistentCrcString()
: CrcString(),
m_memoryBlockManager(NULL),
m_buffer(NULL)
{
DEBUG_FATAL(!ms_memoryBlockManager8, ("Constructing a PersistentCrcString before the class is installed"));
}
// ----------------------------------------------------------------------
PersistentCrcString::PersistentCrcString(CrcString const &rhs)
: CrcString(),
m_memoryBlockManager(NULL),
m_buffer(NULL)
{
DEBUG_FATAL(!ms_memoryBlockManager8, ("Constructing a PersistentCrcString before the class is installed"));
if (!rhs.isEmpty())
PersistentCrcString::set(rhs.getString(), rhs.getCrc());
}
// ----------------------------------------------------------------------
PersistentCrcString::PersistentCrcString(PersistentCrcString const &rhs)
: CrcString(), //lint !e1738 // non copy constructor used to initialize base class // this appears to be intentional.
m_memoryBlockManager(NULL),
m_buffer(NULL)
{
DEBUG_FATAL(!ms_memoryBlockManager8, ("Constructing a PersistentCrcString before the class is installed"));
if (!rhs.isEmpty())
PersistentCrcString::set(rhs.getString(), rhs.getCrc());
}
// ----------------------------------------------------------------------
PersistentCrcString::PersistentCrcString(char const * string, bool applyNormalize)
: CrcString(),
m_memoryBlockManager(NULL),
m_buffer(NULL)
{
DEBUG_FATAL(!ms_memoryBlockManager8, ("Constructing a PersistentCrcString before the class is installed"));
if (string)
PersistentCrcString::set(string, applyNormalize);
}
// ----------------------------------------------------------------------
PersistentCrcString::PersistentCrcString(char const * string, uint32 crc)
: CrcString(),
m_memoryBlockManager(NULL),
m_buffer(NULL)
{
DEBUG_FATAL(!ms_memoryBlockManager8, ("Constructing a PersistentCrcString before the class is installed"));
NOT_NULL(string);
PersistentCrcString::set(string, crc);
}
// ----------------------------------------------------------------------
PersistentCrcString::PersistentCrcString(char const * string, ConstChar)
: CrcString(),
m_memoryBlockManager(ms_fakeConstCharMemoryBlockManager),
m_buffer(const_cast<char *>(string))
{
#ifdef _DEBUG
DEBUG_FATAL(strlen(string)+1 >= Os::MAX_PATH_LENGTH, ("source string too long %d/%d",strlen(string)+1, Os::MAX_PATH_LENGTH));
char buffer[Os::MAX_PATH_LENGTH];
normalize(buffer, string);
DEBUG_FATAL(strcmp(string, buffer) != 0, ("source string was not normalized"));
#endif
calculateCrc();
}
// ----------------------------------------------------------------------
PersistentCrcString::~PersistentCrcString()
{
if (!ms_memoryBlockManager8 && m_memoryBlockManager && m_memoryBlockManager != ms_fakeConstCharMemoryBlockManager)
{
DEBUG_FATAL(true, ("Destructing a PersistentCrcString after the class was removed"));
}
internalFree();
}
// ----------------------------------------------------------------------
char const * PersistentCrcString::getString() const
{
return m_buffer ? m_buffer : "";
}
// ----------------------------------------------------------------------
void PersistentCrcString::internalFree()
{
if (m_buffer)
{
if (m_memoryBlockManager)
{
if (m_memoryBlockManager == ms_fakeConstCharMemoryBlockManager)
{
m_memoryBlockManager = NULL;
}
else
{
m_memoryBlockManager->free(m_buffer);
m_memoryBlockManager = NULL;
}
}
else
delete [] m_buffer;
m_buffer = NULL;
}
}
// ----------------------------------------------------------------------
void PersistentCrcString::clear()
{
internalFree();
m_crc = Crc::crcNull;
}
// ----------------------------------------------------------------------
void PersistentCrcString::internalSet(char const * string, bool applyNormalize)
{
internalFree();
const int stringLength = istrlen(string) + 1;
DEBUG_FATAL(stringLength > Os::MAX_PATH_LENGTH, ("string too long for a filename"));
m_memoryBlockManager = NULL;
if (stringLength <= 8)
m_memoryBlockManager = ms_memoryBlockManager8;
else
if (stringLength <= 16)
m_memoryBlockManager = ms_memoryBlockManager16;
else
if (stringLength <= 32)
m_memoryBlockManager = ms_memoryBlockManager32;
else
if (stringLength <= 48)
m_memoryBlockManager = ms_memoryBlockManager48;
else
if (stringLength <= 64)
m_memoryBlockManager = ms_memoryBlockManager64;
if (m_memoryBlockManager)
m_buffer = reinterpret_cast<char *>(m_memoryBlockManager->allocate());
else
m_buffer = new char[static_cast<size_t>(stringLength)];
if (applyNormalize)
normalize(m_buffer, string);
else
strcpy(m_buffer, string);
}
// ----------------------------------------------------------------------
void PersistentCrcString::set(char const * string, bool applyNormalize)
{
NOT_NULL(string);
internalSet(string, applyNormalize);
calculateCrc();
}
// ----------------------------------------------------------------------
void PersistentCrcString::set(char const * string, uint32 crc)
{
NOT_NULL(string);
internalSet(string, false);
m_crc = crc;
}
//----------------------------------------------------------------------
PersistentCrcString const & PersistentCrcString::operator=(PersistentCrcString const & rhs)
{
if (this != &rhs)
CrcString::set(rhs);
return *this;
} //lint !e1539 //m_buffer not assigned
// ======================================================================
@@ -0,0 +1,69 @@
// ======================================================================
//
// PersistentCrcString.h
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_PersistentCrcString_H
#define INCLUDED_PersistentCrcString_H
// ======================================================================
class MemoryBlockManager;
#include "sharedFoundation/CrcString.h"
// ======================================================================
class PersistentCrcString : public CrcString
{
public:
static PersistentCrcString const empty;
public:
static void install();
public:
PersistentCrcString();
DLLEXPORT explicit PersistentCrcString(CrcString const & rhs);
PersistentCrcString(PersistentCrcString const & rhs);
PersistentCrcString(char const * string, bool applyNormalize);
PersistentCrcString(char const * string, uint32 crc);
virtual DLLEXPORT ~PersistentCrcString();
virtual char const * getString() const;
virtual void clear();
virtual void set(char const * string, bool applyNormalize);
virtual void set(char const * string, uint32 crc);
PersistentCrcString const & operator=(PersistentCrcString const & rhs);
protected:
enum ConstChar
{
CC_true
};
PersistentCrcString(char const * string, ConstChar);
private:
void internalFree();
void internalSet(char const * string, bool applyNormalize);
private:
MemoryBlockManager * m_memoryBlockManager;
char * m_buffer;
};
// ======================================================================
#endif
@@ -0,0 +1,85 @@
// ======================================================================
//
// PointerDeleter.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef POINTER_DELETER_H
#define POINTER_DELETER_H
// ======================================================================
#include <utility>
// ======================================================================
/**
* Delete the argument.
*
* The argument must be a pointer type.
*/
class PointerDeleter
{
public:
template <typename PointerType>
void operator ()(PointerType pointer) const
{
delete pointer;
}
};
// ======================================================================
/**
* Delete the argument using array-style deletion (i.e. delete [] object).
*
* The argument must be a pointer type.
*/
class ArrayPointerDeleter
{
public:
template <typename PointerType>
void operator ()(PointerType pointer) const
{
delete [] pointer;
}
};
// ======================================================================
/**
* Delete the argument's second member variable.
*
* The passed in argument must be of template type std::pair.
*/
class PointerDeleterPairSecond
{
public:
template <typename FirstType, typename SecondType>
void operator ()(std::pair<FirstType, SecondType> &pairArgument) const
{
delete pairArgument.second;
}
};
// ======================================================================
/**
* Delete the argument's second member variable using array-style deletion.
*
* The passed in argument must be of template type std::pair.
*/
class ArrayPointerDeleterPairSecond
{
public:
template <typename FirstType, typename SecondType>
void operator ()(std::pair<FirstType, SecondType> &pairArgument) const
{
delete [] pairArgument.second;
}
};
// ======================================================================
#endif
@@ -0,0 +1,21 @@
//===================================================================
//
// Production.h
// copyright 2002, sony online entertainment
//
//===================================================================
#ifndef INCLUDED_Production_H
#define INCLUDED_Production_H
//===================================================================
#if DEBUG_LEVEL == 0
#define PRODUCTION 1 //-- production
#else
#define PRODUCTION 0 //-- development
#endif
//===================================================================
#endif
@@ -0,0 +1,35 @@
// ======================================================================
//
// SafeCast.h
// Copyright 2001, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_SafeCast_H
#define INCLUDED_SafeCast_H
// ======================================================================
#if DEBUG_LEVEL == DEBUG_LEVEL_RELEASE
#define safe_cast static_cast
#else
template <typename T, typename U>
T safe_cast(U u)
{
if (!u)
return 0;
T t = dynamic_cast<T>(u);
NOT_NULL(t);
return t;
}
#endif
// ======================================================================
#endif
@@ -0,0 +1,203 @@
// ======================================================================
//
// Scheduler.cpp
// Copyright 2000 - 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/Scheduler.h"
#include "sharedFoundation/StaticCallbackEntry.h"
#include <queue>
#include <set>
#include <vector>
//-----------------------------------------------------------------------
/** @brief construct a new Scheduler object
A system may have any number of schedulers running. Periodically
invoke update(const unsigned long) on the Scheduler instance to
trigger callback events.
\code
class MyWorld
{
public:
static void update()
{
instance().worldScheduler.update(Clock::timeMs());
}
private:
static MyWorld & instance()
{
static MyWorld world;
return world;
}
Scheduler worldScheduler;
};
inst main(int, char **)
{
while(true)
{
MyWorld::update();
}
return 0;
}
\endcode
@author Justin Randall
*/
Scheduler::Scheduler() :
deferredCallbackEntryAdditions(new std::vector<StaticCallbackEntry *>),
callbackQueue(new std::priority_queue<StaticCallbackEntry *, std::vector<StaticCallbackEntry *, std::allocator<StaticCallbackEntry *> >, StaticCallbackEntry::Compare>),
currentCount(0),
updating(false)
{
}
//-----------------------------------------------------------------------
Scheduler::~Scheduler()
{
StaticCallbackEntry * c;
while(!callbackQueue->empty())
{
c = callbackQueue->top();
delete c;
callbackQueue->pop();
}
delete callbackQueue;
std::vector<StaticCallbackEntry *>::iterator i = deferredCallbackEntryAdditions->begin();
for (; i != deferredCallbackEntryAdditions->end(); ++i)
{
delete *i;
}
deferredCallbackEntryAdditions->clear();
delete deferredCallbackEntryAdditions;
}
//-----------------------------------------------------------------------
/**
@brief Register a callback entry with the priority queue
Used internally in a few places to register StaticCallbackEntry object
pointers with the CallbackEntrySet priority queue.
@param callback A StaticCallbackEntry object that contains callback
information such as a callback function pointer and
expire count.
@author Justin Randall
*/
void Scheduler::addCallback(StaticCallbackEntry * callback)
{
// if the scheduler is in the middle of an update, ensure that
// the callback is not added THIS frame (prevent infiniet callback loops
// through long loop times or zero callback times)
if(updating)
deferredCallbackEntryAdditions->push_back(callback);
else
callbackQueue->push(callback);
}
//-----------------------------------------------------------------------
/**
@brief The guts of the Scheduler. Request the next callback request
for a static function.
The Scheduler may make callbacks on object member function pointers
as well as static function pointers. When the Scheduler is updated
with a value greater than (when + Scheduler::currentCount) it will
invoke the supplied function.
@param cb a static function pointer
@param context the context for the callback function.
@param delay Used to calculate the expire count/time for the
callback. The current count of the scheduler is
added to 'delay', then the callback is inserted
into the scheduler's priority queue, sorted by
the calculated absolute time.
\code
Scheduler globalScheduler;
void foo()
{
globalScheduler.setCallback(bar, 1000);
}
void bar()
{
globalScheduler.setCallback(foo, 500);
}
\encode
@author Justin Randall
*/
void Scheduler::setCallback(Callback cb, const void *context, unsigned long delay)
{
addCallback(new StaticCallbackEntry(getCurrentCount() + delay, cb, context));
}
//-----------------------------------------------------------------------
/** @brief Trigger pending callbacks
A scheduler must be periodically updated to trigger callback events
that are enqueued. A single unsigned long parameter is passed to the
Scheduler indicating the current "time" or "frame" or some other
value that ensures all callbacks with an expireCount value less than
t will be triggered.
@param t The "time" or "frame" that triggers callbacks with expireCounts
less than t.
\code
int main(int, char **)
{
Scheduler s;
while(1)
{
s.update(Clock::timeMs());
}
return 0;
}
\endcode
@author Justin Randall
*/
void Scheduler::update(const unsigned long t)
{
// prevent recursive updates on a scheduler
if(!updating)
{
updating = true;
currentCount = t;
StaticCallbackEntry * c;
while( (!callbackQueue->empty()) && (c = callbackQueue->top())->getExpireCount() <= currentCount)
{
c->expired();
delete c;
callbackQueue->pop();
}
updating = false;
if(!deferredCallbackEntryAdditions->empty())
{
std::vector<StaticCallbackEntry *>::iterator i;
for(i = deferredCallbackEntryAdditions->begin(); i != deferredCallbackEntryAdditions->end(); ++i)
{
addCallback((*i));
}
deferredCallbackEntryAdditions->clear();
}
}
}
//-----------------------------------------------------------------------
@@ -0,0 +1,121 @@
// ======================================================================
//
// Scheduler.h
// Copyright 2000 - 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef _INCLUDED_Scheduler_H
#define _INCLUDED_Scheduler_H
// ======================================================================
#include "sharedFoundation/StaticCallbackEntry.h"
//-----------------------------------------------------------------------
/** @brief Engine scheduler
A scheduler is a priority queue containing callbacks, which in turn
contain pointers to member functions which are executed when the
callback is ready for processing.
The scheduler is updated with an arbitrary, unsigned long value. This
value is used to examine a priority queue of callback entries. If
the top element in the priority queue has an expireCount member that
is less than the current count (passed to the scheduler update()),
it is popped. If the object it refers to (or static callback function)
is valid, it will invoke the requested callback.
This process is repeated until the top element in the priority queue
has an expireCount greater than the current count.
To avoid infinite loops, a callback is never re-inserted in the
queue during the queue update. If the Scheduler instance is updating,
re-insertions are deferred, and the next earliest opportunity a
callback could occur is during the NEXT update to the scheduler.
\code
class MyObject : public Object
{
public:
MyObject::MyObject() :
{
World::getObjectScheduler().setCallback(this, &MyObject::myExpireFunction, 1000);
}
MyObject::~MyObject()
{
}
private:
void myExpireFunction()
{
World::killObject(this); // destroy this object now!
}
};
void World::update()
{
// each MyObject will put itself on the world kill list
// 1000 milliseconds after creation. They will be placed on
// the list during the scheduler update when MyObject::myExpireFunction
// is invoked.
World::objectScheduler.update(Clock::timeMs());
}
\endcode
@author Justin Randall
*/
class Scheduler
{
public:
typedef void (*Callback)(const void*);
public:
Scheduler();
~Scheduler ();
void setCallback (Callback cb, const void *context, unsigned long delay);
const unsigned long getCurrentCount () const;
void update (const unsigned long currentCount);
private:
void addCallback(StaticCallbackEntry * callback);
// Disabled.
Scheduler & operator = (const Scheduler & rhs);
Scheduler(const Scheduler & source);
private:
stdvector<StaticCallbackEntry *>::fwd * deferredCallbackEntryAdditions;
stdpriority_queue<StaticCallbackEntry *, std::vector<StaticCallbackEntry *, std::allocator<StaticCallbackEntry *> >, StaticCallbackEntry::Compare>::fwd * callbackQueue;
private:
unsigned long currentCount;
bool updating;
};
//-----------------------------------------------------------------------
/** @brief Return the current expire counter for the current/most recent
update frame.
currentCount is updated when Scheduler::update() is invoked. It is set
to the value of the update parameter. This value is used to determine
which items in the priority queue should be executed next.
@author Justin Randall
*/
inline const unsigned long Scheduler::getCurrentCount() const
{
return currentCount;
}
//-----------------------------------------------------------------------
#endif // _INCLUDED_Scheduler_H
@@ -0,0 +1,45 @@
// ======================================================================
//
// StaticCallbackEntry.cpp
// Copyright 2000 - 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/StaticCallbackEntry.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/MemoryBlockManager.h"
// ======================================================================
MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(StaticCallbackEntry, true, 0, 0, 0);
// ======================================================================
StaticCallbackEntry::StaticCallbackEntry(unsigned long when, Callback cb, const void *context) :
m_expireCount(when),
m_staticCallbackFunction(cb),
m_context(context)
{
}
//-----------------------------------------------------------------------
StaticCallbackEntry::~StaticCallbackEntry()
{
// This instance doesn't own these pointers.
m_staticCallbackFunction = 0;
m_context = 0;
}
//-----------------------------------------------------------------------
void StaticCallbackEntry::expired() const
{
if(m_staticCallbackFunction)
m_staticCallbackFunction(m_context);
}
// ======================================================================
@@ -0,0 +1,88 @@
// ======================================================================
//
// StaticCallbackEntry.h
// Copyright 2000 - 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef _INCLUDED_StaticCallbackEntry_H
#define _INCLUDED_StaticCallbackEntry_H
// ======================================================================
#include "sharedFoundation/MemoryBlockManagerMacros.h"
class MemoryBlockManager;
// ======================================================================
/** @brief A class used by Scheduler to invoke a callback on a static
function.
*/
class StaticCallbackEntry
{
MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL;
public:
typedef void (*Callback)(const void *context);
struct Compare
{
bool operator ()(const StaticCallbackEntry * lhs, const StaticCallbackEntry * rhs) const;
};
public:
StaticCallbackEntry(unsigned long when, Callback cb, const void *context);
~StaticCallbackEntry();
unsigned long getExpireCount() const;
void expired() const;
private:
struct StaticCallbackEntryFreeList;
friend struct StaticCallbackEntryFreeList;
private:
static stdvector<StaticCallbackEntry *>::fwd & getStaticCallbackFreeList();
private:
// Disabled.
StaticCallbackEntry(const StaticCallbackEntry &);
StaticCallbackEntry & operator = (const StaticCallbackEntry &);
private:
unsigned long m_expireCount;
Callback m_staticCallbackFunction;
const void *m_context;
};
// ======================================================================
/** @return the expiration count ("time", "frame", whatever) of the callback.
*/
inline unsigned long StaticCallbackEntry::getExpireCount() const
{
return m_expireCount;
}
// ======================================================================
inline bool StaticCallbackEntry::Compare::operator ()(const StaticCallbackEntry * lhs, const StaticCallbackEntry * rhs) const
{
NOT_NULL(lhs);
NOT_NULL(rhs);
return lhs->getExpireCount() > rhs->getExpireCount();
}
// ======================================================================
#endif // _INCLUDED_StaticCallbackEntry_H
@@ -0,0 +1,17 @@
// ======================================================================
//
// StationId.h
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_StationId_H
#define INCLUDED_StationId_H
// ======================================================================
typedef uint32 StationId;
// ======================================================================
#endif
@@ -0,0 +1,131 @@
// ======================================================================
//
// StlForwardDeclaration.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_StlForwardDeclaration_H
#define INCLUDED_StlForwardDeclaration_H
// ======================================================================
// Setup handling for template value defaults that require accessing the
// {template type}::fwd value. gcc 3.2 requires typename here, gcc 2.95
// optionally accepts typename here, msvc 6 will not accept it here.
#if defined(PLATFORM_WIN32) || defined(WIN32)
#define FORWARD_TYPENAME
#elif defined(PLATFORM_LINUX)
#define FORWARD_TYPENAME typename
#else
#error unsupported platform
#endif
// ======================================================================
// grab stlport configuration
#include "stl/_config.h"
namespace std
{
template <class _Tp> struct less;
template <class _Tp> struct equal_to;
template <class _T1, class _T2> struct pair;
template <class _T1> struct hash;
template <class _Tp> class allocator;
template <class _CharT, class _Traits, class _Alloc> class basic_string;
template <class _CharT> class char_traits;
template <size_t _Nb> class bitset;
template <class _Tp, class _Alloc> class deque;
template <class _Tp, class _Alloc> class list;
template <class _Tp, class _Alloc> class queue;
template <class _Tp, class _Alloc> class vector;
template <class _Tp, class _Sequence> class stack;
template <class _Tp, class _Container, class _Compare> class priority_queue;
template <class _Key, class _Tp, class _Compare, class _Alloc> class map;
template <class _Key, class _Tp, class _HashFcn, class _Compare, class _Alloc> class hash_map;
template <class _Key, class _Tp, class _Compare, class _Alloc> class multimap;
template <class _Key, class _Compare, class _Alloc> class set;
template <class _Key, class _HashFcn, class _Compare, class _Alloc> class hash_set;
template <class _Key, class _Compare, class _Alloc> class multiset;
typedef basic_string<char, char_traits<char>, allocator<char> > string;
}
template <class _Tp, class _Alloc = std::allocator<_Tp> > struct stddeque
{
typedef std::deque<_Tp, _Alloc> fwd;
};
template <class _Tp, class _Alloc = std::allocator<_Tp> > struct stdlist
{
typedef std::list<_Tp, _Alloc> fwd;
};
template <class _Key, class _Tp, class _Compare = std::less<_Key>, class _Alloc = std::allocator< std::pair <const _Key, _Tp> > > struct stdmap
{
typedef std::map<_Key, _Tp, _Compare, _Alloc> fwd;
};
template <class _Key, class _Tp, class _HashFcn = std::hash<_Key>, class _Compare = std::equal_to<_Key>, class _Alloc = std::allocator< std::pair <const _Key, _Tp> > > struct stdhash_map
{
typedef std::hash_map<_Key, _Tp, _HashFcn, _Compare, _Alloc> fwd;
};
template <class _Key, class _Tp, class _Compare = std::less<_Key>, class _Alloc = std::allocator< std::pair <const _Key, _Tp> > > struct stdmultimap
{
typedef std::multimap<_Key, _Tp, _Compare, _Alloc> fwd;
};
template <class _Key, class _Compare = std::less<_Key>, class _Alloc = std::allocator<_Key> > struct stdset
{
typedef std::set<_Key, _Compare, _Alloc> fwd;
};
template <class _Key, class _HashFcn = std::hash<_Key>, class _Compare = std::equal_to<_Key>, class _Alloc = std::allocator<_Key> > struct stdhash_set
{
typedef std::hash_set<_Key, _HashFcn, _Compare, _Alloc> fwd;
};
template <class _Key, class _Compare = std::less<_Key>, class _Alloc = std::allocator<_Key> > struct stdmultiset
{
typedef std::multiset<_Key, _Compare, _Alloc> fwd;
};
template <class _Tp, class _Alloc = std::allocator<_Tp> > struct stdvector
{
typedef std::vector<_Tp, _Alloc> fwd;
};
template <class _Tp, class _Container = FORWARD_TYPENAME stdvector<_Tp>::fwd, class _Compare = std::less<typename _Container::value_type> > struct stdpriority_queue
{
typedef std::priority_queue<_Tp, _Container, _Compare> fwd;
};
template <class _Tp, class _Sequence = FORWARD_TYPENAME stddeque<_Tp>::fwd > struct stdqueue
{
typedef std::queue<_Tp, _Sequence> fwd;
};
template <class _Tp, class _Sequence = FORWARD_TYPENAME stddeque<_Tp>::fwd > struct stdstack
{
typedef std::stack<_Tp, _Sequence> fwd;
};
namespace Unicode
{
typedef unsigned short unicode_char_t;
typedef std::basic_string<unicode_char_t, std::char_traits<unicode_char_t>, std::allocator<unicode_char_t> > String;
}
// ======================================================================
#endif
@@ -0,0 +1,45 @@
// ======================================================================
//
// StringCompare.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_StringCompare_H
#define INCLUDED_StringCompare_H
// ======================================================================
#include <cstring>
// ======================================================================
/// A functor used to allow storing of char* in maps with value lookups
class StringCompare
{
public:
inline bool operator() (const char*, const char*) const;
};
inline bool StringCompare::operator() (const char *lhs, const char *rhs) const
{
return static_cast<bool>(strcmp(lhs, rhs) < 0);
}
// ======================================================================
/// A functor used to allow storing of case insensitive char* in maps with value lookups
class StringCaseCompare
{
public:
inline bool operator() (const char*, const char*) const;
};
inline bool StringCaseCompare::operator() (const char *lhs, const char *rhs) const
{
return static_cast<bool>(_stricmp(lhs, rhs) < 0);
}
// ======================================================================
#endif
@@ -0,0 +1,289 @@
// ======================================================================
//
// Tag.h
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#ifndef TAG_H
#define TAG_H
// ======================================================================
#define TAG_DIGIT_NULL 00
#define TAG_DIGIT_SPACE 20
#define TAG_DIGIT_0 30
#define TAG_DIGIT_1 31
#define TAG_DIGIT_2 32
#define TAG_DIGIT_3 33
#define TAG_DIGIT_4 34
#define TAG_DIGIT_5 35
#define TAG_DIGIT_6 36
#define TAG_DIGIT_7 37
#define TAG_DIGIT_8 38
#define TAG_DIGIT_9 39
#define TAG_DIGIT_A 41
#define TAG_DIGIT_B 42
#define TAG_DIGIT_C 43
#define TAG_DIGIT_D 44
#define TAG_DIGIT_E 45
#define TAG_DIGIT_F 46
#define TAG_DIGIT_G 47
#define TAG_DIGIT_H 48
#define TAG_DIGIT_I 49
#define TAG_DIGIT_J 4A
#define TAG_DIGIT_K 4B
#define TAG_DIGIT_L 4C
#define TAG_DIGIT_M 4D
#define TAG_DIGIT_N 4E
#define TAG_DIGIT_O 4F
#define TAG_DIGIT_P 50
#define TAG_DIGIT_Q 51
#define TAG_DIGIT_R 52
#define TAG_DIGIT_S 53
#define TAG_DIGIT_T 54
#define TAG_DIGIT_U 55
#define TAG_DIGIT_V 56
#define TAG_DIGIT_W 57
#define TAG_DIGIT_X 58
#define TAG_DIGIT_Y 59
#define TAG_DIGIT_Z 5A
#define TAG_DIGIT__ 5f
#define TAG_DIGIT_a 61
#define TAG_DIGIT_b 62
#define TAG_DIGIT_c 63
#define TAG_DIGIT_d 64
#define TAG_DIGIT_e 65
#define TAG_DIGIT_f 66
#define TAG_DIGIT_g 67
#define TAG_DIGIT_h 68
#define TAG_DIGIT_i 69
#define TAG_DIGIT_j 6A
#define TAG_DIGIT_k 6B
#define TAG_DIGIT_l 6C
#define TAG_DIGIT_m 6D
#define TAG_DIGIT_n 6E
#define TAG_DIGIT_o 6F
#define TAG_DIGIT_p 70
#define TAG_DIGIT_q 71
#define TAG_DIGIT_r 72
#define TAG_DIGIT_s 73
#define TAG_DIGIT_t 74
#define TAG_DIGIT_u 75
#define TAG_DIGIT_v 76
#define TAG_DIGIT_w 77
#define TAG_DIGIT_x 78
#define TAG_DIGIT_y 79
#define TAG_DIGIT_z 7A
// ======================================================================
typedef uint32 Tag;
// ======================================================================
#define TAG_B(a,b,c,d) 0x ## a ## b ## c ## d
#define TAG_A(a,b,c,d) static_cast<Tag>(TAG_B(a,b,c,d))
#define TAG(a,b,c,d) TAG_A(TAG_DIGIT_ ## a, TAG_DIGIT_ ## b, TAG_DIGIT_ ## c, TAG_DIGIT_ ## d)
#define TAG3(a,b,c) TAG_A(TAG_DIGIT_ ## a, TAG_DIGIT_ ## b, TAG_DIGIT_ ## c, TAG_DIGIT_SPACE)
#define TAG2(a,b) TAG_A(TAG_DIGIT_ ## a, TAG_DIGIT_ ## b, TAG_DIGIT_SPACE, TAG_DIGIT_SPACE)
#define TAG1(a) TAG_A(TAG_DIGIT_ ## a, TAG_DIGIT_SPACE, TAG_DIGIT_SPACE, TAG_DIGIT_SPACE)
#define TAG03(a,b,c) TAG_A(TAG_DIGIT_ ## a, TAG_DIGIT_ ## b, TAG_DIGIT_ ## c, TAG_DIGIT_NULL)
#define TAG02(a,b) TAG_A(TAG_DIGIT_ ## a, TAG_DIGIT_ ## b, TAG_DIGIT_NULL, TAG_DIGIT_NULL)
#define TAG01(a) TAG_A(TAG_DIGIT_ ## a, TAG_DIGIT_NULL, TAG_DIGIT_NULL, TAG_DIGIT_NULL)
// ======================================================================
/**
* Convert a text string to a Tag
*
* This routine will convert a text string, such as "ABCD", to the tag value 'ABCD'.
* If the string is less than 4 characters long, it will be padded with spaces.
* If the string is greater than 4 characters long, it will be truncated.
*
* @param value string to convert to a Tag.
*/
inline Tag ConvertStringToTag(const char *value)
{
Tag result = 0;
const int length = strlen(value);
for (int i = 0; i < 4; ++i)
{
const uint32 ch = static_cast<uint32>((i >= length) ? ' ' : value[i]);
result = (result << 8) | ch;
}
return result;
}
// ----------------------------------------------------------------------
/**
* Convert an integer to a Tag
*
* This routine will convert an int, such as 4, to the tag value '0004'.
*
* @param value value to convert to tag format
*/
inline Tag ConvertIntToTag(int value)
{
Tag result = 0;
DEBUG_FATAL(value < 0 || value > 9999, ("value out of range 0/%d/9999", value));
for (int i = 0; i < 4; ++i)
{
const uint digit = static_cast<uint>(static_cast<int>(value % 10));
value /= 10;
result |= (digit + '0') << (i * 8);
}
return result;
}
// ----------------------------------------------------------------------
/**
* Print the specified tag into a text buffer.
*
* This routine will fill the first four characters of the specified character
* array with the name of the specified tag. If a character of the tag
* is not printable, it will be replaced with a question mark.
*
* A null-character will be appended to the output buffer.
*
* This routine assumes the specified character buffer is at least 5 characters
* in length.
*
* @param tag Tag to format
* @param buffer Character array to format the tag into
*/
inline void ConvertTagToString(Tag tag, char *buffer)
{
int i, j, ch;
DEBUG_FATAL(!buffer, ("buffer is null"));
for (i = 0, j = 24; i < 4; ++i, j -= 8)
{
ch = (static_cast<int>(tag) >> j) & 0xff; //lint !e702 // shift right of a signed quantity
if (isprint(ch))
buffer[i] = static_cast<char>(ch);
else
buffer[i] = '?';
}
buffer[4] = 0;
}
// ----------------------------------------------------------------------
/**
* Convert the specified tag to an int.
*
* This routine will attempt to create an integer using as
* many of least significant bytes of the tag as possible.
*
* Example: TAG(0,1,0,0) == 100
* Example: TAG(1,R,1,0) == 10
* Example: TAG(1,R,1,X) == 0
*
* @param tag Tag to format
* @return Integer form of tag string.
*/
inline int ConvertTagSuffixToInt(Tag tag)
{
int returnValue=0;
for (int i=24;i>=0;i-=8)
{
const int c = (tag>>i) & 0xff;
if (c>='0' && c<='9')
{
returnValue = returnValue*10 + int(c) -'0';
}
else
{
returnValue=0;
}
}
return returnValue;
}
// ----------------------------------------------------------------------
/**
* Convert the specified tag to an int.
*
* This routine will attempt to create an integer from
* a tag containing only numeric characters. If non-numeric
* characters are detected, 0 is returned.
*
* Example: TAG(0,1,0,0) == 100
* Example: TAG(1,R,1,0) == 0
* Example: TAG(1,R,1,X) == 0
*
* @param tag Tag to format
* @return Integer form of tag string.
*/
inline int ConvertTagToInt(Tag tag)
{
int returnValue=0;
for (int i=24;i>=0;i-=8)
{
const int c = (tag>>i) & 0xff;
if (c>='0' && c<='9')
{
returnValue = returnValue*10 + int(c) -'0';
}
else
{
return 0;
}
}
return returnValue;
}
// ======================================================================
const Tag TAG_0000 = TAG(0,0,0,0);
const Tag TAG_0001 = TAG(0,0,0,1);
const Tag TAG_0002 = TAG(0,0,0,2);
const Tag TAG_0003 = TAG(0,0,0,3);
const Tag TAG_0004 = TAG(0,0,0,4);
const Tag TAG_0005 = TAG(0,0,0,5);
const Tag TAG_0006 = TAG(0,0,0,6);
const Tag TAG_0007 = TAG(0,0,0,7);
const Tag TAG_0008 = TAG(0,0,0,8);
const Tag TAG_0009 = TAG(0,0,0,9);
const Tag TAG_0010 = TAG(0,0,1,0);
const Tag TAG_0011 = TAG(0,0,1,1);
const Tag TAG_0012 = TAG(0,0,1,2);
const Tag TAG_0013 = TAG(0,0,1,3);
const Tag TAG_0014 = TAG(0,0,1,4);
const Tag TAG_0015 = TAG(0,0,1,5);
const Tag TAG_DATA = TAG(D,A,T,A);
const Tag TAG_ENTR = TAG(E,N,T,R);
const Tag TAG_FORM = TAG(F,O,R,M);
const Tag TAG_INFO = TAG(I,N,F,O);
const Tag TAG_ARRY = TAG(A,R,R,Y);
const Tag TAG_NAME = TAG(N,A,M,E);
const Tag TAG_PARM = TAG(P,A,R,M);
//-- please do not add any Tags to this file unless they are generic
//-- and expected to be used in many different contexts
// ======================================================================
#endif
@@ -0,0 +1,110 @@
// ======================================================================
//
// TemporaryCrcString.cpp
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/TemporaryCrcString.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/Crc.h"
// ======================================================================
TemporaryCrcString::TemporaryCrcString()
: CrcString()
{
// this is to avoid including Os in the header file
DEBUG_FATAL(static_cast<int>(BUFFER_SIZE) != static_cast<int>(Os::MAX_PATH_LENGTH), ("Os::MAX_PATH_LENGTH and BUFFER_SIZE differ"));
m_buffer[0] = '\0';
}
// ----------------------------------------------------------------------
/**
* Copy constructor.
*
* TRF needed this to allow useful sanity checking with std::set<TemporaryCrcString>.
*/
TemporaryCrcString::TemporaryCrcString(const TemporaryCrcString &rhs)
: CrcString()
{
set(rhs.getString(), rhs.getCrc());
}
// ----------------------------------------------------------------------
TemporaryCrcString::TemporaryCrcString(char const * string, bool applyNormalize)
: CrcString()
{
// this is to avoid including Os in the header file
DEBUG_FATAL(static_cast<int>(BUFFER_SIZE) != static_cast<int>(Os::MAX_PATH_LENGTH), ("Os::MAX_PATH_LENGTH and BUFFER_SIZE differ"));
set(string, applyNormalize);
}
// ----------------------------------------------------------------------
TemporaryCrcString::TemporaryCrcString(char const * string, uint32 crc)
: CrcString()
{
// this is to avoid including Os in the header file
DEBUG_FATAL(static_cast<int>(BUFFER_SIZE) != static_cast<int>(Os::MAX_PATH_LENGTH), ("Os::MAX_PATH_LENGTH and BUFFER_SIZE differ"));
set(string, crc);
}
// ----------------------------------------------------------------------
TemporaryCrcString::~TemporaryCrcString()
{
}
// ----------------------------------------------------------------------
char const * TemporaryCrcString::getString() const
{
return m_buffer;
}
// ----------------------------------------------------------------------
void TemporaryCrcString::clear()
{
m_buffer[0] = '\0';
m_crc = Crc::crcNull;
}
// ----------------------------------------------------------------------
void TemporaryCrcString::internalSet(char const * string, bool applyNormalize)
{
DEBUG_FATAL(strlen(string)+1 > BUFFER_SIZE, ("string too long %d/%d", strlen(string)+1, BUFFER_SIZE));
if (applyNormalize)
normalize(m_buffer, string);
else
strcpy(m_buffer, string);
}
// ----------------------------------------------------------------------
void TemporaryCrcString::set(char const * string, bool applyNormalize)
{
NOT_NULL(string);
internalSet(string, applyNormalize);
calculateCrc();
}
// ----------------------------------------------------------------------
void TemporaryCrcString::set(char const * string, uint32 crc)
{
NOT_NULL(string);
internalSet(string, false);
m_crc = crc;
}
// ======================================================================
@@ -0,0 +1,55 @@
// ======================================================================
//
// TemporaryCrcString.h
// Copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_TemporaryCrcString_H
#define INCLUDED_TemporaryCrcString_H
// ======================================================================
#include "sharedFoundation/CrcString.h"
// ======================================================================
class TemporaryCrcString : public CrcString
{
public:
TemporaryCrcString();
TemporaryCrcString(const TemporaryCrcString &);
DLLEXPORT TemporaryCrcString(const char *string, bool applyNormalize);
TemporaryCrcString(const char *string, uint32 crc);
virtual DLLEXPORT ~TemporaryCrcString();
virtual const char *getString() const;
virtual void clear();
virtual void set(const char *string, bool applyNormalize);
virtual void set(const char *string, uint32 crc);
private:
TemporaryCrcString & operator =(const TemporaryCrcString &);
void internalSet(const char *string, bool applyNormalize);
private:
enum
{
BUFFER_SIZE = 512
};
private:
char m_buffer[BUFFER_SIZE];
};
// ======================================================================
#endif
@@ -0,0 +1,20 @@
// ======================================================================
//
// Timer.cpp
// jeff grills
//
// copyright 1998 Bootprint Entertainment
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/Timer.h"
// ======================================================================
void Timer::setElapsedTime(float seconds)
{
time = seconds;
}
// ======================================================================
@@ -0,0 +1,309 @@
// ======================================================================
//
// Timer.h
// Copyright 1998 Bootprint Entertainment
// Copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Timer_H
#define INCLUDED_Timer_H
// ======================================================================
/**
* Convienent countdown timer class.
*
* Timer objects do not automatically update off the clock. They must be
* told that time is elapsing by calling one of the update*() functions.
* The update routine will return true when the timer expires.
*/
class Timer
{
public:
Timer();
explicit Timer(real seconds);
Timer(const Timer &rhs);
Timer &operator =(const Timer &rhs);
void setExpireTime(real seconds);
void extendExpireTime(real seconds);
void reset();
void setElapsedTime(float seconds);
bool updateNoReset(real elapsedTime);
bool updateZero(real elapsedTime);
bool updateSubtract(real elapsedTime);
bool isExpired() const;
real getExpireTime() const;
real getElapsedRatio() const;
real getRemainingRatio() const;
real getExpirationOvershoot() const;
real getRemainingTime() const;
private:
real expireTime;
real time;
};
// ======================================================================
/** Construct a timer object
*
* The timer is constructed with the belief that no time has elapsed.
* This constructor will set the expire-time to 0.
*/
inline Timer::Timer()
: expireTime(0),
time(0)
{
}
// ----------------------------------------------------------------------
/**
* Construct a timer object.
*
* The timer is constructed with the belief that no time has elapsed.
*
* @param seconds Time (in seconds) that the timer should expire at
*/
inline Timer::Timer(real seconds)
: expireTime(seconds),
time(0)
{
}
// ----------------------------------------------------------------------
/**
* Construct a timer object.
*
* Copy constructor.
*/
inline Timer::Timer(const Timer &rhs)
: expireTime(rhs.expireTime),
time(rhs.time)
{
}
// ----------------------------------------------------------------------
/**
* Assignment operator.
*
* Assignment operator.
*/
inline Timer &Timer::operator =(const Timer &rhs)
{
// if (this != &rhs)
{
expireTime = rhs.expireTime;
time = rhs.time;
}
return *this;
}
// ----------------------------------------------------------------------
/**
* Set a new expire time for the timer.
*
* This routine changes the time at which the timer will expire. It has
* no effect on the amount of time that the timer believes has already
* elapsed.
*
* @param seconds Time (in seconds) that the timer should expire at
*/
inline void Timer::setExpireTime(real seconds)
{
expireTime = seconds;
}
// ----------------------------------------------------------------------
/**
* Extends the expire time for the timer.
*
* This routine changes the time at which the timer will expire. It has
* no effect on the amount of time that the timer believes has already
* elapsed.
*
* @param seconds Time (in seconds) to add to the current expire time
*/
inline void Timer::extendExpireTime(real seconds)
{
expireTime += seconds;
}
// ----------------------------------------------------------------------
/**
* Reset the timer.
*
* This resets the timer to believe that no time has elapsed.
*/
inline void Timer::reset()
{
time = 0.0f;
}
// ----------------------------------------------------------------------
/**
* Inform the timer that time has elapsed, but not not reset the timer.
*
* When the timer expires, it will remain expired until reset() is called
* or one of the update*() functions is called that will reduce the amount
* of elapsed time.
*
* @param elapsedTime Amount of time (in seconds) that has elapsed
* @return True if the timer has expired, false otherwise.
* @see Timer::reset(), Timer::updateZero(), Timer::updateSubtract()
*/
inline bool Timer::updateNoReset(real elapsedTime)
{
time += elapsedTime;
return (time >= expireTime);
}
// ----------------------------------------------------------------------
/**
* Inform the timer that time has elapsed, and reset the time if it expired.
*
* When this routine detects the timer has expired, it will reset the timer.
* This will guarentee at least the amount of time has passed between
* expirations, but will not necessarily behave properly over an extended
* period of time.
*
* @return True if the timer has expired, false otherwise.
* @see Timer::reset(), Timer::updateNoReset(), Timer::updateSubtract()
*/
inline bool Timer::updateZero(real elapsedTime)
{
if (updateNoReset(elapsedTime))
{
reset();
return true;
}
return false;
}
// ----------------------------------------------------------------------
/**
* Inform the timer that time has elapsed, and reduce the time if it expired.
*
* When this routine detects the timer has expired, it will subtract the
* timer expiration time from the current time value. This routine will
* tend to remain more accurate over a longer period of time, but will
* not necessarily guarentee that the specified time will elapse before the
* next expiration (because of carry-over from the previous update).
*
* @return True if the timer has expired, false otherwise.
* @see Timer::reset(), Timer::updateNoReset(), Timer::updateSubtract()
*/
inline bool Timer::updateSubtract(real elapsedTime)
{
if (updateNoReset(elapsedTime))
{
time -= expireTime;
return true;
}
return false;
}
// ----------------------------------------------------------------------
/**
* Check if the timer is expired.
*
* This routine does not update the timer's current time.
*
* @return true if the timer has expired, otherwise false.
*/
inline bool Timer::isExpired() const
{
return time >= expireTime;
}
// ----------------------------------------------------------------------
/**
* Return the expire time
*
* @return expire time
*/
inline real Timer::getExpireTime() const
{
return expireTime;
}
// ----------------------------------------------------------------------
/**
* Calculate ratio (from 0 to 1) of time elapsed.
*
* Should not be called if the expire time has not been set, as the result
* is undefined.
*
* @return ratio (from 0 to 1) of time elapsed
*/
inline real Timer::getElapsedRatio() const
{
return expireTime != 0.0f ? time / expireTime : 0.0f;
}
// ----------------------------------------------------------------------
/**
* Calculate ratio (from 0 to 1) of time remaining.
*
* Should not be called if the expire time has not been set, as the result
* is undefined.
*
* @return ratio (from 0 to 1) of time remaining
*/
inline real Timer::getRemainingRatio() const
{
return expireTime != 0.0f ? ((expireTime - time) / expireTime) : 0.0f;
}
// ----------------------------------------------------------------------
/**
* Return the amount of time beyond the expiration time we are.
*
* The value returned is negative if we haven't expired yet.
*
* @return the overshoot time
*/
inline real Timer::getExpirationOvershoot() const
{
return time - expireTime;
}
// ----------------------------------------------------------------------
/**
* Return the amount of time until expiration.
*
* @return the overshoot time
*/
inline real Timer::getRemainingTime() const
{
return expireTime - time;
}
// ======================================================================
#endif
@@ -0,0 +1,48 @@
// ======================================================================
//
// VoidBindSecond.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include <functional>
// ======================================================================
template <class Operation>
class VoidBinderSecond: public std::unary_function<typename Operation::first_argument_type, void>
{
private:
typename Operation::second_argument_type m_boundValue;
Operation m_operation;
public:
VoidBinderSecond(const Operation& operation, const typename Operation::second_argument_type &boundValue)
: m_operation(operation), m_boundValue(boundValue) {}
void operator()(const typename Operation::first_argument_type& argument) const
{
m_operation(argument, m_boundValue);
}
};
// ======================================================================
/**
* works just like std::bind2nd() when return value of function is void.
*
* this is necessary since our STL breaks under MSVC 6 when using void functions
* with bind2nd.
*/
template <class Operation, typename BindArgumentType>
inline VoidBinderSecond<Operation> VoidBindSecond(const Operation& operation, const BindArgumentType &bindArgument)
{
typedef typename Operation::second_argument_type SecondArgumentType;
return VoidBinderSecond<Operation>(operation, SecondArgumentType(bindArgument));
}
// ======================================================================

Some files were not shown because too many files have changed in this diff Show More