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,11 @@
cmake_minimum_required(VERSION 2.8)
project(sharedFoundation)
if(WIN32)
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/public)
add_subdirectory(src)
@@ -0,0 +1 @@
#include "../../src/shared/ApplicationVersion.h"
@@ -0,0 +1 @@
#include "../../src/shared/ArrayList.h"
@@ -0,0 +1 @@
#include "../../src/shared/AutoDeltaNetworkIdPackedMap.h"
@@ -0,0 +1 @@
#include "../../src/shared/Binary.h"
@@ -0,0 +1 @@
#include "../../src/shared/BitArray.h"
@@ -0,0 +1 @@
#include "../../src/shared/Branch.h"
@@ -0,0 +1,7 @@
#if defined(PLATFORM_WIN32)
#include "../../src/win32/ByteOrder.h"
#elif defined(PLATFORM_LINUX)
#include "../../src/linux/ByteOrder.h"
#else
#error unsupported platform
#endif
@@ -0,0 +1 @@
#include "../../src/shared/CalendarTime.h"
@@ -0,0 +1 @@
#include "../../src/shared/CallbackEntryBase.h"
@@ -0,0 +1 @@
#include "../../src/shared/Clock.h"
@@ -0,0 +1 @@
#include "../../src/shared/CommandLine.h"
@@ -0,0 +1 @@
#include "../../src/shared/ConfigFile.h"
@@ -0,0 +1,7 @@
#if defined(PLATFORM_WIN32)
#include "../../src/win32/ConfigSharedFoundation.h"
#elif defined(PLATFORM_LINUX)
#include "../../src/linux/ConfigSharedFoundation.h"
#else
#error unsupported platform
#endif
@@ -0,0 +1 @@
#include "../../src/shared/ConstCharCrcLowerString.h"
@@ -0,0 +1 @@
#include "../../src/shared/ConstCharCrcString.h"
@@ -0,0 +1 @@
#include "../../src/shared/CrashReportInformation.h"
@@ -0,0 +1 @@
#include "../../src/shared/Crc.h"
@@ -0,0 +1 @@
#include "../../src/shared/CrcLowerString.h"
@@ -0,0 +1 @@
#include "../../src/shared/CrcString.h"
@@ -0,0 +1 @@
#include "../../src/shared/CrcStringTable.h"
@@ -0,0 +1 @@
#include "../../src/shared/DataResource.h"
@@ -0,0 +1 @@
#include "../../src/shared/DataResourceList.h"
@@ -0,0 +1 @@
#include "../../src/shared/DebugInfoManager.h"
@@ -0,0 +1 @@
#include "../../src/shared/dynamicVariable/DynamicVariable.h"
@@ -0,0 +1 @@
#include "../../src/shared/dynamicVariable/DynamicVariableList.h"
@@ -0,0 +1 @@
#include "../../src/shared/dynamicVariable/DynamicVariableListNestedList.h"
@@ -0,0 +1 @@
#include "../../src/shared/dynamicVariable/DynamicVariableLocationData.h"
@@ -0,0 +1 @@
#include "../../src/shared/ExitChain.h"
@@ -0,0 +1 @@
#include "../../src/shared/Fatal.h"
@@ -0,0 +1,7 @@
#if defined(PLATFORM_WIN32)
#include "../../src/win32/FirstPlatform.h"
#elif defined(PLATFORM_LINUX)
#include "../../src/linux/FirstPlatform.h"
#else
#error unsupported platform
#endif
@@ -0,0 +1 @@
#include "../../src/shared/FirstSharedFoundation.h"
@@ -0,0 +1 @@
#include "../../src/shared/FloatMath.h"
@@ -0,0 +1,7 @@
#if defined(PLATFORM_WIN32)
#include "../../src/win32/FloatingPointUnit.h"
#elif defined(PLATFORM_LINUX)
#include "../../src/linux/FloatingPointUnit.h"
#else
#error unsupported platform
#endif
@@ -0,0 +1 @@
#include "../../src/shared/FormattedString.h"
@@ -0,0 +1 @@
#include "../../src/shared/GameControllerMessage.def"
@@ -0,0 +1 @@
#include "../../src/shared/GameControllerMessage.h"
@@ -0,0 +1 @@
#include "../../src/shared/LabelHash.h"
@@ -0,0 +1 @@
#include "../../src/shared/LessPointerComparator.h"
@@ -0,0 +1 @@
#include "../../src/shared/MacroFoundation.h"
@@ -0,0 +1 @@
#include "../../src/shared/Md5.h"
@@ -0,0 +1 @@
#include "../../src/shared/MemoryBlockManager.h"
@@ -0,0 +1 @@
#include "../../src/shared/MemoryBlockManagerMacros.h"
@@ -0,0 +1 @@
#include "../../src/shared/MessageQueue.h"
@@ -0,0 +1 @@
#include "../../src/shared/MessageQueueDataTemplate.h"
@@ -0,0 +1 @@
#include "../../src/shared/Misc.h"
@@ -0,0 +1 @@
#include "../../src/shared/NetworkId.h"
@@ -0,0 +1 @@
#include "../../src/shared/NetworkIdArchive.h"
@@ -0,0 +1,7 @@
#if defined(PLATFORM_WIN32)
#include "../../src/win32/Os.h"
#elif defined(PLATFORM_LINUX)
#include "../../src/linux/Os.h"
#else
#error unsupported platform
#endif
@@ -0,0 +1,7 @@
#if defined(PLATFORM_WIN32)
#include "../../src/win32/PerThreadData.h"
#elif defined(PLATFORM_LINUX)
#include "../../src/linux/PerThreadData.h"
#else
#error unsupported platform
#endif
@@ -0,0 +1 @@
#include "../../src/shared/PersistentCrcString.h"
@@ -0,0 +1,7 @@
#if defined(PLATFORM_WIN32)
#include "../../src/win32/PlatformGlue.h"
#elif defined(PLATFORM_LINUX)
#include "../../src/linux/PlatformGlue.h"
#else
#error unsupported platform
#endif
@@ -0,0 +1 @@
#include "../../src/shared/PointerDeleter.h"
@@ -0,0 +1 @@
#include "../../src/win32/ProcessSpawner.h"
@@ -0,0 +1 @@
#include "../../src/shared/Production.h"
@@ -0,0 +1,5 @@
#if defined(PLATFORM_WIN32)
#include "../../src/win32/RegistryKey.h"
#else
#error unsupported platform
#endif
@@ -0,0 +1 @@
#include "../../src/shared/SafeCast.h"
@@ -0,0 +1 @@
#include "../../src/shared/Scheduler.h"
@@ -0,0 +1,7 @@
#if defined(PLATFORM_WIN32)
#include "../../src/win32/SetupSharedFoundation.h"
#elif defined(PLATFORM_LINUX)
#include "../../src/linux/SetupSharedFoundation.h"
#else
#error unsupported platform
#endif
@@ -0,0 +1 @@
#include "../../src/shared/StaticCallbackEntry.h"
@@ -0,0 +1 @@
#include "../../src/shared/StationId.h"
@@ -0,0 +1 @@
#include "../../src/shared/StlForwardDeclaration.h"
@@ -0,0 +1 @@
#include "../../src/shared/StringCompare.h"
@@ -0,0 +1 @@
#include "../../src/shared/Tag.h"
@@ -0,0 +1 @@
#include "../../src/shared/TemporaryCrcString.h"
@@ -0,0 +1 @@
#include "../../src/shared/Timer.h"
@@ -0,0 +1 @@
#include "../../src/shared/VoidBindSecond.h"
@@ -0,0 +1 @@
#include "../../src/shared/VoidMemberFunction.h"
@@ -0,0 +1 @@
#include "../../src/shared/Watcher.h"
@@ -0,0 +1,5 @@
#if defined(PLATFORM_WIN32)
#include "../../src/win32/WindowsWrapper.h"
#else
#error unsupported platform
#endif
@@ -0,0 +1,5 @@
#if defined(PLATFORM_LINUX)
#include "../../src/linux/vsnprintf.h"
#else
#error unsupported platform
#endif
@@ -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

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