zstring.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. #include "pch.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // ZString::ZStringData
  5. //
  6. //////////////////////////////////////////////////////////////////////////////
  7. ZString::ZStringData::ZStringData(PCC pcc)
  8. {
  9. m_length = pcc ? strlen(pcc) : 0;
  10. m_pch = new char[m_length + 1];
  11. m_pcc = m_pch;
  12. memcpy(m_pch, pcc ? pcc : "", m_length + 1);
  13. }
  14. ZString::ZStringData::ZStringData(PCC pcc, bool bStatic)
  15. {
  16. ZAssert(bStatic);
  17. m_length = strlen(pcc);
  18. m_pch = NULL;
  19. m_pcc = pcc;
  20. }
  21. ZString::ZStringData::ZStringData(PCC pcc, int length)
  22. {
  23. m_length = length;
  24. m_pch = new char[m_length + 1];
  25. m_pcc = m_pch;
  26. memcpy(m_pch, pcc, m_length);
  27. m_pch[m_length] = 0;
  28. }
  29. ZString::ZStringData::ZStringData(char ch, int length)
  30. {
  31. m_length = length;
  32. m_pch = new char[m_length + 1];
  33. m_pcc = m_pch;
  34. memset(m_pch, ch, m_length);
  35. m_pch[m_length] = 0;
  36. }
  37. ZString::ZStringData::ZStringData(const ZStringData* pdata1, const ZStringData* pdata2) :
  38. m_length(pdata1->GetLength() + pdata2->GetLength())
  39. {
  40. m_pch = new char[m_length + 1];
  41. m_pcc = m_pch;
  42. memcpy(m_pch, pdata1->m_pcc, pdata1->GetLength());
  43. memcpy(m_pch + pdata1->m_length, pdata2->m_pcc, pdata2->GetLength() + 1);
  44. }
  45. ZString::ZStringData::~ZStringData()
  46. {
  47. if (m_pch) {
  48. delete[] m_pch;
  49. }
  50. }
  51. void ZString::ZStringData::Set(int index, char ch)
  52. {
  53. ZAssert(
  54. m_pch != NULL
  55. && index < m_length
  56. && GetCount() == 1
  57. );
  58. m_pch[index] = ch;
  59. }
  60. int ZString::ZStringData::Find(const ZStringData* pdata) const
  61. {
  62. for(int index = 0; index < m_length - pdata->m_length + 1; index++) {
  63. for (int index2 = 0; index2 < pdata->m_length; index2++) {
  64. if (m_pcc[index + index2] != pdata->m_pcc[index2]) {
  65. break;
  66. }
  67. }
  68. if (index2 == pdata->m_length) {
  69. return index;
  70. }
  71. }
  72. return -1;
  73. }
  74. int ZString::ZStringData::ReverseFind(const ZStringData* pdata) const
  75. {
  76. for(int index = m_length - pdata->m_length + 1; index >=0 ; index--) {
  77. for (int index2 = 0; index2 < pdata->m_length; index2++) {
  78. if (m_pcc[index + index2] != pdata->m_pcc[index2]) {
  79. break;
  80. }
  81. }
  82. if (index2 == pdata->m_length) {
  83. return index;
  84. }
  85. }
  86. return -1;
  87. }
  88. int ZString::ZStringData::Find(char ch, int index) const
  89. {
  90. for(; index < m_length; index++) {
  91. if (m_pcc[index] == ch) {
  92. return index;
  93. }
  94. }
  95. return -1;
  96. }
  97. int ZString::ZStringData::ReverseFind(char ch, int index) const
  98. {
  99. index = m_length - index;
  100. for(; index >= 0; index--) {
  101. if (m_pcc[index] == ch) {
  102. return index;
  103. }
  104. }
  105. return -1;
  106. }
  107. int ZString::ZStringData::FindAny(const ZStringData* pdata, int index) const
  108. {
  109. int length = pdata->GetLength();
  110. for(; index < m_length; index++) {
  111. for (int index2 = 0; index2 < length; index2++) {
  112. if (m_pcc[index] == pdata->m_pcc[index2]) {
  113. return index;
  114. }
  115. }
  116. }
  117. return -1;
  118. }
  119. int ZString::ZStringData::ReverseFindAny(const ZStringData* pdata, int index) const
  120. {
  121. int length = pdata->GetLength();
  122. index = m_length - index;
  123. for(; index >= 0; index--) {
  124. for (int index2 = 0; index2 < length; index2++) {
  125. if (m_pcc[index] == pdata->m_pcc[index2]) {
  126. return index;
  127. }
  128. }
  129. }
  130. return -1;
  131. }
  132. /*
  133. BSTR ZString::ZStringData::MakeBSTR() const
  134. {
  135. if (m_length != 0) {
  136. WCHAR* pszw = new WCHAR[m_length];
  137. MultiByteToWideChar(CP_ACP, 0, m_pcc, -1, pszw, m_length);
  138. BSTR bstr = SysAllocStringLen(pszw, m_length);
  139. delete[] pszw;
  140. return bstr;
  141. } else {
  142. return SysAllocStringLen(L"", 0);
  143. }
  144. }
  145. */
  146. //////////////////////////////////////////////////////////////////////////////
  147. //
  148. // ZString Constructors
  149. //
  150. //////////////////////////////////////////////////////////////////////////////
  151. TRef<ZString::ZStringData> ZString::s_pemptyData = new ZString::ZStringData("", true);
  152. ZString::ZString() :
  153. m_pdata(s_pemptyData)
  154. {
  155. }
  156. ZString::ZString(PCC pcc) :
  157. m_pdata(new ZStringData(pcc))
  158. {
  159. }
  160. ZString::ZString(PCC pcc, bool bStatic) :
  161. m_pdata(new ZStringData(pcc, bStatic))
  162. {
  163. }
  164. ZString::ZString(PCC pcc, int length)
  165. {
  166. if (length == 0) {
  167. m_pdata = s_pemptyData;
  168. } else {
  169. m_pdata = new ZStringData(pcc, length);
  170. }
  171. }
  172. ZString::ZString(char ch, int length)
  173. {
  174. if (length == 0) {
  175. m_pdata = s_pemptyData;
  176. } else {
  177. m_pdata = new ZStringData(ch, length);
  178. }
  179. }
  180. ZString::ZString(PCC pcc, int length, bool bStatic)
  181. {
  182. if (length == 0) {
  183. m_pdata = s_pemptyData;
  184. } else {
  185. m_pdata = new ZStringData(pcc, length);
  186. }
  187. }
  188. ZString::ZString(const ZString& str) :
  189. m_pdata(str.m_pdata)
  190. {
  191. }
  192. ZString::ZString(ZStringData* pdata) :
  193. m_pdata(pdata)
  194. {
  195. }
  196. ZString::ZString(int value)
  197. {
  198. char buf[32];
  199. _itoa(value,buf,10);
  200. m_pdata = new ZStringData(buf);
  201. }
  202. ZString::ZString(float value, int total, int precision)
  203. {
  204. char format[32];
  205. char buf[32];
  206. sprintf(format, "%%%d.%df", total, precision);
  207. sprintf(buf, format, value);
  208. m_pdata = new ZStringData(buf);
  209. }
  210. ZString::ZString(float value)
  211. {
  212. #ifndef DREAMCAST
  213. char buf[32];
  214. sprintf(buf, "%g", value);
  215. m_pdata = new ZStringData(buf);
  216. #else
  217. int decimal, sign;
  218. char *buffer;
  219. buffer = _fcvt( value, 7, &decimal, &sign );
  220. m_pdata = new ZStringData(buffer);
  221. #endif
  222. }
  223. ZString::ZString(bool b)
  224. {
  225. if (b) {
  226. m_pdata = new ZStringData("true");
  227. } else {
  228. m_pdata = new ZStringData("false");
  229. }
  230. }
  231. ZString operator+(const ZString& str1, const ZString& str2)
  232. {
  233. return ZString(new ZString::ZStringData(str1.m_pdata, str2.m_pdata));
  234. }
  235. ZString ZString::GetProfileString(const ZString& strSection, const ZString& strKey)
  236. {
  237. char buf[256];
  238. DWORD dw = ::GetProfileString(strSection, strKey, "", buf, 256);
  239. return ZString(buf, (int)dw);
  240. }
  241. //////////////////////////////////////////////////////////////////////////////
  242. //
  243. // ZString Operations
  244. //
  245. //////////////////////////////////////////////////////////////////////////////
  246. void ZString::UniqueData()
  247. {
  248. if (m_pdata->GetCount() != 1) {
  249. m_pdata = new ZStringData(m_pdata->GetPointer());
  250. }
  251. }
  252. void ZString::SetEmpty()
  253. {
  254. m_pdata = s_pemptyData;
  255. }
  256. void ZString::Set(int index, char ch)
  257. {
  258. if (index < GetLength()) {
  259. if (m_pdata->GetPointer()[index] != ch) {
  260. UniqueData();
  261. m_pdata->Set(index, ch);
  262. }
  263. }
  264. }
  265. ZString& ZString::operator+=(const ZString& str)
  266. {
  267. m_pdata = new ZStringData(m_pdata, str.m_pdata);
  268. return *this;
  269. }
  270. ZString& ZString::operator=(const ZString& str)
  271. {
  272. m_pdata = str.m_pdata;
  273. return *this;
  274. }
  275. void ZString::ReplaceAll(const ZString& str, char ch)
  276. {
  277. UniqueData();
  278. int length = str.GetLength();
  279. for(int index = 0; index < GetLength(); index++) {
  280. for (int index2 = 0; index2 < length; index2++) {
  281. if (m_pdata->GetPointer()[index] == str[index2]) {
  282. m_pdata->Set(index, ch);
  283. break;
  284. }
  285. }
  286. }
  287. }
  288. void ZString::RemoveAll(char chToRemove)
  289. {
  290. int length = GetLength();
  291. char* cbNew = (char*)_alloca(length + 1);
  292. int nLengthNew = 0;
  293. for (int indexOld = 0; indexOld < GetLength(); indexOld++) {
  294. char chCurrent = m_pdata->GetPointer()[indexOld];
  295. if (chCurrent != chToRemove) {
  296. cbNew[nLengthNew] = chCurrent;
  297. ++nLengthNew;
  298. }
  299. }
  300. cbNew[nLengthNew] = '\0';
  301. m_pdata = new ZStringData(cbNew, nLengthNew);
  302. }
  303. //////////////////////////////////////////////////////////////////////////////
  304. //
  305. // ZString Accessors
  306. //
  307. //////////////////////////////////////////////////////////////////////////////
  308. bool operator==(const ZString& str1, const ZString& str2)
  309. {
  310. return
  311. str1.GetLength() == str2.GetLength()
  312. && (strncmp(str1, str2, str1.GetLength()) == 0);
  313. }
  314. bool operator==(const ZString& str, PCC pcc)
  315. {
  316. ZAssert(pcc != NULL);
  317. return
  318. str.GetLength() == (int)strlen(pcc)
  319. && (strncmp(str, pcc, str.GetLength()) == 0);
  320. }
  321. bool operator==(PCC pcc, const ZString& str)
  322. {
  323. ZAssert(pcc != NULL);
  324. return
  325. str.GetLength() == (int)strlen(pcc)
  326. && (strncmp(str, pcc, str.GetLength()) == 0);
  327. }
  328. bool operator!=(const ZString& str1, const ZString& str2)
  329. {
  330. return
  331. str1.GetLength() != str2.GetLength()
  332. || (strncmp(str1, str2, str1.GetLength()) != 0);
  333. }
  334. bool operator!=(const ZString& str, PCC pcc)
  335. {
  336. ZAssert(pcc != NULL);
  337. return
  338. str.GetLength() != (int)strlen(pcc)
  339. || (strncmp(str, pcc, str.GetLength()) != 0);
  340. }
  341. bool operator!=(PCC pcc, const ZString& str)
  342. {
  343. ZAssert(pcc != NULL);
  344. return
  345. str.GetLength() != (int)strlen(pcc)
  346. || (strncmp(str, pcc, str.GetLength()) != 0);
  347. }
  348. bool operator<(const ZString& str1, const ZString& str2)
  349. {
  350. return strcmp(str1, str2) < 0;
  351. }
  352. bool operator<(const ZString& str, PCC pcc)
  353. {
  354. return strcmp(str, pcc) < 0;
  355. }
  356. bool operator<(PCC pcc, const ZString& str)
  357. {
  358. return strcmp(pcc, str) < 0;
  359. }
  360. /*
  361. BSTR ZString::MakeBSTR() const
  362. {
  363. return m_pdata->MakeBSTR();
  364. }
  365. */
  366. //////////////////////////////////////////////////////////////////////////////
  367. //
  368. // Find functions
  369. //
  370. //////////////////////////////////////////////////////////////////////////////
  371. int ZString::Find(const ZString& str) const
  372. {
  373. return m_pdata->Find(str.m_pdata);
  374. }
  375. int ZString::ReverseFind(const ZString& str) const
  376. {
  377. return m_pdata->Find(str.m_pdata);
  378. }
  379. int ZString::Find(char ch, int index) const
  380. {
  381. return m_pdata->Find(ch, index);
  382. }
  383. int ZString::ReverseFind(char ch, int index) const
  384. {
  385. return m_pdata->ReverseFind(ch, index);
  386. }
  387. int ZString::FindAny(const ZString& str, int index) const
  388. {
  389. return m_pdata->FindAny(str.m_pdata, index);
  390. }
  391. int ZString::ReverseFindAny(const ZString& str, int index) const
  392. {
  393. return m_pdata->ReverseFindAny(str.m_pdata, index);
  394. }
  395. //////////////////////////////////////////////////////////////////////////////
  396. //
  397. // Utility functions
  398. //
  399. //////////////////////////////////////////////////////////////////////////////
  400. int ZString::GetInteger() const
  401. {
  402. return atoi(m_pdata->GetPointer());
  403. }
  404. ZString ZString::Left(int index) const
  405. {
  406. return ZString(m_pdata->GetPointer(), index);
  407. }
  408. ZString ZString::Right(int index) const
  409. {
  410. return ZString(m_pdata->GetPointer() + GetLength() - index, index);
  411. }
  412. ZString ZString::Middle(int index, int length) const
  413. {
  414. return ZString(m_pdata->GetPointer() + index, length);
  415. }
  416. ZString ZString::LeftOf(int index) const
  417. {
  418. return Left(GetLength() - index);
  419. }
  420. ZString ZString::RightOf(int index) const
  421. {
  422. int size = GetLength() - index;
  423. if (size > 0) {
  424. return Right(size);
  425. } else {
  426. return ZString();
  427. }
  428. }
  429. ZString ZString::LeftOf(const ZString& str) const
  430. {
  431. int index = FindAny(str);
  432. if (index == -1) {
  433. return str;
  434. } else {
  435. return Left(index);
  436. }
  437. }
  438. ZString ZString::RightOf(const ZString& str) const
  439. {
  440. int index = FindAny(str);
  441. if (index == -1) {
  442. return ZString();
  443. } else {
  444. return Right(GetLength() - index - 1);
  445. }
  446. }
  447. ZString ZString::ToLower() const
  448. {
  449. char* cbResult = (char*)_alloca(GetLength() + 1);
  450. ZToLower(cbResult, (*this));
  451. return cbResult;
  452. }
  453. ZString ZString::ToUpper() const
  454. {
  455. char* cbResult = (char*)_alloca(GetLength() + 1);
  456. ZToUpper(cbResult, (*this));
  457. return cbResult;
  458. }
  459. void ZToLower(char* szDest, PCC szSource)
  460. {
  461. for (int index = 0; szSource[index] != '\0'; ++index) {
  462. char ch = szSource[index];
  463. if (ch >= 'A' && ch <= 'Z')
  464. szDest[index] = (ch - ('A' - 'a'));
  465. else
  466. szDest[index] = ch;
  467. }
  468. szDest[index] = '\0';
  469. }
  470. void ZToUpper(char* szDest, PCC szSource)
  471. {
  472. for (int index = 0; szSource[index] != '\0'; ++index) {
  473. char ch = szSource[index];
  474. if (ch >= 'a' && ch <= 'z')
  475. szDest[index] = (ch - ('a' - 'A'));
  476. else
  477. szDest[index] = ch;
  478. }
  479. szDest[index] = '\0';
  480. }
  481. //////////////////////////////////////////////////////////////////////////////
  482. //
  483. // Command line
  484. //
  485. //////////////////////////////////////////////////////////////////////////////
  486. ZString ZString::GetToken()
  487. {
  488. ZString strToken;
  489. int length = GetLength();
  490. int index;
  491. if (m_pdata->GetPointer()[0] == '"')
  492. {
  493. index = 1;
  494. while (index < length && m_pdata->GetPointer()[index] != '"')
  495. index++;
  496. if (index < length)
  497. strToken = Middle(1, index++ - 1);
  498. else
  499. strToken = *this;
  500. }
  501. else
  502. {
  503. index = 0;
  504. while (index < length && m_pdata->GetPointer()[index] != ' ')
  505. index++;
  506. strToken = Left(index);
  507. }
  508. while (index < length && m_pdata->GetPointer()[index] == ' ')
  509. index++;
  510. *this = Right(length - index);
  511. return strToken;
  512. }
  513. //////////////////////////////////////////////////////////////////////////////
  514. //
  515. // FilenameString
  516. //
  517. // foo.ext
  518. //
  519. //////////////////////////////////////////////////////////////////////////////
  520. ZString FilenameString::GetExtension() const
  521. {
  522. return RightOf(".");
  523. }
  524. ZString FilenameString::GetName() const
  525. {
  526. int index = Find('.', 0);
  527. if (index == -1) {
  528. return *this;
  529. } else {
  530. return Left(index);
  531. }
  532. }
  533. //////////////////////////////////////////////////////////////////////////////
  534. //
  535. // PathString
  536. //
  537. // foo
  538. // ./foo
  539. // ../foo
  540. // /foo
  541. //
  542. // d:
  543. // d:foo
  544. // d:/foo
  545. // //server/share
  546. //
  547. // , current code doesn't handle c:\ correctly
  548. //
  549. //////////////////////////////////////////////////////////////////////////////
  550. #ifdef DREAMCAST
  551. const char* g_szDirSep = "\\";
  552. #else
  553. const char* g_szDirSep = "/";
  554. #endif
  555. PathString::PathString(PCC pcc) :
  556. ZString(pcc)
  557. {
  558. // : make sure str is valid
  559. #ifdef DREAMCAST
  560. ReplaceAll("/", '\\');
  561. #else
  562. ReplaceAll("\\", '/');
  563. #endif
  564. }
  565. PathString PathString::GetCurrentDirectory()
  566. {
  567. int size = ::GetCurrentDirectory(0, NULL);
  568. char* pch = new char[size];
  569. ::GetCurrentDirectory(size, pch);
  570. PathString str(pch);
  571. delete pch;
  572. return str;
  573. }
  574. PathString PathString::GetModulePath()
  575. {
  576. char ch[128];
  577. GetModuleFileNameA(NULL, ch, sizeof(ch) / sizeof(*ch));
  578. return PathString(ch);
  579. }
  580. FilenameString PathString::GetFilename() const
  581. {
  582. int index = ReverseFindAny("/\\:");
  583. if (index == -1) {
  584. return *this;
  585. } else {
  586. return Right(GetLength() - index - 1);
  587. }
  588. }
  589. ZString PathString::GetExtension() const
  590. {
  591. return GetFilename().GetExtension();
  592. }
  593. ZString PathString::GetName() const
  594. {
  595. return GetFilename().GetName();
  596. }
  597. PathString PathString::GetDirectory() const
  598. {
  599. int index = ReverseFindAny("/\\:");
  600. if (index == -1) {
  601. return PathString();
  602. } else {
  603. return Left(index);
  604. }
  605. }
  606. PathString PathString::GetDrive() const
  607. {
  608. char ch0 = (*this)[0];
  609. char ch1 = (*this)[1];
  610. if ( (ch0 == '/' && ch1 == '/')
  611. || (ch0 == '\\' && ch1 == '\\')
  612. ) {
  613. // network path
  614. return Left(FindAny("/\\", FindAny("/\\", 2) + 1) - 1);
  615. } else if (ch1 == ':') {
  616. // drive letter
  617. return Left(2);
  618. }
  619. return PathString();
  620. }
  621. PathString PathString::operator+(const PathString& strRelativeArg) const
  622. {
  623. PathString strAbsolute = *this;
  624. ZString strRelative = strRelativeArg;
  625. int length = strRelative.GetLength();
  626. char ch0 = strRelative[0];
  627. char ch1 = length > 0 ? strRelative[1] : 0;
  628. char ch2 = length > 1 ? strRelative[2] : 0;
  629. if (ch0 == '/' || ch0 == '\\') {
  630. if (ch1 == ch0) {
  631. // absolute network path
  632. return strRelative;
  633. } else {
  634. // Just use the drive from strAbsolute;
  635. return ZString(strAbsolute.GetDrive()) + g_szDirSep + strRelative;
  636. }
  637. } else if (ch1 == ':') {
  638. // The relative path has a drive letter
  639. if (ch2 == '/' || ch2 == '\\') {
  640. return strRelative;
  641. } else {
  642. ZError("Current directory relative paths not supported.");
  643. return strAbsolute;
  644. }
  645. } else {
  646. // tack the relative path onto the end of the absolute path
  647. while (true) {
  648. ch0 = strRelative[0];
  649. if (ch0 == '.') {
  650. int length = strRelative.GetLength();
  651. if (strRelative[1] == '.') {
  652. strAbsolute = strAbsolute.GetDirectory();
  653. strRelative = strRelative.Right(strRelative.GetLength() - 2);
  654. } else {
  655. strRelative = strRelative.Right(strRelative.GetLength() - 1);
  656. }
  657. } else {
  658. int index = strRelative.FindAny("/\\");
  659. if (index == -1) {
  660. index = strRelative.GetLength();
  661. }
  662. char chLast = strAbsolute[strAbsolute.GetLength() - 1];
  663. if (chLast == '/' || chLast == '\\') {
  664. strAbsolute = ZString(strAbsolute) + strRelative.Left(index);
  665. } else {
  666. strAbsolute = ZString(strAbsolute) + g_szDirSep + strRelative.Left(index);
  667. }
  668. strRelative = strRelative.Right(strRelative.GetLength() - index);
  669. }
  670. ch0 = strRelative[0];
  671. if (ch0 == '/' || ch0 == '\\') {
  672. strRelative = strRelative.Right(strRelative.GetLength() - 1);
  673. } else {
  674. return strAbsolute;
  675. }
  676. }
  677. }
  678. }
  679. //////////////////////////////////////////////////////////////////////////////
  680. //
  681. // Encryption Stuff
  682. //
  683. //////////////////////////////////////////////////////////////////////////////
  684. static const unsigned char vcScramble[256] =
  685. {
  686. 0, 26, 45, 66, 155, 83, 137, 133,
  687. 71, 158, 4, 128, 124, 106, 59, 32,
  688. 244, 2, 100, 193, 42, 25, 228, 76,
  689. 110, 116, 72, 163, 214, 97, 61, 11,
  690. 75, 225, 33, 10, 48, 60, 14, 8,
  691. 101, 67, 179, 7, 82, 69, 165, 152,
  692. 222, 6, 44, 23, 35, 246, 180, 120,
  693. 129, 248, 105, 55, 24, 173, 112, 234,
  694. 9, 171, 99, 27, 28, 54, 22, 135,
  695. 102, 51, 113, 18, 3, 29, 80, 191,
  696. 169, 107, 46, 73, 31, 218, 177, 34,
  697. 176, 186, 93, 36, 153, 147, 178, 160,
  698. 148, 43, 182, 84, 154, 141, 164, 77,
  699. 233, 136, 12, 103, 156, 50, 58, 223,
  700. 118, 209, 13, 119, 204, 188, 52, 41,
  701. 21, 189, 241, 151, 192, 172, 104, 57,
  702. 38, 131, 5, 91, 181, 64, 219, 39,
  703. 205, 130, 63, 94, 109, 81, 254, 255,
  704. 174, 220, 142, 161, 162, 132, 211, 49,
  705. 202, 249, 123, 114, 95, 78, 140, 74,
  706. 86, 115, 251, 15, 1, 65, 62, 231,
  707. 125, 194, 201, 40, 143, 30, 159, 96,
  708. 145, 245, 200, 56, 17, 199, 183, 16,
  709. 134, 229, 121, 87, 149, 235, 122, 92,
  710. 37, 166, 157, 215, 144, 213, 126, 89,
  711. 187, 53, 232, 212, 19, 20, 175, 210,
  712. 207, 168, 150, 203, 216, 197, 252, 68,
  713. 247, 70, 117, 138, 146, 224, 139, 190,
  714. 253, 90, 185, 238, 111, 196, 206, 167,
  715. 108, 85, 226, 221, 208, 243, 170, 195,
  716. 236, 240, 242, 79, 184, 237, 239, 47,
  717. 217, 250, 230, 98, 88, 198, 127, 227
  718. };
  719. static const unsigned char vcUnscramble[256] =
  720. {
  721. 0, 164, 17, 76, 10, 130, 49, 43,
  722. 39, 64, 35, 31, 106, 114, 38, 163,
  723. 183, 180, 75, 204, 205, 120, 70, 51,
  724. 60, 21, 1, 67, 68, 77, 173, 84,
  725. 15, 34, 87, 52, 91, 192, 128, 135,
  726. 171, 119, 20, 97, 50, 2, 82, 247,
  727. 36, 151, 109, 73, 118, 201, 69, 59,
  728. 179, 127, 110, 14, 37, 30, 166, 138,
  729. 133, 165, 3, 41, 215, 45, 217, 8,
  730. 26, 83, 159, 32, 23, 103, 157, 243,
  731. 78, 141, 44, 5, 99, 233, 160, 187,
  732. 252, 199, 225, 131, 191, 90, 139, 156,
  733. 175, 29, 251, 66, 18, 40, 72, 107,
  734. 126, 58, 13, 81, 232, 140, 24, 228,
  735. 62, 74, 155, 161, 25, 218, 112, 115,
  736. 55, 186, 190, 154, 12, 168, 198, 254,
  737. 11, 56, 137, 129, 149, 7, 184, 71,
  738. 105, 6, 219, 222, 158, 101, 146, 172,
  739. 196, 176, 220, 93, 96, 188, 210, 123,
  740. 47, 92, 100, 4, 108, 194, 9, 174,
  741. 95, 147, 148, 27, 102, 46, 193, 231,
  742. 209, 80, 238, 65, 125, 61, 144, 206,
  743. 88, 86, 94, 42, 54, 132, 98, 182,
  744. 244, 226, 89, 200, 117, 121, 223, 79,
  745. 124, 19, 169, 239, 229, 213, 253, 181,
  746. 178, 170, 152, 211, 116, 136, 230, 208,
  747. 236, 113, 207, 150, 203, 197, 28, 195,
  748. 212, 248, 85, 134, 145, 235, 48, 111,
  749. 221, 33, 234, 255, 22, 185, 250, 167,
  750. 202, 104, 63, 189, 240, 245, 227, 246,
  751. 241, 122, 242, 237, 16, 177, 53, 216,
  752. 57, 153, 249, 162, 214, 224, 142, 143
  753. };
  754. static unsigned char ScrambleMunge(unsigned char cbStart, unsigned char cbKey)
  755. {
  756. unsigned char c = cbStart;
  757. ZAssert(c != 0);
  758. ZAssert(cbKey != 0);
  759. // (note: beware XOR, since that could generate a NULL character which
  760. // would truncate the string).
  761. // do an add mod 255 + 1
  762. //c = (unsigned char)((short(c) + short(cbKey) - 2) % 255 + 1);
  763. int n = (int(c) + int(cbKey));
  764. c = (unsigned char)(n - ((n <= 256) ? 1 : 256));
  765. // do a substitution
  766. c = vcScramble[c];
  767. // do a rotation
  768. c = (c << (cbKey & 7)) | (c >> (8 - (cbKey & 7)));
  769. ZAssert(c != 0);
  770. return c;
  771. }
  772. static unsigned char ScrambleUnmunge(unsigned char cbStart, unsigned char cbKey)
  773. {
  774. unsigned char c = cbStart;
  775. ZAssert(c != 0);
  776. ZAssert(cbKey > 0);
  777. // (note: beware XOR, since that could generate a NULL character which
  778. // would truncate the string).
  779. // undo the rotation
  780. c = (c >> (cbKey & 7)) | (c << (8 - (cbKey & 7)));
  781. // undo the substitution
  782. c = vcUnscramble[c];
  783. // undo the add mod 255 + 1
  784. //c = (unsigned char)((short(c) - short(cbKey) + 255) % 255 + 1);
  785. int n = (int(c) - int(cbKey));
  786. c = (unsigned char)(n + ((n >= 0) ? 1 : 256));
  787. ZAssert(c != 0);
  788. return c;
  789. }
  790. const int c_cScrambleRounds = 12;
  791. void ZScramble(char* szDest, PCC szSource, PCC szKey)
  792. {
  793. int length = strlen(szSource);
  794. int lengthKey = strlen(szKey);
  795. memcpy(szDest, szSource, length + 1);
  796. for (int nRound = 0; nRound < c_cScrambleRounds; nRound++)
  797. {
  798. int index;
  799. // do a pass to unscramble it by the key
  800. for (index = 0; index < length; index++)
  801. szDest[index] = (char)(ScrambleMunge((unsigned char)szDest[index],
  802. (unsigned char)szKey[(index + 3*nRound) % lengthKey]));
  803. // cypher block chaining forwards
  804. for (index = 1; index < length; index++)
  805. szDest[index] = (char)(ScrambleMunge((unsigned char)szDest[index],
  806. (unsigned char)szDest[index-1]));
  807. // cypher block chaining backwards
  808. for (index = length - 2; index >= 0; index--)
  809. szDest[index] = (char)(ScrambleMunge((unsigned char)szDest[index],
  810. (unsigned char)szDest[index+1]));
  811. }
  812. }
  813. void ZUnscramble(char* szDest, PCC szSource, PCC szKey)
  814. {
  815. int length = strlen(szSource);
  816. int lengthKey = strlen(szKey);
  817. memcpy(szDest, szSource, length + 1);
  818. for (int nRound = c_cScrambleRounds - 1; nRound >= 0; nRound--)
  819. {
  820. int index;
  821. // undo the cypher block chaining backwards
  822. for (index = 0; index < length - 1; index++)
  823. szDest[index] = (char)(ScrambleUnmunge((unsigned char)szDest[index],
  824. (unsigned char)szDest[index+1]));
  825. // undo the cypher block chaining forwards
  826. for (index = length - 1; index > 0; index--)
  827. szDest[index] = (char)(ScrambleUnmunge((unsigned char)szDest[index],
  828. (unsigned char)szDest[index-1]));
  829. // do a pass to unscramble it by the key
  830. for (index = 0; index < length; index++)
  831. szDest[index] = (char)(ScrambleUnmunge((unsigned char)szDest[index],
  832. (unsigned char)szKey[(index + 3*nRound) % lengthKey]));
  833. }
  834. }
  835. ZString ZString::Scramble(const ZString& strKey) const
  836. {
  837. char* cbResult = (char*)_alloca(GetLength() + 1);
  838. ZScramble(cbResult, (*this), strKey);
  839. return cbResult;
  840. }
  841. ZString ZString::Unscramble(const ZString& strKey) const
  842. {
  843. char* cbResult = (char*)_alloca(GetLength() + 1);
  844. ZUnscramble(cbResult, (*this), strKey);
  845. return cbResult;
  846. }