#include "pch.h" ////////////////////////////////////////////////////////////////////////////// // // ZString::ZStringData // ////////////////////////////////////////////////////////////////////////////// ZString::ZStringData::ZStringData(PCC pcc) { m_length = pcc ? strlen(pcc) : 0; m_pch = new char[m_length + 1]; m_pcc = m_pch; memcpy(m_pch, pcc ? pcc : "", m_length + 1); } ZString::ZStringData::ZStringData(PCC pcc, bool bStatic) { ZAssert(bStatic); m_length = strlen(pcc); m_pch = NULL; m_pcc = pcc; } ZString::ZStringData::ZStringData(PCC pcc, int length) { m_length = length; m_pch = new char[m_length + 1]; m_pcc = m_pch; memcpy(m_pch, pcc, m_length); m_pch[m_length] = 0; } ZString::ZStringData::ZStringData(char ch, int length) { m_length = length; m_pch = new char[m_length + 1]; m_pcc = m_pch; memset(m_pch, ch, m_length); m_pch[m_length] = 0; } ZString::ZStringData::ZStringData(const ZStringData* pdata1, const ZStringData* pdata2) : m_length(pdata1->GetLength() + pdata2->GetLength()) { m_pch = new char[m_length + 1]; m_pcc = m_pch; memcpy(m_pch, pdata1->m_pcc, pdata1->GetLength()); memcpy(m_pch + pdata1->m_length, pdata2->m_pcc, pdata2->GetLength() + 1); } ZString::ZStringData::~ZStringData() { if (m_pch) { delete[] m_pch; } } void ZString::ZStringData::Set(int index, char ch) { ZAssert( m_pch != NULL && index < m_length && GetCount() == 1 ); m_pch[index] = ch; } int ZString::ZStringData::Find(const ZStringData* pdata) const { for(int index = 0; index < m_length - pdata->m_length + 1; index++) { for (int index2 = 0; index2 < pdata->m_length; index2++) { if (m_pcc[index + index2] != pdata->m_pcc[index2]) { break; } } if (index2 == pdata->m_length) { return index; } } return -1; } int ZString::ZStringData::ReverseFind(const ZStringData* pdata) const { for(int index = m_length - pdata->m_length + 1; index >=0 ; index--) { for (int index2 = 0; index2 < pdata->m_length; index2++) { if (m_pcc[index + index2] != pdata->m_pcc[index2]) { break; } } if (index2 == pdata->m_length) { return index; } } return -1; } int ZString::ZStringData::Find(char ch, int index) const { for(; index < m_length; index++) { if (m_pcc[index] == ch) { return index; } } return -1; } int ZString::ZStringData::ReverseFind(char ch, int index) const { index = m_length - index; for(; index >= 0; index--) { if (m_pcc[index] == ch) { return index; } } return -1; } int ZString::ZStringData::FindAny(const ZStringData* pdata, int index) const { int length = pdata->GetLength(); for(; index < m_length; index++) { for (int index2 = 0; index2 < length; index2++) { if (m_pcc[index] == pdata->m_pcc[index2]) { return index; } } } return -1; } int ZString::ZStringData::ReverseFindAny(const ZStringData* pdata, int index) const { int length = pdata->GetLength(); index = m_length - index; for(; index >= 0; index--) { for (int index2 = 0; index2 < length; index2++) { if (m_pcc[index] == pdata->m_pcc[index2]) { return index; } } } return -1; } /* BSTR ZString::ZStringData::MakeBSTR() const { if (m_length != 0) { WCHAR* pszw = new WCHAR[m_length]; MultiByteToWideChar(CP_ACP, 0, m_pcc, -1, pszw, m_length); BSTR bstr = SysAllocStringLen(pszw, m_length); delete[] pszw; return bstr; } else { return SysAllocStringLen(L"", 0); } } */ ////////////////////////////////////////////////////////////////////////////// // // ZString Constructors // ////////////////////////////////////////////////////////////////////////////// TRef ZString::s_pemptyData = new ZString::ZStringData("", true); ZString::ZString() : m_pdata(s_pemptyData) { } ZString::ZString(PCC pcc) : m_pdata(new ZStringData(pcc)) { } ZString::ZString(PCC pcc, bool bStatic) : m_pdata(new ZStringData(pcc, bStatic)) { } ZString::ZString(PCC pcc, int length) { if (length == 0) { m_pdata = s_pemptyData; } else { m_pdata = new ZStringData(pcc, length); } } ZString::ZString(char ch, int length) { if (length == 0) { m_pdata = s_pemptyData; } else { m_pdata = new ZStringData(ch, length); } } ZString::ZString(PCC pcc, int length, bool bStatic) { if (length == 0) { m_pdata = s_pemptyData; } else { m_pdata = new ZStringData(pcc, length); } } ZString::ZString(const ZString& str) : m_pdata(str.m_pdata) { } ZString::ZString(ZStringData* pdata) : m_pdata(pdata) { } ZString::ZString(int value) { char buf[32]; _itoa(value,buf,10); m_pdata = new ZStringData(buf); } ZString::ZString(float value, int total, int precision) { char format[32]; char buf[32]; sprintf(format, "%%%d.%df", total, precision); sprintf(buf, format, value); m_pdata = new ZStringData(buf); } ZString::ZString(float value) { #ifndef DREAMCAST char buf[32]; sprintf(buf, "%g", value); m_pdata = new ZStringData(buf); #else int decimal, sign; char *buffer; buffer = _fcvt( value, 7, &decimal, &sign ); m_pdata = new ZStringData(buffer); #endif } ZString::ZString(bool b) { if (b) { m_pdata = new ZStringData("true"); } else { m_pdata = new ZStringData("false"); } } ZString operator+(const ZString& str1, const ZString& str2) { return ZString(new ZString::ZStringData(str1.m_pdata, str2.m_pdata)); } ZString ZString::GetProfileString(const ZString& strSection, const ZString& strKey) { char buf[256]; DWORD dw = ::GetProfileString(strSection, strKey, "", buf, 256); return ZString(buf, (int)dw); } ////////////////////////////////////////////////////////////////////////////// // // ZString Operations // ////////////////////////////////////////////////////////////////////////////// void ZString::UniqueData() { if (m_pdata->GetCount() != 1) { m_pdata = new ZStringData(m_pdata->GetPointer()); } } void ZString::SetEmpty() { m_pdata = s_pemptyData; } void ZString::Set(int index, char ch) { if (index < GetLength()) { if (m_pdata->GetPointer()[index] != ch) { UniqueData(); m_pdata->Set(index, ch); } } } ZString& ZString::operator+=(const ZString& str) { m_pdata = new ZStringData(m_pdata, str.m_pdata); return *this; } ZString& ZString::operator=(const ZString& str) { m_pdata = str.m_pdata; return *this; } void ZString::ReplaceAll(const ZString& str, char ch) { UniqueData(); int length = str.GetLength(); for(int index = 0; index < GetLength(); index++) { for (int index2 = 0; index2 < length; index2++) { if (m_pdata->GetPointer()[index] == str[index2]) { m_pdata->Set(index, ch); break; } } } } void ZString::RemoveAll(char chToRemove) { int length = GetLength(); char* cbNew = (char*)_alloca(length + 1); int nLengthNew = 0; for (int indexOld = 0; indexOld < GetLength(); indexOld++) { char chCurrent = m_pdata->GetPointer()[indexOld]; if (chCurrent != chToRemove) { cbNew[nLengthNew] = chCurrent; ++nLengthNew; } } cbNew[nLengthNew] = '\0'; m_pdata = new ZStringData(cbNew, nLengthNew); } ////////////////////////////////////////////////////////////////////////////// // // ZString Accessors // ////////////////////////////////////////////////////////////////////////////// bool operator==(const ZString& str1, const ZString& str2) { return str1.GetLength() == str2.GetLength() && (strncmp(str1, str2, str1.GetLength()) == 0); } bool operator==(const ZString& str, PCC pcc) { ZAssert(pcc != NULL); return str.GetLength() == (int)strlen(pcc) && (strncmp(str, pcc, str.GetLength()) == 0); } bool operator==(PCC pcc, const ZString& str) { ZAssert(pcc != NULL); return str.GetLength() == (int)strlen(pcc) && (strncmp(str, pcc, str.GetLength()) == 0); } bool operator!=(const ZString& str1, const ZString& str2) { return str1.GetLength() != str2.GetLength() || (strncmp(str1, str2, str1.GetLength()) != 0); } bool operator!=(const ZString& str, PCC pcc) { ZAssert(pcc != NULL); return str.GetLength() != (int)strlen(pcc) || (strncmp(str, pcc, str.GetLength()) != 0); } bool operator!=(PCC pcc, const ZString& str) { ZAssert(pcc != NULL); return str.GetLength() != (int)strlen(pcc) || (strncmp(str, pcc, str.GetLength()) != 0); } bool operator<(const ZString& str1, const ZString& str2) { return strcmp(str1, str2) < 0; } bool operator<(const ZString& str, PCC pcc) { return strcmp(str, pcc) < 0; } bool operator<(PCC pcc, const ZString& str) { return strcmp(pcc, str) < 0; } /* BSTR ZString::MakeBSTR() const { return m_pdata->MakeBSTR(); } */ ////////////////////////////////////////////////////////////////////////////// // // Find functions // ////////////////////////////////////////////////////////////////////////////// int ZString::Find(const ZString& str) const { return m_pdata->Find(str.m_pdata); } int ZString::ReverseFind(const ZString& str) const { return m_pdata->Find(str.m_pdata); } int ZString::Find(char ch, int index) const { return m_pdata->Find(ch, index); } int ZString::ReverseFind(char ch, int index) const { return m_pdata->ReverseFind(ch, index); } int ZString::FindAny(const ZString& str, int index) const { return m_pdata->FindAny(str.m_pdata, index); } int ZString::ReverseFindAny(const ZString& str, int index) const { return m_pdata->ReverseFindAny(str.m_pdata, index); } ////////////////////////////////////////////////////////////////////////////// // // Utility functions // ////////////////////////////////////////////////////////////////////////////// int ZString::GetInteger() const { return atoi(m_pdata->GetPointer()); } ZString ZString::Left(int index) const { return ZString(m_pdata->GetPointer(), index); } ZString ZString::Right(int index) const { return ZString(m_pdata->GetPointer() + GetLength() - index, index); } ZString ZString::Middle(int index, int length) const { return ZString(m_pdata->GetPointer() + index, length); } ZString ZString::LeftOf(int index) const { return Left(GetLength() - index); } ZString ZString::RightOf(int index) const { int size = GetLength() - index; if (size > 0) { return Right(size); } else { return ZString(); } } ZString ZString::LeftOf(const ZString& str) const { int index = FindAny(str); if (index == -1) { return str; } else { return Left(index); } } ZString ZString::RightOf(const ZString& str) const { int index = FindAny(str); if (index == -1) { return ZString(); } else { return Right(GetLength() - index - 1); } } ZString ZString::ToLower() const { char* cbResult = (char*)_alloca(GetLength() + 1); ZToLower(cbResult, (*this)); return cbResult; } ZString ZString::ToUpper() const { char* cbResult = (char*)_alloca(GetLength() + 1); ZToUpper(cbResult, (*this)); return cbResult; } void ZToLower(char* szDest, PCC szSource) { for (int index = 0; szSource[index] != '\0'; ++index) { char ch = szSource[index]; if (ch >= 'A' && ch <= 'Z') szDest[index] = (ch - ('A' - 'a')); else szDest[index] = ch; } szDest[index] = '\0'; } void ZToUpper(char* szDest, PCC szSource) { for (int index = 0; szSource[index] != '\0'; ++index) { char ch = szSource[index]; if (ch >= 'a' && ch <= 'z') szDest[index] = (ch - ('a' - 'A')); else szDest[index] = ch; } szDest[index] = '\0'; } ////////////////////////////////////////////////////////////////////////////// // // Command line // ////////////////////////////////////////////////////////////////////////////// ZString ZString::GetToken() { ZString strToken; int length = GetLength(); int index; if (m_pdata->GetPointer()[0] == '"') { index = 1; while (index < length && m_pdata->GetPointer()[index] != '"') index++; if (index < length) strToken = Middle(1, index++ - 1); else strToken = *this; } else { index = 0; while (index < length && m_pdata->GetPointer()[index] != ' ') index++; strToken = Left(index); } while (index < length && m_pdata->GetPointer()[index] == ' ') index++; *this = Right(length - index); return strToken; } ////////////////////////////////////////////////////////////////////////////// // // FilenameString // // foo.ext // ////////////////////////////////////////////////////////////////////////////// ZString FilenameString::GetExtension() const { return RightOf("."); } ZString FilenameString::GetName() const { int index = Find('.', 0); if (index == -1) { return *this; } else { return Left(index); } } ////////////////////////////////////////////////////////////////////////////// // // PathString // // foo // ./foo // ../foo // /foo // // d: // d:foo // d:/foo // //server/share // // , current code doesn't handle c:\ correctly // ////////////////////////////////////////////////////////////////////////////// #ifdef DREAMCAST const char* g_szDirSep = "\\"; #else const char* g_szDirSep = "/"; #endif PathString::PathString(PCC pcc) : ZString(pcc) { // : make sure str is valid #ifdef DREAMCAST ReplaceAll("/", '\\'); #else ReplaceAll("\\", '/'); #endif } PathString PathString::GetCurrentDirectory() { int size = ::GetCurrentDirectory(0, NULL); char* pch = new char[size]; ::GetCurrentDirectory(size, pch); PathString str(pch); delete pch; return str; } PathString PathString::GetModulePath() { char ch[128]; GetModuleFileNameA(NULL, ch, sizeof(ch) / sizeof(*ch)); return PathString(ch); } FilenameString PathString::GetFilename() const { int index = ReverseFindAny("/\\:"); if (index == -1) { return *this; } else { return Right(GetLength() - index - 1); } } ZString PathString::GetExtension() const { return GetFilename().GetExtension(); } ZString PathString::GetName() const { return GetFilename().GetName(); } PathString PathString::GetDirectory() const { int index = ReverseFindAny("/\\:"); if (index == -1) { return PathString(); } else { return Left(index); } } PathString PathString::GetDrive() const { char ch0 = (*this)[0]; char ch1 = (*this)[1]; if ( (ch0 == '/' && ch1 == '/') || (ch0 == '\\' && ch1 == '\\') ) { // network path return Left(FindAny("/\\", FindAny("/\\", 2) + 1) - 1); } else if (ch1 == ':') { // drive letter return Left(2); } return PathString(); } PathString PathString::operator+(const PathString& strRelativeArg) const { PathString strAbsolute = *this; ZString strRelative = strRelativeArg; int length = strRelative.GetLength(); char ch0 = strRelative[0]; char ch1 = length > 0 ? strRelative[1] : 0; char ch2 = length > 1 ? strRelative[2] : 0; if (ch0 == '/' || ch0 == '\\') { if (ch1 == ch0) { // absolute network path return strRelative; } else { // Just use the drive from strAbsolute; return ZString(strAbsolute.GetDrive()) + g_szDirSep + strRelative; } } else if (ch1 == ':') { // The relative path has a drive letter if (ch2 == '/' || ch2 == '\\') { return strRelative; } else { ZError("Current directory relative paths not supported."); return strAbsolute; } } else { // tack the relative path onto the end of the absolute path while (true) { ch0 = strRelative[0]; if (ch0 == '.') { int length = strRelative.GetLength(); if (strRelative[1] == '.') { strAbsolute = strAbsolute.GetDirectory(); strRelative = strRelative.Right(strRelative.GetLength() - 2); } else { strRelative = strRelative.Right(strRelative.GetLength() - 1); } } else { int index = strRelative.FindAny("/\\"); if (index == -1) { index = strRelative.GetLength(); } char chLast = strAbsolute[strAbsolute.GetLength() - 1]; if (chLast == '/' || chLast == '\\') { strAbsolute = ZString(strAbsolute) + strRelative.Left(index); } else { strAbsolute = ZString(strAbsolute) + g_szDirSep + strRelative.Left(index); } strRelative = strRelative.Right(strRelative.GetLength() - index); } ch0 = strRelative[0]; if (ch0 == '/' || ch0 == '\\') { strRelative = strRelative.Right(strRelative.GetLength() - 1); } else { return strAbsolute; } } } } ////////////////////////////////////////////////////////////////////////////// // // Encryption Stuff // ////////////////////////////////////////////////////////////////////////////// static const unsigned char vcScramble[256] = { 0, 26, 45, 66, 155, 83, 137, 133, 71, 158, 4, 128, 124, 106, 59, 32, 244, 2, 100, 193, 42, 25, 228, 76, 110, 116, 72, 163, 214, 97, 61, 11, 75, 225, 33, 10, 48, 60, 14, 8, 101, 67, 179, 7, 82, 69, 165, 152, 222, 6, 44, 23, 35, 246, 180, 120, 129, 248, 105, 55, 24, 173, 112, 234, 9, 171, 99, 27, 28, 54, 22, 135, 102, 51, 113, 18, 3, 29, 80, 191, 169, 107, 46, 73, 31, 218, 177, 34, 176, 186, 93, 36, 153, 147, 178, 160, 148, 43, 182, 84, 154, 141, 164, 77, 233, 136, 12, 103, 156, 50, 58, 223, 118, 209, 13, 119, 204, 188, 52, 41, 21, 189, 241, 151, 192, 172, 104, 57, 38, 131, 5, 91, 181, 64, 219, 39, 205, 130, 63, 94, 109, 81, 254, 255, 174, 220, 142, 161, 162, 132, 211, 49, 202, 249, 123, 114, 95, 78, 140, 74, 86, 115, 251, 15, 1, 65, 62, 231, 125, 194, 201, 40, 143, 30, 159, 96, 145, 245, 200, 56, 17, 199, 183, 16, 134, 229, 121, 87, 149, 235, 122, 92, 37, 166, 157, 215, 144, 213, 126, 89, 187, 53, 232, 212, 19, 20, 175, 210, 207, 168, 150, 203, 216, 197, 252, 68, 247, 70, 117, 138, 146, 224, 139, 190, 253, 90, 185, 238, 111, 196, 206, 167, 108, 85, 226, 221, 208, 243, 170, 195, 236, 240, 242, 79, 184, 237, 239, 47, 217, 250, 230, 98, 88, 198, 127, 227 }; static const unsigned char vcUnscramble[256] = { 0, 164, 17, 76, 10, 130, 49, 43, 39, 64, 35, 31, 106, 114, 38, 163, 183, 180, 75, 204, 205, 120, 70, 51, 60, 21, 1, 67, 68, 77, 173, 84, 15, 34, 87, 52, 91, 192, 128, 135, 171, 119, 20, 97, 50, 2, 82, 247, 36, 151, 109, 73, 118, 201, 69, 59, 179, 127, 110, 14, 37, 30, 166, 138, 133, 165, 3, 41, 215, 45, 217, 8, 26, 83, 159, 32, 23, 103, 157, 243, 78, 141, 44, 5, 99, 233, 160, 187, 252, 199, 225, 131, 191, 90, 139, 156, 175, 29, 251, 66, 18, 40, 72, 107, 126, 58, 13, 81, 232, 140, 24, 228, 62, 74, 155, 161, 25, 218, 112, 115, 55, 186, 190, 154, 12, 168, 198, 254, 11, 56, 137, 129, 149, 7, 184, 71, 105, 6, 219, 222, 158, 101, 146, 172, 196, 176, 220, 93, 96, 188, 210, 123, 47, 92, 100, 4, 108, 194, 9, 174, 95, 147, 148, 27, 102, 46, 193, 231, 209, 80, 238, 65, 125, 61, 144, 206, 88, 86, 94, 42, 54, 132, 98, 182, 244, 226, 89, 200, 117, 121, 223, 79, 124, 19, 169, 239, 229, 213, 253, 181, 178, 170, 152, 211, 116, 136, 230, 208, 236, 113, 207, 150, 203, 197, 28, 195, 212, 248, 85, 134, 145, 235, 48, 111, 221, 33, 234, 255, 22, 185, 250, 167, 202, 104, 63, 189, 240, 245, 227, 246, 241, 122, 242, 237, 16, 177, 53, 216, 57, 153, 249, 162, 214, 224, 142, 143 }; static unsigned char ScrambleMunge(unsigned char cbStart, unsigned char cbKey) { unsigned char c = cbStart; ZAssert(c != 0); ZAssert(cbKey != 0); // (note: beware XOR, since that could generate a NULL character which // would truncate the string). // do an add mod 255 + 1 //c = (unsigned char)((short(c) + short(cbKey) - 2) % 255 + 1); int n = (int(c) + int(cbKey)); c = (unsigned char)(n - ((n <= 256) ? 1 : 256)); // do a substitution c = vcScramble[c]; // do a rotation c = (c << (cbKey & 7)) | (c >> (8 - (cbKey & 7))); ZAssert(c != 0); return c; } static unsigned char ScrambleUnmunge(unsigned char cbStart, unsigned char cbKey) { unsigned char c = cbStart; ZAssert(c != 0); ZAssert(cbKey > 0); // (note: beware XOR, since that could generate a NULL character which // would truncate the string). // undo the rotation c = (c >> (cbKey & 7)) | (c << (8 - (cbKey & 7))); // undo the substitution c = vcUnscramble[c]; // undo the add mod 255 + 1 //c = (unsigned char)((short(c) - short(cbKey) + 255) % 255 + 1); int n = (int(c) - int(cbKey)); c = (unsigned char)(n + ((n >= 0) ? 1 : 256)); ZAssert(c != 0); return c; } const int c_cScrambleRounds = 12; void ZScramble(char* szDest, PCC szSource, PCC szKey) { int length = strlen(szSource); int lengthKey = strlen(szKey); memcpy(szDest, szSource, length + 1); for (int nRound = 0; nRound < c_cScrambleRounds; nRound++) { int index; // do a pass to unscramble it by the key for (index = 0; index < length; index++) szDest[index] = (char)(ScrambleMunge((unsigned char)szDest[index], (unsigned char)szKey[(index + 3*nRound) % lengthKey])); // cypher block chaining forwards for (index = 1; index < length; index++) szDest[index] = (char)(ScrambleMunge((unsigned char)szDest[index], (unsigned char)szDest[index-1])); // cypher block chaining backwards for (index = length - 2; index >= 0; index--) szDest[index] = (char)(ScrambleMunge((unsigned char)szDest[index], (unsigned char)szDest[index+1])); } } void ZUnscramble(char* szDest, PCC szSource, PCC szKey) { int length = strlen(szSource); int lengthKey = strlen(szKey); memcpy(szDest, szSource, length + 1); for (int nRound = c_cScrambleRounds - 1; nRound >= 0; nRound--) { int index; // undo the cypher block chaining backwards for (index = 0; index < length - 1; index++) szDest[index] = (char)(ScrambleUnmunge((unsigned char)szDest[index], (unsigned char)szDest[index+1])); // undo the cypher block chaining forwards for (index = length - 1; index > 0; index--) szDest[index] = (char)(ScrambleUnmunge((unsigned char)szDest[index], (unsigned char)szDest[index-1])); // do a pass to unscramble it by the key for (index = 0; index < length; index++) szDest[index] = (char)(ScrambleUnmunge((unsigned char)szDest[index], (unsigned char)szKey[(index + 3*nRound) % lengthKey])); } } ZString ZString::Scramble(const ZString& strKey) const { char* cbResult = (char*)_alloca(GetLength() + 1); ZScramble(cbResult, (*this), strKey); return cbResult; } ZString ZString::Unscramble(const ZString& strKey) const { char* cbResult = (char*)_alloca(GetLength() + 1); ZUnscramble(cbResult, (*this), strKey); return cbResult; }