4449 lines
150 KiB
C++
4449 lines
150 KiB
C++
/*
|
|
** Command & Conquer Renegade(tm)
|
|
** Copyright 2025 Electronic Arts Inc.
|
|
**
|
|
** This program is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/***********************************************************************************************
|
|
*** Confidential - Westwood Studios ***
|
|
***********************************************************************************************
|
|
* *
|
|
* Project Name : Commando *
|
|
* *
|
|
* $Archive:: /Commando/Code/Commando/datasafe.h $*
|
|
* *
|
|
* $Author:: Steve_t $*
|
|
* *
|
|
* $Modtime:: 1/31/02 12:13p $*
|
|
* *
|
|
* $Revision:: 20 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
#ifndef _DATASAFE_H
|
|
#define _DATASAFE_H
|
|
|
|
/*
|
|
** Adapted from original code by Jeff Brown
|
|
**
|
|
** //=============================================================================
|
|
** // DataSafe.h
|
|
** // Public header file for the datasafe
|
|
** // Author: Jeff Brown
|
|
** // Date: Apr 16, 1999
|
|
** //=============================================================================
|
|
**
|
|
**
|
|
**
|
|
**
|
|
** Class Overview. ST - 7/11/2001 8:19PM
|
|
**
|
|
** DataSafeHandleClass.
|
|
** Used to manage handles to items stored in the data safe.
|
|
**
|
|
** DataSafeEntryClass and DataSafeEntryDataClass<T>.
|
|
** Represent a single item as stored in the data safe. DataSafeEntryClass has the header
|
|
** information used to retrieve the item from the safe and the derived DataSafeEntryDataClass
|
|
** also includes the actual type specific data payload.
|
|
**
|
|
** DataSafeEntryListClass
|
|
** This is a manager class for a linked list of DataSafeEntryDataClass<T>'s. Only the same
|
|
** type of DataSafeEntryDataClass<T> classes can currently be linked together and exist in
|
|
** the same list.
|
|
**
|
|
** DataSafeEntryTypeClass
|
|
** Every object put into the data safe is allocated a type ID so that like types (with the
|
|
** same ID) can be identified for linking and swapping purposes. DataSafeEntryTypeClass is
|
|
** a covenient holder for type information.
|
|
**
|
|
** GenericDataSafeClass and DataSafeClass<T>
|
|
** The safe itself consists of one static GenericDataSafeClass and many DataSafeClass<T>'s -
|
|
** one DataSafeClass<T> for every type of data we want to store in the data safe.
|
|
** Also included is an array of DataSafeEntryListClass's that act as pointers to the data safe
|
|
** entries.
|
|
**
|
|
**
|
|
** SafeDataClass
|
|
** This is a convenience class used to automate insertion and removal of items and provide
|
|
** a set of operators for common types. Using this class, adding existing data to the data safe
|
|
** can be as simple as just changing how it's declared. e.g.
|
|
**
|
|
** int SomeData;
|
|
**
|
|
** becomes
|
|
**
|
|
** SafeDataClass<int> SomeData;
|
|
**
|
|
** There are also some macros provided to make declaration easier so you could also just say
|
|
**
|
|
** safe_int SomeData;
|
|
**
|
|
** Currently, only a subset of operators are defined but more can easily be added as needed.
|
|
** Some changes to code will be required where operators are not available. For example
|
|
**
|
|
** SomeData += 10;
|
|
**
|
|
** would be a problem because the += operator is not defined. However the 'int' operator, the
|
|
** = operator and the conversion operator () are defined so you could change the code to read
|
|
**
|
|
** SomeData = (int)SomeData + 10;
|
|
**
|
|
** or
|
|
**
|
|
** SomeData = SomeData() + 10;
|
|
**
|
|
** You can pretty much throw anything into the data safe using this class to automate isertion
|
|
** and retrieval. Some examples.
|
|
**
|
|
** safe_float HideyFloat;
|
|
** safe_double CantFindMe[256];
|
|
** SafeDataClass<SomeNamedClass> ASafeClass;
|
|
** SafeDataClass<SomeOtherType> ASafeType;
|
|
**
|
|
** For types without existing macros, you will have to declare a new DataSafeClass<T> once for
|
|
** each type in DataSafe.cpp using the DECLARE_DATA_SAFE macro. So in the above example, you
|
|
** would have to add the following lines in DataSafe.cpp to allow storage of the new types
|
|
**
|
|
** DECLARE_DATA_SAFE(SomeNamedClass);
|
|
** DECLARE_DATA_SAFE(SomeOtherType);
|
|
**
|
|
**
|
|
**
|
|
**
|
|
** Known external dependencies.
|
|
** DynamicVectorClass
|
|
** TICKS_PER_SECOND = 1000
|
|
** FreeRandom - Renegade random number generator.
|
|
** WWDEBUG_SAY - Equivalent to DebugString in C&C. Just a formatted debug output.
|
|
**
|
|
*/
|
|
|
|
/*
|
|
** Includes.
|
|
*/
|
|
#ifndef _ALWAYS_H
|
|
#include "always.h"
|
|
#include <assert.h>
|
|
#include <malloc.h>
|
|
#include <memory.h>
|
|
#include <windows.h>
|
|
#endif //_ALWAYS_H
|
|
|
|
#ifndef _TIMEMGR_H
|
|
#include "timemgr.h"
|
|
#endif //_TIMEMGR_H
|
|
|
|
#ifndef _WWDEBUG_H
|
|
#include "wwdebug.h"
|
|
#endif //_WWDEBUG_H
|
|
|
|
//#ifndef MMSYS_H
|
|
//#include "mmsys.h"
|
|
//#endif //MMSYS_H
|
|
#include "systimer.h"
|
|
|
|
/*
|
|
** Use Renegade assert.
|
|
*/
|
|
#ifdef WWASSERT
|
|
#define ds_assert WWASSERT
|
|
#else //WWASSERT
|
|
#define ds_assert assert
|
|
#endif //WWASSERT
|
|
|
|
|
|
/*
|
|
** TEMP. Profile builds don't have asserts.
|
|
*/
|
|
#ifndef DEBUG
|
|
#undef ds_assert
|
|
#define ds_assert(x)
|
|
#pragma warning(disable : 4189)
|
|
#endif //DEBUG
|
|
|
|
#ifndef WWDEBUG
|
|
#pragma warning(disable : 4101)
|
|
#endif
|
|
|
|
|
|
/*
|
|
** Enable this define to make the datasafe thread safe (there is a performance penalty).
|
|
*/
|
|
//#define THREAD_SAFE_DATA_SAFE
|
|
|
|
/*
|
|
** Number of linked lists we can create for data safe items. Only like sized items can be stored in the same list.
|
|
*/
|
|
#define MAX_DATASAFE_LISTS 8192
|
|
|
|
/*
|
|
** The maximum number of different data types that can be stored in the data safe. This should normally fit into a byte for
|
|
** handle encoding reasons.
|
|
*/
|
|
#define MAX_DATASAFE_TYPES 128
|
|
|
|
/*
|
|
** Max number of entries in a single list before we have to create a second list for items of the same size. The smaller this
|
|
** value, the quicker we will be able to retrieve data from the safe. The larger we make it, the more secure the data safe will
|
|
** be.
|
|
*/
|
|
#define MAX_ENTRIES_PER_LIST 16
|
|
|
|
/*
|
|
** How often the data safe entries get shuffled around and re-keyed. This is the delay between each shuffle.
|
|
*/
|
|
#define SHUFFLE_TIME (TICKS_PER_SECOND * 7)
|
|
|
|
/*
|
|
** The delay between each integrity check on the data safe. This is a slow operation.
|
|
*/
|
|
#define SECURITY_CHECK_TIME (TICKS_PER_SECOND * 15)
|
|
|
|
/*
|
|
** The number of copies of objects of any one type that can exist in an unencrypted state. These copies are only used as return
|
|
** values and changes to the copies can never be propagated back into the safe.
|
|
*/
|
|
#define MAX_OBJECT_COPIES 8
|
|
|
|
/*
|
|
** Sentinel values. Used to see if someone just zeroes the whole safe or tampered with the get function.
|
|
*/
|
|
#define SENTINEL_ONE 0x29874362
|
|
#define SENTINEL_TWO 0x0bad0bad
|
|
|
|
#define DATASAFE_TIME_CHECK_CALLS 100000
|
|
|
|
/*
|
|
** Defines to allow convenient use of built-in types inside the data safe.
|
|
**
|
|
*/
|
|
#ifdef PARAM_EDITING_ON
|
|
|
|
#define safe_int int
|
|
#define safe_unsigned_int unsigned int
|
|
|
|
#define safe_long long
|
|
#define safe_unsigned_long unsigned long
|
|
|
|
#define safe_float float
|
|
|
|
#define safe_double double
|
|
|
|
#else //PARAM_EDITING_ON
|
|
|
|
#define safe_int SafeDataClass<int>
|
|
#define safe_unsigned_int SafeDataClass<unsigned int>
|
|
|
|
#define safe_long SafeDataClass<int>
|
|
#define safe_unsigned_long SafeDataClass<unsigned int>
|
|
|
|
#define safe_float SafeDataClass<float>
|
|
|
|
#define safe_double SafeDataClass<double>
|
|
|
|
#endif //PARAM_EDITING_ON
|
|
|
|
|
|
/*
|
|
** Make sure we pulled in the right timer defines.
|
|
*/
|
|
#if TICKS_PER_SECOND != 1000
|
|
#error Code assumes TICKS_PER_SECOND == 1000
|
|
#endif
|
|
|
|
|
|
/*
|
|
** We want to inline functions within inline functions to make the code harder to hack by having multiple copies of it.
|
|
*/
|
|
#pragma inline_recursion(on)
|
|
#pragma inline_depth(4)
|
|
#pragma warning(disable : 4714)
|
|
|
|
/*
|
|
** Data safe handle.
|
|
**
|
|
** This consists of a linked list number, an entry identifier and a type.
|
|
**
|
|
** The whole shooting match can just be treated like an int.
|
|
**
|
|
*/
|
|
class DataSafeHandleClass
|
|
{
|
|
public:
|
|
|
|
/*
|
|
** Consturctor.
|
|
*/
|
|
DataSafeHandleClass(int val = 0) {
|
|
Handle.Whole.WholeHandle = val;
|
|
};
|
|
|
|
/*
|
|
** Validity check.
|
|
*/
|
|
bool Is_Valid(void) const {
|
|
return(Handle.Whole.WholeHandle != -1);
|
|
};
|
|
|
|
/*
|
|
** Convenience functions and operators to handle setting or getting a handle using an int.
|
|
*/
|
|
inline int operator = (const int &val) {
|
|
Handle.Whole.WholeHandle = val;
|
|
return(val);
|
|
};
|
|
|
|
inline operator int (void) {
|
|
return(Handle.Whole.WholeHandle);
|
|
}
|
|
|
|
inline operator int (void) const {
|
|
return(Handle.Whole.WholeHandle);
|
|
}
|
|
|
|
inline int &operator () (void) {
|
|
return(Handle.Whole.WholeHandle);
|
|
}
|
|
|
|
/*
|
|
** Handle data.
|
|
*/
|
|
union tHandle {
|
|
struct {
|
|
/*
|
|
** All the handle components conveniently together in an int.
|
|
*/
|
|
int WholeHandle;
|
|
} Whole;
|
|
|
|
struct {
|
|
|
|
/*
|
|
** ID is basically the index of the item in the linked list. It's a little more complex
|
|
** than that since an ID can be re-used after the original user is removed from the
|
|
** list but the whole list is searched for a matching ID when retrieving anyway.
|
|
*/
|
|
unsigned char ID;
|
|
|
|
/*
|
|
** The type of object this handle represents.
|
|
*/
|
|
unsigned char Type;
|
|
|
|
/*
|
|
** The list number where we can find this object.
|
|
*/
|
|
unsigned short List;
|
|
} Part;
|
|
|
|
} Handle;
|
|
};
|
|
|
|
/*
|
|
** Known packing is required here otherwise the default alignment is the same as the largest member
|
|
** of the structure. When combined with an expansion of DataSafeEntryDataClass<T> for doubles, the
|
|
** packing alignment becomes 8 (the size of a double) thus the offset of Data is not always as expected.
|
|
** i.e. you can no longer use sizeof(DataSafeEntryClass) to get the offset of the Data member of
|
|
** the derived class. This also prevents bloating (due to the bool member) when using large expansions
|
|
** for 'T'
|
|
*/
|
|
#pragma pack(push)
|
|
#pragma pack(4)
|
|
|
|
/*
|
|
**
|
|
** This class represents an internal data safe entry minus the actual data. In practice, this class will never be used
|
|
** except to refer to a DataSafeEntryDataClass<T> which actually contains the type specific data.
|
|
**
|
|
*/
|
|
class DataSafeEntryClass
|
|
{
|
|
|
|
public:
|
|
|
|
/*
|
|
** Identifying handle.
|
|
*/
|
|
DataSafeHandleClass Handle;
|
|
|
|
/*
|
|
** Linked list next and prev.
|
|
**
|
|
** Note: These can point to a DataSafeEntryDataClass expanded for any type.
|
|
*/
|
|
DataSafeEntryClass *Next;
|
|
DataSafeEntryClass *Prev;
|
|
|
|
/*
|
|
** Size of data.
|
|
*/
|
|
unsigned long Size;
|
|
|
|
/*
|
|
** Is this a slop (fake, to allow swapping with only 1 real entry) entry?
|
|
*/
|
|
bool IsSlop;
|
|
};
|
|
|
|
|
|
/*
|
|
** This is a complete internal data safe entry including the header and the encrypted data.
|
|
**
|
|
*/
|
|
template<class T>
|
|
class DataSafeEntryDataClass : public DataSafeEntryClass
|
|
{
|
|
public:
|
|
T Data;
|
|
};
|
|
|
|
#pragma pack(pop)
|
|
|
|
|
|
|
|
/*
|
|
** This class represents a single data safe entry list. There can be mutiple lists in a data safe but all entries in a single
|
|
** list must be of the same type.
|
|
*/
|
|
class DataSafeEntryListClass
|
|
{
|
|
public:
|
|
|
|
/*
|
|
** Constructor.
|
|
*/
|
|
DataSafeEntryListClass(void) {
|
|
SafeList = NULL;
|
|
EntryCount = 0;
|
|
EntryType = -1;
|
|
SlopCount = 0;
|
|
memset(HandleIDUsage, 0, sizeof(HandleIDUsage));
|
|
};
|
|
|
|
/*
|
|
** Pointer to the head of the list.
|
|
*/
|
|
DataSafeEntryClass *SafeList;
|
|
|
|
/*
|
|
** Number of entries in the list.
|
|
*/
|
|
int EntryCount;
|
|
|
|
/*
|
|
** Type of entry in this list.
|
|
*/
|
|
int EntryType;
|
|
|
|
/*
|
|
** Number of slop entries in this list.
|
|
*/
|
|
int SlopCount;
|
|
|
|
/*
|
|
** Handle IDs used in this list.
|
|
*/
|
|
char HandleIDUsage[MAX_ENTRIES_PER_LIST];
|
|
};
|
|
|
|
|
|
/*
|
|
**
|
|
** This class describes a type of entry in the data safe. It's important to keep track of the types of objects we add since
|
|
** only similar types can be swapped in memory. This class is just a convenient container to help us match type codes with
|
|
** unique IDs.
|
|
**
|
|
**
|
|
*/
|
|
class DataSafeEntryTypeClass
|
|
{
|
|
public:
|
|
|
|
DataSafeEntryTypeClass(void) {
|
|
TypeCode = 0;
|
|
ID = -1;
|
|
Size = 0;
|
|
};
|
|
|
|
|
|
/*
|
|
** A unique number used to match and assign type IDs. This can come from anywhere as long as it's different for every type.
|
|
*/
|
|
unsigned long TypeCode;
|
|
|
|
/*
|
|
** This is the user friendly ID that is stored along with entries in the data safe and returned in the handle that's
|
|
** given out when something is added to the safe.
|
|
** It's also the index into the type list.
|
|
*/
|
|
int ID;
|
|
|
|
/*
|
|
** The size of this type of object. Must be a multiple of 4 bytes for the data safe. (This is redundant now that we
|
|
** have a type/size lookup table).
|
|
*/
|
|
int Size;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
** GenericDataSafeClass
|
|
**
|
|
** This class represents a single data safe. It can only function as the base class to one or more instances of
|
|
** DataSafeClass<T>.
|
|
**
|
|
**
|
|
** This class functions as a base class for all the templated 'DataSafeClass'es so that they can all share a single set of
|
|
** static data. Normally, static data in a templated class is duplicated for each expansion of the class.
|
|
**
|
|
** Even though there may be many instances and expansions of the derived DataSafeClass<T> there is only ever one global
|
|
** data safe and that is represented by this class.
|
|
**
|
|
*/
|
|
class GenericDataSafeClass
|
|
{
|
|
public:
|
|
|
|
/*
|
|
** Constructor.
|
|
*/
|
|
GenericDataSafeClass(void);
|
|
|
|
/*
|
|
** Query functions.
|
|
*/
|
|
static DataSafeEntryClass * Get_Entry(DataSafeHandleClass handle);
|
|
static int Get_Entry_Type(DataSafeHandleClass handle);
|
|
|
|
/*
|
|
** System timer reset.
|
|
*/
|
|
static void Reset_Timers(void);
|
|
|
|
/*
|
|
** Thread safety. This is normally handled automatically but if you need to manually lock the safe for a period of time
|
|
** to do a read/hold/write then this is the way to do it.
|
|
*/
|
|
#ifdef THREAD_SAFE_DATA_SAFE
|
|
static void Lock(void);
|
|
static void Unlock(void);
|
|
#endif //THREAD_SAFE_DATA_SAFE
|
|
|
|
/*
|
|
** Stats, debug helpers.
|
|
*/
|
|
static void Dump_Safe_Stats(char *dump_buffer, int buffer_size);
|
|
static void Print_Safe_Stats_To_Debug_Output(void);
|
|
static void Reset(void);
|
|
|
|
|
|
#ifdef THREAD_SAFE_DATA_SAFE
|
|
static void Set_Preferred_Thread(unsigned int){};
|
|
#else //THREAD_SAFE_DATA_SAFE
|
|
static void Set_Preferred_Thread(unsigned int thread_id) {PreferredThread = thread_id;};
|
|
#endif //THREAD_SAFE_DATA_SAFE
|
|
|
|
protected:
|
|
|
|
/*
|
|
** Cleanup.
|
|
*/
|
|
void Shutdown(void);
|
|
|
|
/*
|
|
** Query functions.
|
|
*/
|
|
static DataSafeEntryClass * Get_Entry_By_Index(int list, int index);
|
|
|
|
/*
|
|
** Security
|
|
*/
|
|
static void Shuffle(bool forced = false);
|
|
static void Swap_Entries(DataSafeEntryClass *first, DataSafeEntryClass *second, int type);
|
|
static void Encrypt(void *data, int size, unsigned long key = SimpleKey, bool do_checksum = true);
|
|
static void Decrypt(void *data, int size, unsigned long key = SimpleKey, bool do_checksum = true);
|
|
static void Mem_Copy_Encrypt(void *dest, void *src, int size, bool do_checksum);
|
|
static void Mem_Copy_Decrypt(void *dest, void *src, int size, bool do_checksum);
|
|
static __forceinline void Security_Check(void);
|
|
static __forceinline void Security_Fault(void);
|
|
static void Say_Security_Fault(void);
|
|
|
|
/*
|
|
** Insertion support.
|
|
*/
|
|
static int Get_Random_List_For_Insertion(int type);
|
|
static void Random_Insertion(DataSafeEntryClass *entry, int list, int type, bool is_slop = false);
|
|
static int Create_Safe_List(int type);
|
|
static int Get_Handle_ID(int list);
|
|
|
|
/*
|
|
** Deletion support. Just used to make sure we are doing type safe deletion.
|
|
*/
|
|
static void Remove_From_List(int list, DataSafeEntryClass *entry_ptr);
|
|
static void Free_Handle_ID(int list, int id);
|
|
|
|
/*
|
|
** Type identification.
|
|
*/
|
|
static inline int Get_Type_Size(int type);
|
|
|
|
#ifdef THREAD_SAFE_DATA_SAFE
|
|
/*
|
|
** Thread safety.
|
|
*/
|
|
class ThreadLockClass
|
|
{
|
|
public:
|
|
/*
|
|
** Constructor. Grabs the mutex.
|
|
*/
|
|
inline ThreadLockClass(void) {
|
|
int deadlock = WaitForSingleObject(GenericDataSafeClass::SafeMutex, 10 * 1000);
|
|
if (deadlock == WAIT_TIMEOUT) {
|
|
WWDEBUG_SAY(("Data Safe: Timeout waiting for data safe mutex\n"));
|
|
ds_assert(deadlock != WAIT_TIMEOUT);
|
|
}
|
|
};
|
|
|
|
/*
|
|
** Destructor, releases the mutex.
|
|
*/
|
|
inline ~ThreadLockClass(void) {
|
|
ReleaseMutex(GenericDataSafeClass::SafeMutex);
|
|
};
|
|
};
|
|
#else //THREAD_SAFE_DATA_SAFE
|
|
|
|
/*
|
|
** If thread safety is not required, this class compiles out to nothing when used in release mode.
|
|
*/
|
|
class ThreadLockClass
|
|
{
|
|
public:
|
|
#ifdef WWDEBUG
|
|
__forceinline ThreadLockClass(void) {
|
|
if (GenericDataSafeClass::PreferredThread != GetCurrentThreadId()) {
|
|
WWDEBUG_SAY(("DATASAFE.H - PreferredThread = %08X, GetCurrentThreadId() == %08X\n", GenericDataSafeClass::PreferredThread, GetCurrentThreadId()));
|
|
}
|
|
ds_assert(GenericDataSafeClass::PreferredThread == GetCurrentThreadId());
|
|
};
|
|
#endif //WWDEBUG
|
|
};
|
|
|
|
static unsigned int PreferredThread;
|
|
#endif //THREAD_SAFE_DATA_SAFE
|
|
|
|
friend ThreadLockClass;
|
|
|
|
/*
|
|
** Static data. We only need one each of these, regardless of how many DataSafeClass 'types' there are.
|
|
**
|
|
**
|
|
**
|
|
*/
|
|
|
|
/*
|
|
** Simple key value used for xoring.
|
|
*/
|
|
static unsigned long SimpleKey;
|
|
|
|
/*
|
|
** Key used for encrypting handles.
|
|
*/
|
|
static unsigned long HandleKey;
|
|
|
|
/*
|
|
** Number of valid entries in the Safe list.
|
|
*/
|
|
static int NumLists;
|
|
|
|
/*
|
|
** Array of pointers to data lists. We can't use a dynamic vector class here because the handles we give out include
|
|
** an index into this array. Dynamic vector class moves entries around to remove gaps in the array which would leave
|
|
** the handles pointing to the wrong element.
|
|
*/
|
|
static DataSafeEntryListClass *Safe[MAX_DATASAFE_LISTS];
|
|
|
|
/*
|
|
** Integrity check.
|
|
*/
|
|
static unsigned long Checksum;
|
|
|
|
/*
|
|
** Shuffle delay.
|
|
*/
|
|
static unsigned long ShuffleDelay;
|
|
|
|
/*
|
|
** Security check delay.
|
|
*/
|
|
static unsigned long SecurityCheckDelay;
|
|
|
|
/*
|
|
** List of types that are stored in the data safe.
|
|
*/
|
|
static DataSafeEntryTypeClass TypeList[MAX_DATASAFE_TYPES];
|
|
static int TypeListCount;
|
|
|
|
/*
|
|
** Mutex to ensure thread safety.
|
|
*/
|
|
#ifdef THREAD_SAFE_DATA_SAFE
|
|
static HANDLE SafeMutex;
|
|
#endif //THREAD_SAFE_DATA_SAFE
|
|
|
|
/*
|
|
** Sentinels. Can't use 'SafeDataClass' as it's constructor adds data to the safe - i.e. us.
|
|
*/
|
|
static DataSafeHandleClass SentinelOne;
|
|
static DataSafeHandleClass SentinelTwo;
|
|
|
|
/*
|
|
** Number of CRC errors so we can report it in the game results.
|
|
*/
|
|
static int CRCErrors;
|
|
|
|
|
|
/*
|
|
** Statistics - debug only.
|
|
*/
|
|
#ifdef WWDEBUG
|
|
static unsigned long LastDump;
|
|
static int NumSwaps;
|
|
static int NumFetches;
|
|
static int SlopCount;
|
|
static int NumSecurityChecks;
|
|
static int NumShuffles;
|
|
#endif //WWDEBUG
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
** DataSafeClass<T>
|
|
**
|
|
** This templated class is used to provide type specific functionality in the data safe. There must be at least one instance
|
|
** of this class for each type of data we want to store in the safe. This, along with 'GenericDataSafeClass' represents
|
|
** a single global data safe.
|
|
**
|
|
*/
|
|
template<class T>
|
|
class DataSafeClass : public GenericDataSafeClass
|
|
{
|
|
|
|
public:
|
|
DataSafeClass(T *bogus_ptr = NULL, int slopcount = 3);
|
|
~DataSafeClass(void);
|
|
|
|
/*
|
|
** Query functions.
|
|
*/
|
|
static bool Get(DataSafeHandleClass handle, T* &item);
|
|
static inline bool In_Return_List(T *ptr) {
|
|
if (ptr) {
|
|
void *temp = (void*)ptr;
|
|
if (temp >= &ReturnList[0][0] && temp < &ReturnList[MAX_OBJECT_COPIES][0]) {
|
|
if (((unsigned long) temp - (unsigned long)(&ReturnList[0][0])) % sizeof(T) == 0) {
|
|
return(true);
|
|
}
|
|
}
|
|
}
|
|
return(false);
|
|
|
|
};
|
|
|
|
/*
|
|
** Set functions.
|
|
*/
|
|
static bool Set(DataSafeHandleClass handle, T *data);
|
|
|
|
/*
|
|
** Add functions.
|
|
*/
|
|
static DataSafeHandleClass Add_Entry(T &value, bool is_slop = false);
|
|
|
|
/*
|
|
** Removal functions.
|
|
*/
|
|
static void Delete_Entry(DataSafeHandleClass handle);
|
|
|
|
|
|
private:
|
|
|
|
/*
|
|
** Type identification.
|
|
*/
|
|
static int Get_Type_ID(unsigned long type_code, int size);
|
|
static unsigned long Get_Type_Code(void);
|
|
|
|
/*
|
|
** Type of this DataSafe.
|
|
*/
|
|
static int Type;
|
|
|
|
/*
|
|
** Min slop entries for this type of safe.
|
|
*/
|
|
static int MinSlop;
|
|
|
|
/*
|
|
** Copies of items in the data safe. Only used to return copies of items in the safe.
|
|
**
|
|
** The number of elements in this list is the number of times you can call the 'Get' function before you start to
|
|
** invalidate the data you got 'n' calls ago. For this reason, you should always make a copy of data retrieved from
|
|
** the safe if you plan to use it more than once.
|
|
*/
|
|
static char ReturnList[MAX_OBJECT_COPIES][sizeof(T)];
|
|
static int ReturnIndex;
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
**
|
|
** Macros to help in declaring data safe types.
|
|
**
|
|
**
|
|
**
|
|
*/
|
|
#define DECLARE_DATA_SAFE(type) \
|
|
DataSafeClass<type> DataSafe##type; \
|
|
int DataSafeClass<type>::Type; \
|
|
char DataSafeClass<type>::ReturnList[MAX_OBJECT_COPIES][sizeof(type)]; \
|
|
int DataSafeClass<type>::ReturnIndex; \
|
|
int DataSafeClass<type>::MinSlop;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
**
|
|
** SafeDataClass.
|
|
**
|
|
** This class is for convenience when using the data safe. Just expand this class for the type you want to add to the data safe
|
|
** and it will keep track of the handle and automate the adding in, and removal of, data in the safe.
|
|
**
|
|
*/
|
|
extern char ErrorVal[1024];
|
|
template<class T>
|
|
class SafeDataClass
|
|
{
|
|
|
|
public:
|
|
|
|
/*
|
|
** Constructor, destructor.
|
|
*/
|
|
SafeDataClass(void);
|
|
SafeDataClass(T data);
|
|
~SafeDataClass(void);
|
|
|
|
/*
|
|
** Copy constructor. This is a bad thing to call.
|
|
*/
|
|
SafeDataClass(SafeDataClass &) {
|
|
ds_assert(false);
|
|
};
|
|
|
|
/*
|
|
** Helper functions for data safe class storage.
|
|
*/
|
|
inline T* Get_Ptr(void) const;
|
|
inline bool Commit(T* data_ptr) const;
|
|
|
|
/*
|
|
** Operators.
|
|
*/
|
|
inline T &operator () (void) const;
|
|
|
|
inline T &operator = (T const &data);
|
|
inline T &operator = (SafeDataClass<T> &safedata);
|
|
|
|
inline operator int(void) const;
|
|
inline operator unsigned int(void) const;
|
|
inline operator long(void) const;
|
|
inline operator unsigned long(void) const;
|
|
inline operator float(void) const;
|
|
inline operator double(void) const;
|
|
|
|
inline bool operator == (T const &data);
|
|
inline bool operator == (SafeDataClass<T> &safedata);
|
|
|
|
inline bool operator != (T const &data);
|
|
inline bool operator != (SafeDataClass<T> &safedata);
|
|
|
|
inline bool operator > (T const &data);
|
|
inline bool operator > (SafeDataClass<T> &safedata);
|
|
|
|
inline bool operator >= (T const &data);
|
|
inline bool operator >= (SafeDataClass<T> &safedata);
|
|
|
|
inline bool operator < (T const &data);
|
|
inline bool operator < (SafeDataClass<T> &safedata);
|
|
|
|
inline bool operator <= (T const &data);
|
|
inline bool operator <= (SafeDataClass<T> &safedata);
|
|
|
|
inline T &operator + (T const &data);
|
|
inline T &operator + (SafeDataClass<T> &safedata);
|
|
|
|
inline T &operator += (T const &data);
|
|
inline T &operator += (SafeDataClass<T> &safedata);
|
|
|
|
inline T &operator - (T const &data);
|
|
inline T &operator - (SafeDataClass<T> &safedata);
|
|
|
|
inline T &operator -= (T const &data);
|
|
inline T &operator -= (SafeDataClass<T> &safedata);
|
|
|
|
inline T &operator * (T const &data);
|
|
inline T &operator * (SafeDataClass<T> &safedata);
|
|
|
|
inline T &operator *= (T const &data);
|
|
inline T &operator *= (SafeDataClass<T> &safedata);
|
|
|
|
inline T &operator / (T const &data);
|
|
inline T &operator / (SafeDataClass<T> &safedata);
|
|
|
|
inline T &operator /= (T const &data);
|
|
inline T &operator /= (SafeDataClass<T> &safedata);
|
|
|
|
inline T &operator ++ (void);
|
|
inline T &operator -- (void);
|
|
|
|
inline T &operator ++ (int);
|
|
inline T &operator -- (int);
|
|
|
|
/*
|
|
** Query and set functions.
|
|
*/
|
|
DataSafeHandleClass Get_Handle(void) {return(Handle);};
|
|
T Get(void);
|
|
void Set(T);
|
|
|
|
|
|
private:
|
|
/*
|
|
** This is the handle that represents this classes data in the datasafe.
|
|
*/
|
|
DataSafeHandleClass Handle;
|
|
|
|
#ifdef WWDEBUG
|
|
T DebugData;
|
|
#endif //WWDEBUG
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
**
|
|
**
|
|
**
|
|
** File separation.
|
|
**
|
|
**
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Simple functions, suitable for inline expansion.
|
|
**
|
|
**
|
|
**
|
|
**
|
|
*/
|
|
|
|
|
|
/*
|
|
**
|
|
**
|
|
** GenericDataSafeClass functions.
|
|
**
|
|
**
|
|
*/
|
|
|
|
/***********************************************************************************************
|
|
* GenericDataSafeClass::Get_Type_Size -- Get the size of this type *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Type ID of object *
|
|
* *
|
|
* OUTPUT: Size of object *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 6/27/2001 12:47PM ST : Created *
|
|
*=============================================================================================*/
|
|
inline int GenericDataSafeClass::Get_Type_Size(int type)
|
|
{
|
|
ds_assert(type >= 0);
|
|
ds_assert(type < MAX_DATASAFE_TYPES);
|
|
ds_assert(type < TypeListCount);
|
|
return(TypeList[type].Size);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* GenericDataSafeClass::Security_Fault -- Security fault handler *
|
|
* *
|
|
* __forceinline used to make sure there are multiple copies of this code. It's bloaty *
|
|
* but it makes it harder to hack out (but only a little bit) *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/9/2001 2:20PM ST : Created *
|
|
*=============================================================================================*/
|
|
__forceinline void GenericDataSafeClass::Security_Fault(void)
|
|
{
|
|
WWDEBUG_SAY(("Data Safe:Security fault\n"));
|
|
CRCErrors++;
|
|
|
|
Say_Security_Fault();
|
|
ds_assert(false);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* GenericDataSafeClass::Security_Check -- Look for security problems. *
|
|
* *
|
|
* __forceinline used to make sure there are multiple copies of this code. It's bloaty *
|
|
* but it makes it harder to hack out (but only a little bit) *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/9/2001 1:08PM ST : Created *
|
|
*=============================================================================================*/
|
|
__forceinline void GenericDataSafeClass::Security_Check(void)
|
|
{
|
|
ThreadLockClass locker;
|
|
|
|
/*
|
|
** Flag to prevent recursion.
|
|
*/
|
|
static bool _checking = false;
|
|
|
|
/*
|
|
** Only check the time every n calls.
|
|
*/
|
|
static unsigned long _calls = 0;
|
|
_calls++;
|
|
if (_calls < DATASAFE_TIME_CHECK_CALLS) {
|
|
return;
|
|
}
|
|
_calls = 0;
|
|
|
|
/*
|
|
** See if SimpleKey has been zeroed out.
|
|
*/
|
|
if (HandleKey - SimpleKey == HandleKey) {
|
|
WWDEBUG_SAY(("Data Safe: Simple Key compromised!\n"));
|
|
Security_Fault();
|
|
}
|
|
|
|
/*
|
|
** See if HandleKey has been zeroed out.
|
|
*/
|
|
if (SimpleKey - HandleKey == SimpleKey) {
|
|
WWDEBUG_SAY(("Data Safe: Handle Key compromised!\n"));
|
|
Security_Fault();
|
|
}
|
|
|
|
/*
|
|
** Use the checksum to verify the whole data safe.
|
|
** Yes, the whole safe. A teeny bit slow maybe.
|
|
**
|
|
** Since we are going through the whole safe here, we might as well make a note of where slop
|
|
** needs to be added or removed and count how many total slop entries we have.
|
|
*/
|
|
unsigned long time = TIMEGETTIME();
|
|
if (time < SecurityCheckDelay || (time | SecurityCheckDelay) == 0 || (time - SecurityCheckDelay) > SECURITY_CHECK_TIME) {
|
|
|
|
#ifdef WWDEBUG
|
|
SlopCount = 0;
|
|
NumSecurityChecks++;
|
|
#endif //WWDEBUG
|
|
|
|
/*
|
|
** If toooo much time has gone by then do it anyway.
|
|
*/
|
|
if (!_checking) { // || (time - SecurityCheckDelay) > SECURITY_CHECK_TIME * 5) {
|
|
|
|
_checking = true;
|
|
//WWDEBUG_SAY(("Data Safe: Performing security check\n"));
|
|
SecurityCheckDelay = time;
|
|
unsigned long checkey = ~SimpleKey;
|
|
|
|
/*
|
|
** Loop through every list.
|
|
*/
|
|
for (int i=0 ; i<NumLists ; i++) {
|
|
ds_assert(Safe[i] != NULL);
|
|
if (Safe[i] != NULL && Safe[i]->EntryCount > 0) {
|
|
|
|
/*
|
|
** Dereference stuff - make sure the list makes sense.
|
|
*/
|
|
DataSafeEntryClass *entry_ptr = Safe[i]->SafeList;
|
|
unsigned long *data = NULL;
|
|
ds_assert(entry_ptr != NULL);
|
|
int data_size = entry_ptr->Size;
|
|
ds_assert((data_size & 3) == 0);
|
|
data_size = data_size >> 2;
|
|
|
|
if (entry_ptr) {
|
|
|
|
/*
|
|
** Go through each entry in the list.
|
|
*/
|
|
for (int j=0 ; j<Safe[i]->EntryCount ; j++) {
|
|
#ifdef WWDEBUG
|
|
/*
|
|
** Count slop entries for debug purposes.
|
|
*/
|
|
if (entry_ptr->IsSlop) {
|
|
SlopCount++;
|
|
}
|
|
#endif //WWDEBUG
|
|
/*
|
|
** Add in the handle.
|
|
*/
|
|
checkey ^= entry_ptr->Handle;
|
|
|
|
/*
|
|
** Add in the data.
|
|
*/
|
|
data = (unsigned long *) (((char*)entry_ptr) + sizeof(*entry_ptr));
|
|
for (int z=0 ; z<data_size ; z++) {
|
|
checkey ^= *data++;
|
|
}
|
|
|
|
/*
|
|
** Next entry.
|
|
*/
|
|
entry_ptr = entry_ptr->Next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (checkey != Checksum) {
|
|
WWDEBUG_SAY(("Data Safe: Incorrect checksum!\n"));
|
|
Security_Fault();
|
|
}
|
|
|
|
/*
|
|
** Check the values of the sentinels.
|
|
*/
|
|
if (NumLists) {
|
|
int *val = NULL;
|
|
if ((int)SentinelOne != 0) {
|
|
bool got = DataSafeClass<int>::Get(SentinelOne, val);
|
|
if (!got || val == NULL || *val != SENTINEL_ONE) {
|
|
WWDEBUG_SAY(("Data Safe: Incorrect sentinel value!\n"));
|
|
Security_Fault();
|
|
}
|
|
}
|
|
val = NULL;
|
|
if ((int)SentinelTwo != 0) {
|
|
bool got = DataSafeClass<int>::Get(SentinelTwo, val);
|
|
if (!got || val == NULL || *val != SENTINEL_TWO) {
|
|
WWDEBUG_SAY(("Data Safe: Incorrect sentinel value!\n"));
|
|
Security_Fault();
|
|
}
|
|
}
|
|
}
|
|
#ifdef WWDEBUG
|
|
Print_Safe_Stats_To_Debug_Output();
|
|
#endif //WWDEBUG
|
|
_checking = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
**
|
|
**
|
|
** DataSafeClass functions.
|
|
**
|
|
**
|
|
*/
|
|
|
|
|
|
/***********************************************************************************************
|
|
* DataSafeClass::DataSafeClass -- Class constructor *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Bogus pointer. Pointer that isn't referenced. It's only used for type info *
|
|
* Number of 'slop' entries to create *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 6/25/2001 1:51PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
DataSafeClass<T>::DataSafeClass(T*, int slopcount)
|
|
{
|
|
ThreadLockClass locker;
|
|
|
|
/*
|
|
** Clear out the return list.
|
|
*/
|
|
memset(ReturnList, 0, sizeof(ReturnList));
|
|
ReturnIndex = 0;
|
|
|
|
/*
|
|
** Get the type info for 'T'. Different types get stored in different places in the safe. Only similar types can be in the
|
|
** same safe list.
|
|
*/
|
|
int data_size = sizeof(T);
|
|
int type_code = Get_Type_Code();
|
|
|
|
/*
|
|
** Get_Type_ID will return the Type ID for this type code (instruction pointer). It will create a new type if this one
|
|
** doesn't already exist.
|
|
*/
|
|
int id = Get_Type_ID(type_code, data_size);
|
|
Type = id;
|
|
|
|
MinSlop = slopcount;
|
|
|
|
/*
|
|
** Add some slop entries here. These are just bogues entries than can be swapped in memory with real entries. The less
|
|
** commonly added data types should be give more slop entries.
|
|
*/
|
|
for (int i=0 ; i<slopcount ; i++) {
|
|
|
|
/*
|
|
** We need to make sure the constructor gets called for this object type before it's added to the safe. But we must
|
|
** also make sure that the destructor *isn't* called when we go out of scope here - it will be called explicitly
|
|
** when the datasafe is destructed. By using _alloca, and doing an in-place new, the memory that the object sits in
|
|
** will be freed when it goes out of scope but the destructor for 'T' won't be called.
|
|
*/
|
|
void *stackmem = _alloca(sizeof(T));
|
|
T *slop_ptr = new (stackmem) T;
|
|
Add_Entry(*slop_ptr, true);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* DataSafeClass::~DataSafeClass -- Class destructor. Removes remaining slop entries. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/5/2001 11:38AM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
DataSafeClass<T>::~DataSafeClass(void)
|
|
{
|
|
ThreadLockClass locker;
|
|
|
|
/*
|
|
** Remove all slop enries of our type from all lists. Note that this will delete non-slop entries too if any remain at this
|
|
** time.
|
|
*/
|
|
for (int i=0 ; i<NumLists ; i++) {
|
|
ds_assert(Safe[i] != NULL);
|
|
if (Safe[i] != NULL && Safe[i]->EntryType == Type && Safe[i]->EntryCount > 0) {
|
|
|
|
while (Safe[i]->EntryCount > 0) {
|
|
|
|
/*
|
|
** Delete the first entry in the list.
|
|
*/
|
|
int entries = Safe[i]->EntryCount;
|
|
DataSafeHandleClass handle = Safe[i]->SafeList->Handle ^ SimpleKey;
|
|
handle = handle ^ HandleKey;
|
|
Delete_Entry(handle);
|
|
|
|
/*
|
|
** Safety check. If something goes wrong and we didn't delete the entry then we will never get out of this loop
|
|
** so check for that case.
|
|
*/
|
|
ds_assert(entries == Safe[i]->EntryCount+1);
|
|
if (entries != Safe[i]->EntryCount+1) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Shutdown();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* DataSafeClass::Get_Type_Code -- Get a unique code per type without using RTTI *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Type code *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/2/2001 11:17AM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
unsigned long DataSafeClass<T>::Get_Type_Code(void)
|
|
{
|
|
/*
|
|
** Make sure this function gets expanded multiple times for different types by referencing the type.
|
|
*/
|
|
volatile int data_size = sizeof(T);
|
|
data_size = data_size;
|
|
|
|
/*
|
|
** Since we aren't using RTTI I need some other way of distinguishing types in the safe. Because it's templatised, this
|
|
** code will get expanded once for each type it's used with. I will use the location in memory of the function to
|
|
** uniquely identify each type. What a cunning plan.
|
|
*/
|
|
static unsigned long instruction_pointer;
|
|
instruction_pointer = 0;
|
|
__asm {
|
|
here:
|
|
lea eax,here
|
|
mov [instruction_pointer],eax
|
|
};
|
|
|
|
ds_assert(instruction_pointer != 0);
|
|
|
|
return(instruction_pointer);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* DataSafeClass::Get_Type_ID -- Get the id for the given type and size *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Type identifier code *
|
|
* Size of type *
|
|
* *
|
|
* OUTPUT: Type ID *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 6/27/2001 12:44PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
int DataSafeClass<T>::Get_Type_ID(unsigned long type_code, int size)
|
|
{
|
|
int id = 0;
|
|
|
|
/*
|
|
** See if we already have an ID for this type code.
|
|
*/
|
|
for (int i=0 ; i<TypeListCount ; i++) {
|
|
if (TypeList[i].TypeCode == type_code) {
|
|
ds_assert(TypeList[i].Size == size);
|
|
return(TypeList[i].ID);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Create a new type entry.
|
|
*/
|
|
ds_assert(TypeListCount < MAX_DATASAFE_TYPES);
|
|
if (TypeListCount < MAX_DATASAFE_TYPES) {
|
|
ds_assert(TypeList[TypeListCount].TypeCode == 0);
|
|
ds_assert(TypeList[TypeListCount].Size == 0);
|
|
TypeList[TypeListCount].TypeCode = type_code;
|
|
TypeList[TypeListCount].ID = TypeListCount;
|
|
TypeList[TypeListCount].Size = size;
|
|
id = TypeListCount++;
|
|
}
|
|
|
|
return(id);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* DataSafeClass::Add_Entry -- Create a new data safe entry and init it to the value provided *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Value *
|
|
* *
|
|
* OUTPUT: Handle *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 6/19/2001 8:34PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
DataSafeHandleClass DataSafeClass<T>::Add_Entry(T &value, bool is_slop)
|
|
{
|
|
ThreadLockClass locker;
|
|
Security_Check();
|
|
|
|
/*
|
|
** Allocate memory for the new entry.
|
|
*/
|
|
DataSafeEntryClass *entry_ptr = (DataSafeEntryClass*) new char [sizeof(DataSafeEntryDataClass<T>)];
|
|
ds_assert(entry_ptr);
|
|
|
|
if (entry_ptr) {
|
|
|
|
/*
|
|
** Init the data safe entry to reasonable values.
|
|
*/
|
|
entry_ptr->Next = NULL;
|
|
entry_ptr->Prev = NULL;
|
|
entry_ptr->Size = sizeof(value);
|
|
entry_ptr->IsSlop = is_slop;
|
|
|
|
/*
|
|
** Copy the data to the safe entry.
|
|
*/
|
|
DataSafeEntryDataClass<T>* data_ptr = (DataSafeEntryDataClass<T>*) entry_ptr;
|
|
Mem_Copy_Encrypt(& data_ptr->Data, &value, sizeof(value), true);
|
|
|
|
/*
|
|
** Find out which list we will be adding the entry to.
|
|
*/
|
|
int list = Get_Random_List_For_Insertion(Type);
|
|
ds_assert(list >= 0 && list < MAX_DATASAFE_LISTS);
|
|
ds_assert(Safe[list] != NULL);
|
|
|
|
if (list != -1 && Safe[list] != NULL) {
|
|
|
|
/*
|
|
** Now we know the list, we can get the next index id for that list and build a handle for the entry.
|
|
*/
|
|
int index = Get_Handle_ID(list);
|
|
ds_assert(index >= 0 && index < MAX_ENTRIES_PER_LIST);
|
|
DataSafeHandleClass handle;
|
|
handle.Handle.Part.List = list;
|
|
handle.Handle.Part.ID = index;
|
|
handle.Handle.Part.Type = Type;
|
|
|
|
/*
|
|
** We have a handle. Better encrypt it.
|
|
*/
|
|
DataSafeHandleClass encrypted_handle = handle ^ SimpleKey;
|
|
Checksum = Checksum ^ encrypted_handle;
|
|
|
|
/*
|
|
** Store it in the entry so we can do a search and match to get this entry out again.
|
|
*/
|
|
entry_ptr->Handle = encrypted_handle;
|
|
|
|
/*
|
|
** Insert the entry into the chosen list.
|
|
*/
|
|
Random_Insertion(entry_ptr, list, Type, is_slop);
|
|
|
|
/*
|
|
** Maybe add slop here if there is only one entry in the list.
|
|
** It will get removed later as more entries are added.
|
|
*/
|
|
if (Safe[list]->EntryCount == 1 && !is_slop) {
|
|
for (int i=0 ; i<MinSlop ; i++) {
|
|
entry_ptr = (DataSafeEntryClass*) new char [sizeof(DataSafeEntryDataClass<T>)];
|
|
ds_assert(entry_ptr);
|
|
|
|
if (entry_ptr) {
|
|
entry_ptr->Next = NULL;
|
|
entry_ptr->Prev = NULL;
|
|
entry_ptr->Size = sizeof(T);
|
|
entry_ptr->IsSlop = true;
|
|
|
|
/*
|
|
** Encrypt the garbage data in the uninitialized memory we just allocated for the
|
|
** object. It has to be encrypted to keep the CRC right.
|
|
*/
|
|
Encrypt(&((DataSafeEntryDataClass<T>*)entry_ptr)->Data, sizeof(T), SimpleKey, true);
|
|
|
|
/*
|
|
** Get a handle ID. Not really needed since we won't be returning a handle but it
|
|
** keeps the ID usage list neat. Fill in the rest of the handle to make it valid.
|
|
*/
|
|
DataSafeHandleClass slop_handle;
|
|
slop_handle.Handle.Part.ID = Get_Handle_ID(list);
|
|
slop_handle.Handle.Part.List = list;
|
|
slop_handle.Handle.Part.Type = Type;
|
|
DataSafeHandleClass encrypted_slop_handle = slop_handle ^ SimpleKey;
|
|
Checksum = Checksum ^ encrypted_slop_handle;
|
|
entry_ptr->Handle = encrypted_slop_handle;
|
|
|
|
/*
|
|
** Insert the slop entry.
|
|
*/
|
|
Random_Insertion(entry_ptr, list, Type, true);
|
|
}
|
|
}
|
|
ds_assert(Safe[list]->SlopCount == MinSlop);
|
|
ds_assert(Safe[list]->EntryCount == MinSlop + 1);
|
|
}
|
|
|
|
/*
|
|
** Maybe remove some slop if the list is filling up.
|
|
*/
|
|
if (Safe[list]->SlopCount != 0 && Safe[list]->EntryCount > Safe[list]->SlopCount * 2 && !is_slop) {
|
|
|
|
/*
|
|
** Lots of entries here. Remove all slop by building a list of slop entries then
|
|
** removing them one by one.
|
|
*/
|
|
entry_ptr = Safe[list]->SafeList;
|
|
ds_assert(entry_ptr != NULL);
|
|
DataSafeHandleClass removal_list[MAX_ENTRIES_PER_LIST];
|
|
int removal_count = 0;
|
|
|
|
if (entry_ptr) {
|
|
|
|
/*
|
|
** Go through each entry in the list.
|
|
*/
|
|
for (int j=0 ; j<Safe[list]->EntryCount ; j++) {
|
|
|
|
/*
|
|
** If this is a slop entry then mark it for removal.
|
|
*/
|
|
if (entry_ptr->IsSlop) {
|
|
DataSafeHandleClass decode_handle = entry_ptr->Handle ^ SimpleKey;
|
|
decode_handle = decode_handle ^ HandleKey;
|
|
removal_list[removal_count++] = decode_handle;
|
|
}
|
|
|
|
/*
|
|
** Next entry.
|
|
*/
|
|
entry_ptr = entry_ptr->Next;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Remove all marked entries. Delete_Entry will fix up the lists slop count.
|
|
*/
|
|
for (int j=0 ; j<removal_count ; j++) {
|
|
Delete_Entry(removal_list[j]);
|
|
}
|
|
ds_assert(Safe[list]->SlopCount == 0);
|
|
}
|
|
|
|
/*
|
|
** Return the handle, encrypted using the handle key.
|
|
*/
|
|
handle.Handle.Whole.WholeHandle ^= HandleKey;
|
|
return(handle);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Allocation error.
|
|
*/
|
|
return((DataSafeHandleClass)-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* DataSafeClass::Delete_Entry -- Delete an entry from the data safe *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Handle to entry *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 6/25/2001 1:32PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
void DataSafeClass<T>::Delete_Entry(DataSafeHandleClass handle)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
ThreadLockClass locker;
|
|
int list;
|
|
int id;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(handle.Is_Valid());
|
|
|
|
/*
|
|
** Check safe integrity.
|
|
*/
|
|
Security_Check();
|
|
|
|
/*
|
|
** The handles we give out are encrypted so we need to decrypt temporarily to extract the list number.
|
|
*/
|
|
DataSafeHandleClass new_handle = handle ^ HandleKey;
|
|
list = new_handle.Handle.Part.List;
|
|
id = new_handle.Handle.Part.ID;
|
|
|
|
/*
|
|
** Check that list number.
|
|
*/
|
|
ds_assert(list >= 0);
|
|
ds_assert(list < NumLists);
|
|
ds_assert(Safe[list] != NULL);
|
|
|
|
/*
|
|
** Get a pointer to the actual entry in the safe list.
|
|
*/
|
|
DataSafeEntryClass *entry_ptr = Get_Entry(handle);
|
|
ds_assert(entry_ptr != NULL);
|
|
|
|
if (entry_ptr != NULL) {
|
|
|
|
/*
|
|
** Apply the current data key to the handle to fix up the checksum.
|
|
*/
|
|
DataSafeHandleClass match_handle = new_handle ^ SimpleKey;
|
|
Checksum ^= match_handle;
|
|
|
|
/*
|
|
** We found the entry for this handle. We need to fix up the list pointers and delete the memory.
|
|
** Since we originally memcpy'ed this object into place we will have to call the destructor explicitly. The explicit
|
|
** destructor call will have no effect if the object doesn't have a destructor defined.
|
|
**
|
|
** We need to decrypt the object in place before calling the desturctor otherwise it will have a hard time acting on
|
|
** it's own data. This has the bonus of fixing up the checksum too.
|
|
*/
|
|
DataSafeEntryDataClass<T> *whole_entry_ptr = (DataSafeEntryDataClass<T>*) entry_ptr;
|
|
Decrypt(&whole_entry_ptr->Data, Get_Type_Size(Safe[list]->EntryType), SimpleKey);
|
|
if (!whole_entry_ptr->IsSlop) {
|
|
whole_entry_ptr->Data.T::~T();
|
|
}
|
|
Remove_From_List(list, entry_ptr);
|
|
Free_Handle_ID(list, id);
|
|
delete [] (void*) entry_ptr;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
** No match found.
|
|
*/
|
|
WWDEBUG_SAY(("Datasafe: No item found for handle %08x\n", (int)handle));
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* DataSafeClass::Get -- Get a copy of an item in the data safe. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Handle to data safe entry *
|
|
* (out) Pointer to copy of object *
|
|
* *
|
|
* OUTPUT: True if object retrieved OK *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/2/2001 11:07AM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
bool DataSafeClass<T>::Get(DataSafeHandleClass handle, T* &item)
|
|
{
|
|
ThreadLockClass locker;
|
|
|
|
/*
|
|
** Get a pointer to the entry.
|
|
*/
|
|
DataSafeEntryClass *entry_ptr = Get_Entry(handle);
|
|
|
|
if (entry_ptr == NULL) {
|
|
return(false);
|
|
}
|
|
|
|
DataSafeEntryDataClass<T> *data_entry_ptr = (DataSafeEntryDataClass<T>*) entry_ptr;
|
|
|
|
/*
|
|
** Copy the object from the data safe and decrypt it in one pass. Don't adjust the checksum as the object is staying
|
|
** the same in the safe.
|
|
*/
|
|
Mem_Copy_Decrypt(&ReturnList[ReturnIndex][0], &data_entry_ptr->Data, sizeof(T), false);
|
|
|
|
/*
|
|
** Return the object.
|
|
*/
|
|
item = (T*)(&ReturnList[ReturnIndex][0]);
|
|
|
|
/*
|
|
** Fix up the return list index.
|
|
*/
|
|
ReturnIndex++;
|
|
if (ReturnIndex >= MAX_OBJECT_COPIES) {
|
|
ReturnIndex = 0;
|
|
}
|
|
|
|
/*
|
|
** Move stuff around.
|
|
*/
|
|
Shuffle();
|
|
|
|
/*
|
|
** Check safe integrity.
|
|
*/
|
|
Security_Check();
|
|
|
|
return(true);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* DataSafeClass::Set -- Set the value of an entry in the data safe *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Handle to data in the safe *
|
|
* New value to set *
|
|
* *
|
|
* OUTPUT: True if handle was valid *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:11PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
bool DataSafeClass<T>::Set(DataSafeHandleClass handle, T *data)
|
|
{
|
|
ThreadLockClass locker;
|
|
|
|
/*
|
|
** Get a pointer to the entry.
|
|
*/
|
|
DataSafeEntryClass *entry_ptr = Get_Entry(handle);
|
|
|
|
if (entry_ptr == NULL) {
|
|
return(false);
|
|
}
|
|
|
|
DataSafeEntryDataClass<T> *data_entry_ptr = (DataSafeEntryDataClass<T>*) entry_ptr;
|
|
|
|
/*
|
|
** Decrypt the old entry just to fix up the checksum.
|
|
*/
|
|
Decrypt(&data_entry_ptr->Data, sizeof(T), SimpleKey, true);
|
|
|
|
/*
|
|
** Copy the object into the data safe and encrypt it in one pass.
|
|
*/
|
|
Mem_Copy_Encrypt(&data_entry_ptr->Data, data, sizeof(T), true);
|
|
|
|
/*
|
|
** Move stuff around.
|
|
*/
|
|
Shuffle();
|
|
|
|
/*
|
|
** Check safe integrity.
|
|
*/
|
|
Security_Check();
|
|
|
|
return(true);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
**
|
|
**
|
|
** SafeDataClass functions.
|
|
**
|
|
**
|
|
*/
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::SafeDataClass -- Class constructor. Adds the data to the data safe *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Initial value to store in the safe *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 11:50AM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline SafeDataClass<T>::SafeDataClass(T data)
|
|
{
|
|
Handle = DataSafeClass<T>::Add_Entry(data);
|
|
#ifdef WWDEBUG
|
|
DebugData = data;
|
|
#endif //WWDEBUG
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::SafeDataClass -- Class constructor. Adds the fetches a safe handle *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 11:50AM ST : Created *
|
|
*=============================================================================================*/
|
|
//warning C4700: local variable 'data' used without having been initialized
|
|
//#pragma warning(push, 0)
|
|
//#pragma warning(disable : 4700)
|
|
template <class T>
|
|
SafeDataClass<T>::SafeDataClass(void)
|
|
{
|
|
/*
|
|
** The data here isn't initialised since no default value was provided. I have to provide *some* sort of
|
|
** init though as the bloody compiler won't let me turn off the 'local variable 'data' used without having been initialized'
|
|
** message. Grrrr.
|
|
**
|
|
** Allocating the memory on the stack then doing an in place new seems to mollify the compiler so we don't get the warning
|
|
** and it does much the same thing as just declaring 'T data'. It also has the benefit that the destructor won't be called
|
|
** for the slop object when we exit this function but the memory will be freed.
|
|
*/
|
|
void *stackmem = _alloca(sizeof(T));
|
|
T *data = new (stackmem) T;
|
|
|
|
/*
|
|
** Add the entry to the data safe and note the handle.
|
|
*/
|
|
Handle = DataSafeClass<T>::Add_Entry(*data);
|
|
#ifdef WWDEBUG
|
|
DebugData = *data;
|
|
#endif //WWDEBUG
|
|
|
|
}
|
|
//#pragma warning(pop)
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::~SafeDataClass -- Class desturctor. Removes the data from the data safe *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 11:51AM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline SafeDataClass<T>::~SafeDataClass(void)
|
|
{
|
|
if (Handle.Is_Valid()) {
|
|
DataSafeClass<T>::Delete_Entry(Handle);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator = - assignment operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to assign *
|
|
* *
|
|
* OUTPUT: Data assigned *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator = (T const &data)
|
|
{
|
|
/*
|
|
** If we have a valid handle, then set the data into the data safe.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, (T*) &data);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = data;
|
|
#endif //WWDEBUG
|
|
}
|
|
|
|
return((T&)data);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator = - assignment operator for assigning from other SafeDataClass's *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to assign *
|
|
* *
|
|
* OUTPUT: Data assigned *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator = (SafeDataClass<T> &safedata)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safedata.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then get the data for this handle from the data safe.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
/*
|
|
** Get the value for the other safe data class
|
|
** and set it into the safe entry with our handle.
|
|
*/
|
|
other_value = safedata.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, (T*) other_value);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = *other_value;
|
|
#endif //WWDEBUG
|
|
} else {
|
|
/*
|
|
** Bad error case, have to return something so use the value we already have.
|
|
*/
|
|
return((T&)*other_value);
|
|
}
|
|
}
|
|
|
|
return((T&)*other_value);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator == - Equality check operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to compare against *
|
|
* *
|
|
* OUTPUT: true if equal *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator == (T const &data)
|
|
{
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
return(*data_ptr == data);
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator == - Equality check operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Safe Data to compare against *
|
|
* *
|
|
* OUTPUT: true if equal *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator == (SafeDataClass<T> &safedata)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safedata.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
*/
|
|
other_value = safedata.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
|
|
/*
|
|
** Check them against each other,
|
|
*/
|
|
return(*data_ptr == *other_value);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator != - Inequality check operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to compare against *
|
|
* *
|
|
* OUTPUT: true if not equal *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator != (T const &data)
|
|
{
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
return(*data_ptr != data);
|
|
}
|
|
}
|
|
|
|
return(true);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator != - Inequality check operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to compare against *
|
|
* *
|
|
* OUTPUT: true if not equal *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator != (SafeDataClass<T> &safedata)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safedata.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
*/
|
|
other_value = safedata.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
|
|
/*
|
|
** Check them against each other,
|
|
*/
|
|
return(*data_ptr != *other_value);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator > - > operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to compare against *
|
|
* *
|
|
* OUTPUT: true if greater than *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator > (T const &data)
|
|
{
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
return(*data_ptr > data);
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator > - > operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Safe Data to compare against *
|
|
* *
|
|
* OUTPUT: true if greater than *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator > (SafeDataClass<T> &safedata)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safedata.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
*/
|
|
other_value = safedata.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
|
|
/*
|
|
** Check them against each other,
|
|
*/
|
|
return(*data_ptr > *other_value);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator >= - >= operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to compare against *
|
|
* *
|
|
* OUTPUT: true if greater than or equal *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator >= (T const &data)
|
|
{
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
return(*data_ptr >= data);
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator >= - >= operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Safe Data to compare against *
|
|
* *
|
|
* OUTPUT: true if greater than or equal *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator >= (SafeDataClass<T> &safedata)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safedata.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
*/
|
|
other_value = safedata.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
|
|
/*
|
|
** Check them against each other,
|
|
*/
|
|
return(*data_ptr >= *other_value);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator < - < operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to compare against *
|
|
* *
|
|
* OUTPUT: true if less than *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator < (T const &data)
|
|
{
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
return(*data_ptr < data);
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator < - < operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Safe Data to compare against *
|
|
* *
|
|
* OUTPUT: true if less than *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator < (SafeDataClass<T> &safedata)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safedata.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
*/
|
|
other_value = safedata.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
|
|
/*
|
|
** Check them against each other,
|
|
*/
|
|
return(*data_ptr < *other_value);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator <= - <= operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to compare against *
|
|
* *
|
|
* OUTPUT: true if less than or equal *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator <= (T const &data)
|
|
{
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
return(*data_ptr <= data);
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator <= - <= operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Safe Data to compare against *
|
|
* *
|
|
* OUTPUT: true if less than or equal *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::operator <= (SafeDataClass<T> &safedata)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safedata.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then check the value against the supplied data.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
*/
|
|
other_value = safedata.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
|
|
/*
|
|
** Check them against each other,
|
|
*/
|
|
return(*data_ptr <= *other_value);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator + - + operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to add *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator + (T const &value)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
|
|
/*
|
|
** If we have a valid handle, then get the current value and apply the change
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
*data_ptr = *data_ptr + value;
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator + - + operator *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to add *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator + (SafeDataClass<T> &safevalue)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safevalue.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then get the data for this handle from the data safe.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
** and do the math.
|
|
*/
|
|
other_value = safevalue.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
*data_ptr = *data_ptr + *other_value;
|
|
return((T&)*data_ptr);
|
|
} else {
|
|
/*
|
|
** Bad error case, have to return something so use the value we already have.
|
|
*/
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator += - += operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to add *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator += (T const &value)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
|
|
/*
|
|
** If we have a valid handle, then get the current value and apply the change
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
*data_ptr = *data_ptr + value;
|
|
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = *data_ptr;
|
|
#endif //WWDEBUG
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator += - += operator *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to add *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator += (SafeDataClass<T> &safevalue)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safevalue.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then get the data for this handle from the data safe.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
** and do the math.
|
|
*/
|
|
other_value = safevalue.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
*data_ptr = *data_ptr + *other_value;
|
|
#ifdef WWDEBUG
|
|
ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = *data_ptr;
|
|
#endif //WWDEBUG
|
|
return((T&)*data_ptr);
|
|
} else {
|
|
/*
|
|
** Bad error case, have to return something so use the value we already have.
|
|
*/
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator - - - operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to subtract *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator - (T const &value)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
|
|
/*
|
|
** If we have a valid handle, then get the current value and apply the change
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
*data_ptr = *data_ptr - value;
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator - - - operator *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to subtract *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator - (SafeDataClass<T> &safevalue)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safevalue.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then get the data for this handle from the data safe.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
** and do the math.
|
|
*/
|
|
other_value = safevalue.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
*data_ptr = *data_ptr - *other_value;
|
|
return((T&)*data_ptr);
|
|
} else {
|
|
/*
|
|
** Bad error case, have to return something so use the value we already have.
|
|
*/
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator -= - -= operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to subtract *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator -= (T const &value)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
|
|
/*
|
|
** If we have a valid handle, then get the current value and apply the change
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
*data_ptr = *data_ptr - value;
|
|
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = *data_ptr;
|
|
#endif //WWDEBUG
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator -= - -= operator *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to subtract *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator -= (SafeDataClass<T> &safevalue)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safevalue.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then get the data for this handle from the data safe.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
** and do the math.
|
|
*/
|
|
other_value = safevalue.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
*data_ptr = *data_ptr - *other_value;
|
|
#ifdef WWDEBUG
|
|
ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = *data_ptr;
|
|
#endif //WWDEBUG
|
|
return((T&)*data_ptr);
|
|
} else {
|
|
/*
|
|
** Bad error case, have to return something so use the value we already have.
|
|
*/
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator * - * operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to multiply by *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator * (T const &value)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
|
|
/*
|
|
** If we have a valid handle, then get the current value and apply the change
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
*data_ptr = *data_ptr * value;
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator * - * operator *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to multiply by *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator * (SafeDataClass<T> &safevalue)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safevalue.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then get the data for this handle from the data safe.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
** and do the math.
|
|
*/
|
|
other_value = safevalue.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
*data_ptr = *data_ptr * *other_value;
|
|
return((T&)*data_ptr);
|
|
} else {
|
|
/*
|
|
** Bad error case, have to return something so use the value we already have.
|
|
*/
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator *= - *= operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to multiply by *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator *= (T const &value)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
|
|
/*
|
|
** If we have a valid handle, then get the current value and apply the change
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
*data_ptr = *data_ptr * value;
|
|
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = *data_ptr;
|
|
#endif //WWDEBUG
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator *= - *= operator *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to multiply by *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator *= (SafeDataClass<T> &safevalue)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safevalue.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then get the data for this handle from the data safe.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
** and do the math.
|
|
*/
|
|
other_value = safevalue.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
*data_ptr = *data_ptr * *other_value;
|
|
#ifdef WWDEBUG
|
|
ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = *data_ptr;
|
|
#endif //WWDEBUG
|
|
return((T&)*data_ptr);
|
|
} else {
|
|
/*
|
|
** Bad error case, have to return something so use the value we already have.
|
|
*/
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator / - / operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to divide by *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator / (T const &value)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(value != 0);
|
|
|
|
/*
|
|
** If we have a valid handle, then get the current value and apply the change
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
*data_ptr = *data_ptr / value;
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator / - / operator *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to divide by *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator / (SafeDataClass<T> &safevalue)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safevalue.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then get the data for this handle from the data safe.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
** and do the math.
|
|
*/
|
|
other_value = safevalue.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
ds_assert(*other_value != 0);
|
|
*data_ptr = *data_ptr / *other_value;
|
|
return((T&)*data_ptr);
|
|
} else {
|
|
/*
|
|
** Bad error case, have to return something so use the value we already have.
|
|
*/
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator /= - /= operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to divide by *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator /= (T const &value)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(value != 0);
|
|
|
|
/*
|
|
** If we have a valid handle, then get the current value and apply the change
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
*data_ptr = *data_ptr / value;
|
|
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = *data_ptr;
|
|
#endif //WWDEBUG
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator /= - /= operator *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Data to divide by *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator /= (SafeDataClass<T> &safevalue)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
T *other_value = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(safevalue.Get_Handle().Is_Valid());
|
|
ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));
|
|
|
|
/*
|
|
** If we have a valid handle, then get the data for this handle from the data safe.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
/*
|
|
** Looks like we have the value for this safe data class. Get the value for the other one.
|
|
** and do the math.
|
|
*/
|
|
other_value = safevalue.Get_Ptr();
|
|
ds_assert(other_value != NULL);
|
|
|
|
if (other_value) {
|
|
ds_assert(*other_value != 0);
|
|
*data_ptr = *data_ptr / *other_value;
|
|
#ifdef WWDEBUG
|
|
ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = *data_ptr;
|
|
#endif //WWDEBUG
|
|
return((T&)*data_ptr);
|
|
} else {
|
|
/*
|
|
** Bad error case, have to return something so use the value we already have.
|
|
*/
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator ++ - prefix increment operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator ++ (void)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
|
|
/*
|
|
** If we have a valid handle, then get the current value and apply the change
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
(*data_ptr)++;
|
|
|
|
#ifdef WWDEBUG
|
|
ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = *data_ptr;
|
|
#endif //WWDEBUG
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator -- - prefix decrement operator. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Result *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator -- (void)
|
|
{
|
|
/*
|
|
** Locals.
|
|
*/
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** Asserts.
|
|
*/
|
|
ds_assert(Handle.Is_Valid());
|
|
|
|
/*
|
|
** If we have a valid handle, then get the current value and apply the change
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
ds_assert(data_ptr);
|
|
|
|
if (data_ptr) {
|
|
(*data_ptr)--;
|
|
|
|
#ifdef WWDEBUG
|
|
ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Set(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
#ifdef WWDEBUG
|
|
DebugData = *data_ptr;
|
|
#endif //WWDEBUG
|
|
return((T&)*data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case, have to return something.
|
|
*/
|
|
return((T&)ErrorVal[0]);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator ++ - postfix ++ operator *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: int (not used, denotes postfix operator) *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/23/2001 3:54PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator ++ (int)
|
|
{
|
|
/*
|
|
** Just call the prefix version of the operator.
|
|
*/
|
|
return(this->operator ++ ());
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator -- - postfix -- operator *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: int (not used, denotes postfix operator) *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/23/2001 3:54PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator -- (int)
|
|
{
|
|
/*
|
|
** Just call the prefix version of the operator.
|
|
*/
|
|
return(this->operator -- ());
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator () - Conversion operator used for data retrieval *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: nothing *
|
|
* *
|
|
* OUTPUT: Copy of data in safe *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T &SafeDataClass<T>::operator () (void) const
|
|
{
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
|
|
** handle.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
if (data_ptr) {
|
|
return(*data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case. Need to return some valid value.
|
|
*/
|
|
static T oh_dear;
|
|
return(oh_dear);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator int -- Return the data for this class as an int *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Data cast to int *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/6/2001 11:47AM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline SafeDataClass<T>::operator int (void) const
|
|
{
|
|
ds_assert(sizeof(T) == sizeof(int));
|
|
|
|
T *data_ptr = NULL;
|
|
|
|
#ifdef WWDEBUG
|
|
/*
|
|
** Check that T is safe to return as an int
|
|
*/
|
|
T x = 0;
|
|
int y = (T)x;
|
|
ds_assert(x == y);
|
|
#endif //WWDEBUG
|
|
|
|
/*
|
|
** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
|
|
** handle.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
if (data_ptr) {
|
|
return(*((int*)data_ptr));
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case. Need to return some valid value.
|
|
*/
|
|
static int oh_dear;
|
|
return(oh_dear);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator unsigned int -- Return the data for this class as an unsigned int *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Data cast to unsigned int *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/6/2001 11:47AM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline SafeDataClass<T>::operator unsigned int (void) const
|
|
{
|
|
ds_assert(sizeof(T) == sizeof(unsigned int));
|
|
|
|
T *data_ptr = NULL;
|
|
|
|
#ifdef WWDEBUG
|
|
/*
|
|
** Check that T is safe to return as an unsigned int
|
|
*/
|
|
T x = 0;
|
|
unsigned int y = (T)x;
|
|
ds_assert(x == y);
|
|
#endif //WWDEBUG
|
|
|
|
/*
|
|
** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
|
|
** handle.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
if (data_ptr) {
|
|
return(*((unsigned int*)data_ptr));
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case. Need to return some valid value.
|
|
*/
|
|
static unsigned int oh_dear;
|
|
return(oh_dear);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator long -- Return the data for this class as a long *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Data cast to long *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/6/2001 11:47AM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline SafeDataClass<T>::operator long (void) const
|
|
{
|
|
ds_assert(sizeof(T) == sizeof(long));
|
|
|
|
T *data_ptr = NULL;
|
|
|
|
#ifdef WWDEBUG
|
|
/*
|
|
** Check that T is safe to return as a long
|
|
*/
|
|
T x = 0;
|
|
long y = (T)x;
|
|
ds_assert(x == y);
|
|
#endif //WWDEBUG
|
|
|
|
/*
|
|
** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
|
|
** handle.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
if (data_ptr) {
|
|
return(*((long*)data_ptr));
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case. Need to return some valid value.
|
|
*/
|
|
static long oh_dear;
|
|
return(oh_dear);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator int -- Return the data for this class as an unsigned long *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Data cast to unsigned long *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/6/2001 11:47AM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline SafeDataClass<T>::operator unsigned long (void) const
|
|
{
|
|
ds_assert(sizeof(T) == sizeof(unsigned long));
|
|
|
|
T *data_ptr = NULL;
|
|
|
|
#ifdef WWDEBUG
|
|
/*
|
|
** Check that T is safe to return as an unsigned long
|
|
*/
|
|
T x = 0;
|
|
unsigned long y = (T)x;
|
|
ds_assert(x == y);
|
|
#endif //WWDEBUG
|
|
|
|
/*
|
|
** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
|
|
** handle.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
if (data_ptr) {
|
|
return(*((unsigned long*)data_ptr));
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case. Need to return some valid value.
|
|
*/
|
|
static unsigned long oh_dear;
|
|
return(oh_dear);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator int -- Return the data for this class as a float *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Data cast to float *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/6/2001 11:47AM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline SafeDataClass<T>::operator float (void) const
|
|
{
|
|
ds_assert(sizeof(T) == sizeof(float));
|
|
|
|
T *data_ptr = NULL;
|
|
|
|
#ifdef WWDEBUG
|
|
/*
|
|
** Check that T is safe to return as a float
|
|
*/
|
|
T x = 0;
|
|
float y = (T)x;
|
|
ds_assert(x == y);
|
|
#endif //WWDEBUG
|
|
|
|
/*
|
|
** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
|
|
** handle.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
if (data_ptr) {
|
|
return(*((float*)data_ptr));
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case. Need to return some valid value.
|
|
*/
|
|
static float oh_dear;
|
|
return(oh_dear);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::operator int -- Return the data for this class as a double *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Data cast to double *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/6/2001 11:47AM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline SafeDataClass<T>::operator double (void) const
|
|
{
|
|
ds_assert(sizeof(T) == sizeof(double));
|
|
|
|
T *data_ptr = NULL;
|
|
|
|
#ifdef WWDEBUG
|
|
/*
|
|
** Check that T is safe to return as a double
|
|
*/
|
|
T x = 0;
|
|
double y = (T)x;
|
|
ds_assert(x == y);
|
|
#endif //WWDEBUG
|
|
|
|
/*
|
|
** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
|
|
** handle.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
if (data_ptr) {
|
|
return(*((double*)data_ptr));
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case. Need to return some valid value.
|
|
*/
|
|
static double oh_dear;
|
|
return(oh_dear);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::Get_Ptr - Get a pointer to a decrypted version of a class in the data safe *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: nothing *
|
|
* *
|
|
* OUTPUT: Ptr to copy of data in safe *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/3/2001 12:05PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline T *SafeDataClass<T>::Get_Ptr(void) const
|
|
{
|
|
T *data_ptr = NULL;
|
|
|
|
/*
|
|
** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
|
|
** handle.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
#ifdef WWDEBUG
|
|
bool ok =
|
|
#endif //WWDEBUG
|
|
DataSafeClass<T>::Get(Handle, data_ptr);
|
|
ds_assert(ok);
|
|
if (data_ptr) {
|
|
return(data_ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Error case.
|
|
*/
|
|
ds_assert(false);
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* SafeDataClass::Commit -- Write decrypted data safe data back into the safe *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Ptr to data (must be from prior return list) *
|
|
* *
|
|
* OUTPUT: True if commited back into the safe *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 7/13/2001 2:28PM ST : Created *
|
|
*=============================================================================================*/
|
|
template <class T>
|
|
inline bool SafeDataClass<T>::Commit(T *data_ptr) const
|
|
{
|
|
ds_assert(Handle.Is_Valid());
|
|
ds_assert(DataSafeClass<T>::In_Return_List(data_ptr));
|
|
|
|
/*
|
|
** If the handle is valid, and the data pointer is one of our temporary return buffers
|
|
** then copy the data back into the safe.
|
|
*/
|
|
if (Handle.Is_Valid()) {
|
|
|
|
/*
|
|
** Verify it's one of our temp data pointers.
|
|
*/
|
|
if (DataSafeClass<T>::In_Return_List(data_ptr)) {
|
|
#ifdef WWDEBUG
|
|
DebugData = *data_ptr;
|
|
#endif //WWDEBUG
|
|
return(DataSafeClass<T>::Set(Handle, data_ptr));
|
|
}
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
#pragma warning(default : 4189)
|
|
#pragma warning(default : 4101)
|
|
|
|
|
|
#endif //_DATASAFE_H
|
|
|
|
|
|
|
|
|