mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-28 22:15:49 -04:00
Initial commit of the sharedFoundation library
This commit is contained in:
@@ -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)
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/ApplicationVersion.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/ArrayList.h"
|
||||
+1
@@ -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"
|
||||
+1
@@ -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"
|
||||
+7
@@ -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
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/ConstCharCrcLowerString.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/ConstCharCrcString.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/CrashReportInformation.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/Crc.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/CrcLowerString.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/CrcString.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/CrcStringTable.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/DataResource.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/DataResourceList.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/DebugInfoManager.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/dynamicVariable/DynamicVariable.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/dynamicVariable/DynamicVariableList.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/dynamicVariable/DynamicVariableListNestedList.h"
|
||||
+1
@@ -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
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/FirstSharedFoundation.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/FloatMath.h"
|
||||
+7
@@ -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
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/FormattedString.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/GameControllerMessage.def"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/GameControllerMessage.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/LabelHash.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/LessPointerComparator.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/MacroFoundation.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/Md5.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/MemoryBlockManager.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/MemoryBlockManagerMacros.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/MessageQueue.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/MessageQueueDataTemplate.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/Misc.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/NetworkId.h"
|
||||
+1
@@ -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
|
||||
+1
@@ -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
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/PointerDeleter.h"
|
||||
+1
@@ -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"
|
||||
+7
@@ -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
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/StaticCallbackEntry.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/StationId.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/StlForwardDeclaration.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/StringCompare.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/Tag.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/TemporaryCrcString.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/Timer.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/VoidBindSecond.h"
|
||||
+1
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/VoidMemberFunction.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/Watcher.h"
|
||||
+5
@@ -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
Reference in New Issue
Block a user