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.
496 lines
12 KiB
C++
496 lines
12 KiB
C++
//===========================================================================//
|
|
// File: string.cpp //
|
|
// Project: MUNGA //
|
|
// Contents: //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 03/26/95 ECH Initial coding. //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "StuffHeaders.hpp"
|
|
#include <mbstring.h>
|
|
#define __mbsrchr(s,c) (char*)_mbsrchr((const unsigned char*)(s),(c))
|
|
|
|
//#############################################################################
|
|
//############################## MString ################################
|
|
//#############################################################################
|
|
|
|
MString
|
|
*MString::s_Empty = NULL;
|
|
|
|
HGOSHEAP
|
|
g_MStringHeap = NULL;
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
MString::InitializeClass()
|
|
{
|
|
Verify(!g_MStringHeap);
|
|
g_MStringHeap = gos_CreateMemoryHeap("MString");
|
|
Check_Pointer(g_MStringHeap);
|
|
|
|
Verify(!s_Empty);
|
|
s_Empty = new MString("");
|
|
Check_Object(s_Empty);
|
|
|
|
|
|
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
MString::TerminateClass()
|
|
{
|
|
Check_Object(s_Empty);
|
|
delete s_Empty;
|
|
s_Empty = NULL;
|
|
|
|
Check_Pointer(g_MStringHeap);
|
|
gos_DestroyMemoryHeap(g_MStringHeap);
|
|
g_MStringHeap = NULL;
|
|
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
MString::MString(const char *cstr)
|
|
{
|
|
gos_PushCurrentHeap(g_MStringHeap);
|
|
|
|
if (!cstr)
|
|
m_text = NULL;
|
|
else
|
|
{
|
|
unsigned t = strlen(cstr)+2;
|
|
m_text = new char[t];
|
|
Check_Pointer(m_text);
|
|
*m_text++ = 1;
|
|
Mem_Copy(m_text, cstr, t-1, t-1);
|
|
}
|
|
|
|
gos_PopCurrentHeap();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
MString::MString(
|
|
const char *cstr1,
|
|
const char *cstr2
|
|
)
|
|
{
|
|
Check_Pointer(cstr1);
|
|
Check_Pointer(cstr2);
|
|
|
|
gos_PushCurrentHeap(g_MStringHeap);
|
|
|
|
unsigned t1 = strlen(cstr1);
|
|
unsigned t2 = strlen(cstr2);
|
|
unsigned t = t1 + t2 + 2;
|
|
m_text = new char[t];
|
|
Check_Pointer(m_text);
|
|
*m_text++ = 1;
|
|
Mem_Copy(m_text, cstr1, t1, t-1);
|
|
Mem_Copy(m_text+t1, cstr2, t2+1, t-1-t1);
|
|
|
|
gos_PopCurrentHeap();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
MString::MString(
|
|
const char *cstr,
|
|
char ch
|
|
)
|
|
{
|
|
Check_Pointer(cstr);
|
|
Verify(ch != '\0');
|
|
|
|
gos_PushCurrentHeap(g_MStringHeap);
|
|
|
|
unsigned t = strlen(cstr)+3;
|
|
m_text = new char[t];
|
|
Check_Pointer(m_text);
|
|
*m_text++ = 1;
|
|
Mem_Copy(m_text, cstr, t-3, t-1);
|
|
m_text[t-3] = ch;
|
|
m_text[t-2] = '\0';
|
|
|
|
gos_PopCurrentHeap();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
MString::AllocateLength(unsigned length)
|
|
{
|
|
Check_Object(this);
|
|
|
|
gos_PushCurrentHeap(g_MStringHeap);
|
|
|
|
DetachReference();
|
|
if (!length)
|
|
m_text = NULL;
|
|
else
|
|
{
|
|
unsigned t = length+2;
|
|
m_text = new char[t];
|
|
Check_Pointer(m_text);
|
|
*m_text++ = 1;
|
|
#if defined(_ARMOR)
|
|
memset(m_text, ' ', length);
|
|
m_text[length] = '\0';
|
|
#endif
|
|
}
|
|
|
|
gos_PopCurrentHeap();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
MString&
|
|
MString::operator=(const MString &str)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(&str);
|
|
Verify(!m_text || m_text != str.m_text || m_text[-1]>1);
|
|
|
|
DetachReference();
|
|
m_text = str.m_text;
|
|
if (m_text)
|
|
{
|
|
char *count = m_text-1;
|
|
Check_Pointer(count);
|
|
Verify(*count != -1);
|
|
++(*count);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
MString&
|
|
MString::operator=(const char *cstr)
|
|
{
|
|
Check_Object(this);
|
|
Verify(!m_text || m_text != cstr || m_text[-1]>1);
|
|
|
|
DetachReference();
|
|
if (!cstr)
|
|
m_text = NULL;
|
|
else
|
|
{
|
|
gos_PushCurrentHeap(g_MStringHeap);
|
|
|
|
unsigned t = strlen(cstr)+2;
|
|
m_text = new char[t];
|
|
Check_Pointer(m_text);
|
|
*(m_text++) = 1;
|
|
Mem_Copy(m_text, cstr, t-1, t-1);
|
|
|
|
gos_PopCurrentHeap();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
bool
|
|
Stuff::Close_Enough(
|
|
const char *str1,
|
|
const char *str2,
|
|
Scalar e
|
|
)
|
|
{
|
|
Check_Pointer(str1);
|
|
Check_Pointer(str2);
|
|
|
|
return !_stricmp(str1, str2);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
MString
|
|
MString::GetNthToken(
|
|
size_t nth_token,
|
|
const char *delimiters
|
|
) const
|
|
{
|
|
Check_Object(this);
|
|
if (!m_text)
|
|
return *this;
|
|
|
|
//
|
|
// Which delimters to use
|
|
//
|
|
const char *delimiter_string = " \t,";
|
|
if (delimiters != NULL)
|
|
delimiter_string = delimiters;
|
|
Check_Pointer(delimiter_string);
|
|
|
|
//
|
|
// Parse string with strtok
|
|
//
|
|
MString temp((const char*)*this);
|
|
size_t i;
|
|
Check_Pointer(temp.m_text);
|
|
char *ptr = strtok(temp, delimiter_string);
|
|
for (i = 0; i < nth_token; i++)
|
|
{
|
|
if ((ptr = strtok(NULL, delimiter_string)) == NULL)
|
|
break;
|
|
}
|
|
|
|
return MString(ptr);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
MString::ToUpper()
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(m_text);
|
|
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// If there is more that one reference to this string, split it off
|
|
//-----------------------------------------------------------------
|
|
//
|
|
if ((BYTE)m_text[-1] > 1)
|
|
operator=(operator char*());
|
|
strupr(m_text);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
MString::ToLower()
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(m_text);
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// If there is more that one reference to this string, split it off
|
|
//-----------------------------------------------------------------
|
|
//
|
|
if ((BYTE)m_text[-1] > 1)
|
|
operator=(operator char*());
|
|
strlwr(m_text);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
// Removes spaces and makes them _ characters
|
|
void
|
|
MString::RemoveSpaces()
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(m_text);
|
|
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// If there is more that one reference to this string, split it off
|
|
//-----------------------------------------------------------------
|
|
//
|
|
if ((BYTE)m_text[-1] > 1)
|
|
operator=(operator char*());
|
|
|
|
unsigned len = strlen(m_text);
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
if (m_text[i] == ' ')
|
|
m_text[i] = '_';
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MString&
|
|
MString::StripExtension()
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(m_text);
|
|
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// If there is more that one reference to this string, split it off
|
|
//-----------------------------------------------------------------
|
|
//
|
|
if ((BYTE)m_text[-1] > 1)
|
|
operator=(operator char*());
|
|
char *p = strrchr(m_text, '.');
|
|
if (p)
|
|
*p = '\0';
|
|
return *this;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MString&
|
|
MString::IsolateDirectory()
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(m_text);
|
|
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// If there is more that one reference to this string, split it off
|
|
//-----------------------------------------------------------------
|
|
//
|
|
if ((BYTE)m_text[-1] > 1)
|
|
operator=(operator char*());
|
|
char *p = __mbsrchr(m_text, '\\');
|
|
if (p)
|
|
*++p = '\0';
|
|
else
|
|
*m_text = '\0';
|
|
return *this;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MString&
|
|
MString::StripDirectory()
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(m_text);
|
|
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// If there is more that one reference to this string, split it off
|
|
//-----------------------------------------------------------------
|
|
//
|
|
if ((BYTE)m_text[-1] > 1)
|
|
operator=(operator char*());
|
|
char *p = __mbsrchr(m_text, '\\');
|
|
if (p)
|
|
{
|
|
char *q = m_text;
|
|
do
|
|
{
|
|
*q++ = *++p;
|
|
}
|
|
while (*p);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
MemoryStream&
|
|
MemoryStreamIO::Read(
|
|
MemoryStream *stream,
|
|
MString *str
|
|
)
|
|
{
|
|
Check_Object(stream);
|
|
Check_Object(str);
|
|
|
|
size_t string_length;
|
|
Read(stream, &string_length);
|
|
if (string_length > 0)
|
|
{
|
|
str->AllocateLength(string_length);
|
|
Verify(str->GetLength() == string_length);
|
|
stream->ReadBytes(str->m_text, string_length + 1);
|
|
}
|
|
Check_Object(str);
|
|
return *stream;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
MemoryStream&
|
|
MemoryStreamIO::Write(
|
|
MemoryStream *stream,
|
|
const MString *str
|
|
)
|
|
{
|
|
Check_Object(stream);
|
|
Check_Object(str);
|
|
|
|
unsigned len = 0;
|
|
if (str->m_text)
|
|
len = str->GetLength();
|
|
Write(stream, &len);
|
|
if (len > 0)
|
|
stream->WriteBytes(str->m_text, len + 1);
|
|
return *stream;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
unsigned
|
|
MString::ComputeHash(const char* ptr)
|
|
{
|
|
//
|
|
// Verify that the unsigned is 32 bits wide
|
|
// Hash value is first 16 bits of fileID and first 16 bits of recordID
|
|
//
|
|
Verify(sizeof(unsigned) == sizeof(DWORD));
|
|
|
|
unsigned ret = 0;
|
|
|
|
register i, r, len = strlen(ptr), int_len = len >> 2;
|
|
|
|
for(i=0;i<int_len;i++)
|
|
{
|
|
r = ((int *)ptr)[i];
|
|
_asm mov ecx, i
|
|
_asm ror r, cl
|
|
ret += r;
|
|
}
|
|
|
|
switch (len&3)
|
|
{
|
|
case 1:
|
|
case 2:
|
|
ret += ((WORD *)ptr)[i*2];
|
|
break;
|
|
case 3:
|
|
ret += ((int *)ptr)[i];
|
|
break;
|
|
}
|
|
|
|
return (ret & 0x7fffffff);
|
|
}
|