Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
366 lines
12 KiB
C++
366 lines
12 KiB
C++
#ifndef __COMUTILHPP__
|
|
#define __COMUTILHPP__
|
|
|
|
#pragma once
|
|
|
|
#include <tchar.h>
|
|
#include <limits.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <windows.h>
|
|
|
|
template<typename type>
|
|
inline type clamp (const type& min,const type& x,const type& max)
|
|
{
|
|
if (x < min)
|
|
return min;
|
|
if (x>max)
|
|
return max;
|
|
return x;
|
|
}
|
|
#if 0
|
|
template<typename type>
|
|
type max(const type& a,const type& b)
|
|
{
|
|
return (((a) > (b)) ? (a) : (b));
|
|
}
|
|
template<typename type>
|
|
type min(const type& a,const type& b)
|
|
{
|
|
return (((a) < (b)) ? (a) : (b));
|
|
}
|
|
#endif
|
|
inline bool IsAlNum(BYTE bChar)
|
|
{
|
|
#pragma warning (disable:4800)
|
|
WORD wResult;
|
|
BOOL bRc;
|
|
|
|
bRc = GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, (LPCTSTR)&bChar, 1, &wResult);
|
|
assert(bRc);
|
|
return (bool)(wResult & (C1_ALPHA | C1_DIGIT));
|
|
}
|
|
|
|
inline bool IsSpace(BYTE bChar)
|
|
{
|
|
#pragma warning (disable:4800)
|
|
WORD wResult;
|
|
BOOL bRc;
|
|
|
|
bRc = GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, (LPCTSTR)&bChar, 1, &wResult);
|
|
assert(bRc);
|
|
return (bool)(wResult & (C1_SPACE));
|
|
}
|
|
|
|
inline bool IsSpace(WORD bChar)
|
|
{
|
|
#pragma warning (disable:4800)
|
|
WORD wResult;
|
|
BOOL bRc;
|
|
|
|
bRc = GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE1, (LPCTSTR)&bChar, 2, &wResult);
|
|
assert(bRc);
|
|
return (bool)(wResult & (C1_SPACE));
|
|
}
|
|
|
|
|
|
#define _countof(array) (sizeof(array)/sizeof(array[0]))
|
|
|
|
#ifdef OLE2ANSI
|
|
typedef LPSTR BSTR;
|
|
#else
|
|
typedef LPWSTR BSTR;// must (semantically) match typedef in oleauto.h
|
|
#endif
|
|
|
|
struct CCom_StringData
|
|
{
|
|
long nRefs; // reference count
|
|
int nDataLength;
|
|
int nAllocLength;
|
|
// TCHAR data[nAllocLength]
|
|
|
|
TCHAR* data()
|
|
{ return (TCHAR*)(this+1); }
|
|
};
|
|
|
|
bool comline_AfxIsValidString(LPCWSTR lpsz, int nLength = -1);
|
|
bool comline_AfxIsValidString(LPCSTR lpsz, int nLength = -1);
|
|
bool comline_AfxIsValidAddress(const void* lp,UINT nBytes, bool bReadWrite = true);
|
|
int comline_AfxLoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf,HINSTANCE inst);
|
|
|
|
class CCom_String
|
|
{
|
|
public:
|
|
// Constructors
|
|
CCom_String();
|
|
CCom_String(const CCom_String& stringSrc);
|
|
CCom_String(TCHAR ch, int nRepeat = 1);
|
|
CCom_String(LPCTSTR lpsz);
|
|
CCom_String(LPCWSTR lpsz);
|
|
CCom_String(LPCTSTR lpch, int nLength);
|
|
CCom_String(const unsigned char* psz);
|
|
|
|
// Attributes & Operations
|
|
// as an array of characters
|
|
int GetLength() const;
|
|
bool IsEmpty() const;
|
|
void Empty(); // free up the data
|
|
|
|
TCHAR GetAt(int nIndex) const; // 0 based
|
|
TCHAR operator[](int nIndex) const; // same as GetAt
|
|
void SetAt(int nIndex, TCHAR ch);
|
|
operator LPCTSTR() const; // as a C string
|
|
|
|
// overloaded assignment
|
|
const CCom_String& operator=(const CCom_String& stringSrc);
|
|
const CCom_String& operator=(TCHAR ch);
|
|
#ifdef _UNICODE
|
|
const CCom_String& operator=(char ch);
|
|
#endif
|
|
const CCom_String& operator=(LPCSTR lpsz);
|
|
const CCom_String& operator=(LPCWSTR lpsz);
|
|
const CCom_String& operator=(const unsigned char* psz);
|
|
|
|
// string concatenation
|
|
const CCom_String& operator+=(const CCom_String& string);
|
|
const CCom_String& operator+=(TCHAR ch);
|
|
#ifdef _UNICODE
|
|
const CCom_String& operator+=(char ch);
|
|
#endif
|
|
const CCom_String& operator+=(LPCTSTR lpsz);
|
|
|
|
friend CCom_String operator+(const CCom_String& string1,
|
|
const CCom_String& string2);
|
|
friend CCom_String operator+(const CCom_String& string, TCHAR ch);
|
|
friend CCom_String operator+(TCHAR ch, const CCom_String& string);
|
|
#ifdef _UNICODE
|
|
friend CCom_String operator+(const CCom_String& string, char ch);
|
|
friend CCom_String operator+(char ch, const CCom_String& string);
|
|
#endif
|
|
friend CCom_String operator+(const CCom_String& string, LPCTSTR lpsz);
|
|
friend CCom_String operator+(LPCTSTR lpsz, const CCom_String& string);
|
|
|
|
// string comparison
|
|
int Compare(LPCTSTR lpsz) const; // straight character
|
|
int CompareNoCase(LPCTSTR lpsz) const; // ignore case
|
|
int Collate(LPCTSTR lpsz) const; // NLS aware
|
|
|
|
// simple sub-string extraction
|
|
CCom_String Mid(int nFirst, int nCount) const;
|
|
CCom_String Mid(int nFirst) const;
|
|
CCom_String Left(int nCount) const;
|
|
CCom_String Right(int nCount) const;
|
|
|
|
CCom_String SpanIncluding(LPCTSTR lpszCharSet) const;
|
|
CCom_String SpanExcluding(LPCTSTR lpszCharSet) const;
|
|
|
|
// upper/lower/reverse conversion
|
|
void MakeUpper();
|
|
void MakeLower();
|
|
void MakeReverse();
|
|
|
|
// trimming whitespace (either side)
|
|
void TrimRight();
|
|
void TrimLeft();
|
|
|
|
// searching (return starting index, or -1 if not found)
|
|
// look for a single character match
|
|
int Find(TCHAR ch) const; // like "C" strchr
|
|
int ReverseFind(TCHAR ch) const;
|
|
int FindOneOf(LPCTSTR lpszCharSet) const;
|
|
|
|
// advanced manipulation
|
|
int Replace(TCHAR chOld, TCHAR chNew);
|
|
int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew);
|
|
int Remove(TCHAR chRemove);
|
|
int Insert(int nIndex, TCHAR ch);
|
|
int Insert(int nIndex, LPCTSTR pstr);
|
|
int Delete(int nIndex, int nCount = 1);
|
|
|
|
// look for a specific sub-string
|
|
int Find(LPCTSTR lpszSub) const; // like "C" strstr
|
|
|
|
// simple formatting
|
|
void _cdecl Format(LPCTSTR lpszFormat, ...);
|
|
void _cdecl Format(UINT nFormatID,HINSTANCE inst, ...);
|
|
void _cdecl FormatHex (char *mem,int count);
|
|
void FormatV(LPCTSTR lpszFormat, va_list argList);
|
|
|
|
#ifndef _MAC
|
|
// formatting for localization (uses FormatMessage API)
|
|
void _cdecl FormatMessage(LPCTSTR lpszFormat, ...);
|
|
void _cdecl FormatMessage(UINT nFormatID,HINSTANCE inst, ...);
|
|
#endif
|
|
|
|
// Windows support
|
|
bool LoadString(UINT nID,HINSTANCE inst=NULL); // load from string resource
|
|
// 255 chars max
|
|
#ifndef _UNICODE
|
|
// ANSI <-> OEM support (convert string in place)
|
|
void AnsiToOem();
|
|
void OemToAnsi();
|
|
#endif
|
|
|
|
#ifndef _AFX_NO_BSTR_SUPPORT
|
|
// OLE BSTR support (use for OLE automation)
|
|
BSTR AllocSysString() const;
|
|
BSTR SetSysString(BSTR* pbstr) const;
|
|
#endif
|
|
|
|
// Access to string implementation buffer as "C" character array
|
|
LPTSTR GetBuffer(int nMinBufLength);
|
|
void ReleaseBuffer(int nNewLength = -1);
|
|
LPTSTR GetBufferSetLength(int nNewLength);
|
|
void FreeExtra();
|
|
|
|
// Use LockBuffer/UnlockBuffer to turn refcounting off
|
|
LPTSTR LockBuffer();
|
|
void UnlockBuffer();
|
|
|
|
// Implementation
|
|
public:
|
|
~CCom_String();
|
|
int GetAllocLength() const;
|
|
|
|
protected:
|
|
LPTSTR m_pchData; // pointer to ref counted string data
|
|
|
|
// implementation helpers
|
|
CCom_StringData* GetData() const;
|
|
void Init();
|
|
void AllocCopy(CCom_String& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const;
|
|
void AllocBuffer(int nLen);
|
|
void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData);
|
|
void ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data);
|
|
void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData);
|
|
void CopyBeforeWrite();
|
|
void AllocBeforeWrite(int nLen);
|
|
void Release();
|
|
static void PASCAL Release(CCom_StringData* pData);
|
|
static int PASCAL SafeStrlen(LPCTSTR lpsz);
|
|
};
|
|
|
|
// Compare helpers
|
|
bool operator==(const CCom_String& s1, const CCom_String& s2);
|
|
bool operator==(const CCom_String& s1, LPCTSTR s2);
|
|
bool operator==(LPCTSTR s1, const CCom_String& s2);
|
|
bool operator!=(const CCom_String& s1, const CCom_String& s2);
|
|
bool operator!=(const CCom_String& s1, LPCTSTR s2);
|
|
bool operator!=(LPCTSTR s1, const CCom_String& s2);
|
|
bool operator<(const CCom_String& s1, const CCom_String& s2);
|
|
bool operator<(const CCom_String& s1, LPCTSTR s2);
|
|
bool operator<(LPCTSTR s1, const CCom_String& s2);
|
|
bool operator>(const CCom_String& s1, const CCom_String& s2);
|
|
bool operator>(const CCom_String& s1, LPCTSTR s2);
|
|
bool operator>(LPCTSTR s1, const CCom_String& s2);
|
|
bool operator<=(const CCom_String& s1, const CCom_String& s2);
|
|
bool operator<=(const CCom_String& s1, LPCTSTR s2);
|
|
bool operator<=(LPCTSTR s1, const CCom_String& s2);
|
|
bool operator>=(const CCom_String& s1, const CCom_String& s2);
|
|
bool operator>=(const CCom_String& s1, LPCTSTR s2);
|
|
bool operator>=(LPCTSTR s1, const CCom_String& s2);
|
|
|
|
// conversion helpers
|
|
int _cdecl _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count);
|
|
int _cdecl _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count);
|
|
|
|
// Globals
|
|
extern TCHAR comline_afxChNil;
|
|
const CCom_String& comline_AfxGetEmptyString();
|
|
#define comline_afxEmptyString comline_AfxGetEmptyString()
|
|
|
|
|
|
|
|
// CCom_String
|
|
inline CCom_StringData* CCom_String::GetData() const
|
|
{ assert(m_pchData != NULL); return ((CCom_StringData*)m_pchData)-1; }
|
|
inline void CCom_String::Init()
|
|
{ m_pchData = comline_afxEmptyString.m_pchData; }
|
|
inline CCom_String::CCom_String(const unsigned char* lpsz)
|
|
{ Init(); *this = (LPCSTR)lpsz; }
|
|
inline const CCom_String& CCom_String::operator=(const unsigned char* lpsz)
|
|
{ *this = (LPCSTR)lpsz; return *this; }
|
|
#ifdef _UNICODE
|
|
inline const CCom_String& CCom_String::operator+=(char ch)
|
|
{ *this += (TCHAR)ch; return *this; }
|
|
inline const CCom_String& CCom_String::operator=(char ch)
|
|
{ *this = (TCHAR)ch; return *this; }
|
|
inline CCom_String operator+(const CCom_String& string, char ch)
|
|
{ return string + (TCHAR)ch; }
|
|
inline CCom_String operator+(char ch, const CCom_String& string)
|
|
{ return (TCHAR)ch + string; }
|
|
#endif
|
|
|
|
inline int CCom_String::GetLength() const
|
|
{ return GetData()->nDataLength; }
|
|
inline int CCom_String::GetAllocLength() const
|
|
{ return GetData()->nAllocLength; }
|
|
inline bool CCom_String::IsEmpty() const
|
|
{ return GetData()->nDataLength == 0; }
|
|
inline CCom_String::operator LPCTSTR() const
|
|
{ return m_pchData; }
|
|
inline int PASCAL CCom_String::SafeStrlen(LPCTSTR lpsz)
|
|
{ return (lpsz == NULL) ? 0 : lstrlen(lpsz); }
|
|
|
|
// CCom_String support (windows specific)
|
|
inline int CCom_String::Compare(LPCTSTR lpsz) const
|
|
{ return _tcscmp(m_pchData, lpsz); } // MBCS/Unicode aware
|
|
inline int CCom_String::CompareNoCase(LPCTSTR lpsz) const
|
|
{ return _tcsicmp(m_pchData, lpsz); } // MBCS/Unicode aware
|
|
// CCom_String::Collate is often slower than Compare but is MBSC/Unicode
|
|
// aware as well as locale-sensitive with respect to sort order.
|
|
inline int CCom_String::Collate(LPCTSTR lpsz) const
|
|
{ return _tcscoll(m_pchData, lpsz); } // locale sensitive
|
|
|
|
inline TCHAR CCom_String::GetAt(int nIndex) const
|
|
{
|
|
assert(nIndex >= 0);
|
|
assert(nIndex < GetData()->nDataLength);
|
|
return m_pchData[nIndex];
|
|
}
|
|
inline TCHAR CCom_String::operator[](int nIndex) const
|
|
{
|
|
// same as GetAt
|
|
assert(nIndex >= 0);
|
|
assert(nIndex < GetData()->nDataLength);
|
|
return m_pchData[nIndex];
|
|
}
|
|
inline bool operator==(const CCom_String& s1, const CCom_String& s2)
|
|
{ return s1.Compare(s2) == 0; }
|
|
inline bool operator==(const CCom_String& s1, LPCTSTR s2)
|
|
{ return s1.Compare(s2) == 0; }
|
|
inline bool operator==(LPCTSTR s1, const CCom_String& s2)
|
|
{ return s2.Compare(s1) == 0; }
|
|
inline bool operator!=(const CCom_String& s1, const CCom_String& s2)
|
|
{ return s1.Compare(s2) != 0; }
|
|
inline bool operator!=(const CCom_String& s1, LPCTSTR s2)
|
|
{ return s1.Compare(s2) != 0; }
|
|
inline bool operator!=(LPCTSTR s1, const CCom_String& s2)
|
|
{ return s2.Compare(s1) != 0; }
|
|
inline bool operator<(const CCom_String& s1, const CCom_String& s2)
|
|
{ return s1.Compare(s2) < 0; }
|
|
inline bool operator<(const CCom_String& s1, LPCTSTR s2)
|
|
{ return s1.Compare(s2) < 0; }
|
|
inline bool operator<(LPCTSTR s1, const CCom_String& s2)
|
|
{ return s2.Compare(s1) > 0; }
|
|
inline bool operator>(const CCom_String& s1, const CCom_String& s2)
|
|
{ return s1.Compare(s2) > 0; }
|
|
inline bool operator>(const CCom_String& s1, LPCTSTR s2)
|
|
{ return s1.Compare(s2) > 0; }
|
|
inline bool operator>(LPCTSTR s1, const CCom_String& s2)
|
|
{ return s2.Compare(s1) < 0; }
|
|
inline bool operator<=(const CCom_String& s1, const CCom_String& s2)
|
|
{ return s1.Compare(s2) <= 0; }
|
|
inline bool operator<=(const CCom_String& s1, LPCTSTR s2)
|
|
{ return s1.Compare(s2) <= 0; }
|
|
inline bool operator<=(LPCTSTR s1, const CCom_String& s2)
|
|
{ return s2.Compare(s1) >= 0; }
|
|
inline bool operator>=(const CCom_String& s1, const CCom_String& s2)
|
|
{ return s1.Compare(s2) >= 0; }
|
|
inline bool operator>=(const CCom_String& s1, LPCTSTR s2)
|
|
{ return s1.Compare(s2) >= 0; }
|
|
inline bool operator>=(LPCTSTR s1, const CCom_String& s2)
|
|
{ return s2.Compare(s1) <= 0; }
|
|
|
|
#endif |