StringUtils.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. //
  2. // Copyright (c) 2008-2017 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../Precompiled.h"
  23. #include "../Core/StringUtils.h"
  24. #include <cstdio>
  25. #include "../DebugNew.h"
  26. namespace Urho3D
  27. {
  28. static const String base64_chars =
  29. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  30. "abcdefghijklmnopqrstuvwxyz"
  31. "0123456789+/";
  32. unsigned CountElements(const char* buffer, char separator)
  33. {
  34. if (!buffer)
  35. return 0;
  36. const char* endPos = buffer + String::CStringLength(buffer);
  37. const char* pos = buffer;
  38. unsigned ret = 0;
  39. while (pos < endPos)
  40. {
  41. if (*pos != separator)
  42. break;
  43. ++pos;
  44. }
  45. while (pos < endPos)
  46. {
  47. const char* start = pos;
  48. while (start < endPos)
  49. {
  50. if (*start == separator)
  51. break;
  52. ++start;
  53. }
  54. if (start == endPos)
  55. {
  56. ++ret;
  57. break;
  58. }
  59. const char* end = start;
  60. while (end < endPos)
  61. {
  62. if (*end != separator)
  63. break;
  64. ++end;
  65. }
  66. ++ret;
  67. pos = end;
  68. }
  69. return ret;
  70. }
  71. bool ToBool(const String& source)
  72. {
  73. return ToBool(source.CString());
  74. }
  75. bool ToBool(const char* source)
  76. {
  77. unsigned length = String::CStringLength(source);
  78. for (unsigned i = 0; i < length; ++i)
  79. {
  80. auto c = (char)tolower(source[i]);
  81. if (c == 't' || c == 'y' || c == '1')
  82. return true;
  83. else if (c != ' ' && c != '\t')
  84. break;
  85. }
  86. return false;
  87. }
  88. int ToInt(const String& source, int base)
  89. {
  90. return ToInt(source.CString(), base);
  91. }
  92. int ToInt(const char* source, int base)
  93. {
  94. if (!source)
  95. return 0;
  96. // Shield against runtime library assert by converting illegal base values to 0 (autodetect)
  97. if (base < 2 || base > 36)
  98. base = 0;
  99. return (int)strtol(source, nullptr, base);
  100. }
  101. long long ToInt64(const char* source, int base)
  102. {
  103. if (!source)
  104. return 0;
  105. // Shield against runtime library assert by converting illegal base values to 0 (autodetect)
  106. if (base < 2 || base > 36)
  107. base = 0;
  108. return strtoll(source, nullptr, base);
  109. }
  110. long long ToInt64(const String& source, int base)
  111. {
  112. return ToInt64(source.CString(), base);
  113. }
  114. unsigned ToUInt(const String& source, int base)
  115. {
  116. return ToUInt(source.CString(), base);
  117. }
  118. unsigned long long ToUInt64(const char* source, int base)
  119. {
  120. if (!source)
  121. return 0;
  122. // Shield against runtime library assert by converting illegal base values to 0 (autodetect)
  123. if (base < 2 || base > 36)
  124. base = 0;
  125. return strtoull(source, nullptr, base);
  126. }
  127. unsigned long long ToUInt64(const String& source, int base)
  128. {
  129. return ToUInt64(source.CString(), base);
  130. }
  131. unsigned ToUInt(const char* source, int base)
  132. {
  133. if (!source)
  134. return 0;
  135. if (base < 2 || base > 36)
  136. base = 0;
  137. return (unsigned)strtoul(source, nullptr, base);
  138. }
  139. float ToFloat(const String& source)
  140. {
  141. return ToFloat(source.CString());
  142. }
  143. float ToFloat(const char* source)
  144. {
  145. if (!source)
  146. return 0;
  147. return (float)strtod(source, nullptr);
  148. }
  149. double ToDouble(const String& source)
  150. {
  151. return ToDouble(source.CString());
  152. }
  153. double ToDouble(const char* source)
  154. {
  155. if (!source)
  156. return 0;
  157. return strtod(source, nullptr);
  158. }
  159. Color ToColor(const String& source)
  160. {
  161. return ToColor(source.CString());
  162. }
  163. Color ToColor(const char* source)
  164. {
  165. Color ret;
  166. unsigned elements = CountElements(source, ' ');
  167. if (elements < 3)
  168. return ret;
  169. auto* ptr = (char*)source;
  170. ret.r_ = (float)strtod(ptr, &ptr);
  171. ret.g_ = (float)strtod(ptr, &ptr);
  172. ret.b_ = (float)strtod(ptr, &ptr);
  173. if (elements > 3)
  174. ret.a_ = (float)strtod(ptr, &ptr);
  175. return ret;
  176. }
  177. IntRect ToIntRect(const String& source)
  178. {
  179. return ToIntRect(source.CString());
  180. }
  181. IntRect ToIntRect(const char* source)
  182. {
  183. IntRect ret(IntRect::ZERO);
  184. unsigned elements = CountElements(source, ' ');
  185. if (elements < 4)
  186. return ret;
  187. auto* ptr = (char*)source;
  188. ret.left_ = (int)strtol(ptr, &ptr, 10);
  189. ret.top_ = (int)strtol(ptr, &ptr, 10);
  190. ret.right_ = (int)strtol(ptr, &ptr, 10);
  191. ret.bottom_ = (int)strtol(ptr, &ptr, 10);
  192. return ret;
  193. }
  194. IntVector2 ToIntVector2(const String& source)
  195. {
  196. return ToIntVector2(source.CString());
  197. }
  198. IntVector2 ToIntVector2(const char* source)
  199. {
  200. IntVector2 ret(IntVector2::ZERO);
  201. unsigned elements = CountElements(source, ' ');
  202. if (elements < 2)
  203. return ret;
  204. auto* ptr = (char*)source;
  205. ret.x_ = (int)strtol(ptr, &ptr, 10);
  206. ret.y_ = (int)strtol(ptr, &ptr, 10);
  207. return ret;
  208. }
  209. IntVector3 ToIntVector3(const String& source)
  210. {
  211. return ToIntVector3(source.CString());
  212. }
  213. IntVector3 ToIntVector3(const char* source)
  214. {
  215. IntVector3 ret(IntVector3::ZERO);
  216. unsigned elements = CountElements(source, ' ');
  217. if (elements < 3)
  218. return ret;
  219. auto* ptr = (char*)source;
  220. ret.x_ = (int)strtol(ptr, &ptr, 10);
  221. ret.y_ = (int)strtol(ptr, &ptr, 10);
  222. ret.z_ = (int)strtol(ptr, &ptr, 10);
  223. return ret;
  224. }
  225. Rect ToRect(const String& source)
  226. {
  227. return ToRect(source.CString());
  228. }
  229. Rect ToRect(const char* source)
  230. {
  231. Rect ret(Rect::ZERO);
  232. unsigned elements = CountElements(source, ' ');
  233. if (elements < 4)
  234. return ret;
  235. auto* ptr = (char*)source;
  236. ret.min_.x_ = (float)strtod(ptr, &ptr);
  237. ret.min_.y_ = (float)strtod(ptr, &ptr);
  238. ret.max_.x_ = (float)strtod(ptr, &ptr);
  239. ret.max_.y_ = (float)strtod(ptr, &ptr);
  240. return ret;
  241. }
  242. Quaternion ToQuaternion(const String& source)
  243. {
  244. return ToQuaternion(source.CString());
  245. }
  246. Quaternion ToQuaternion(const char* source)
  247. {
  248. unsigned elements = CountElements(source, ' ');
  249. auto* ptr = (char*)source;
  250. if (elements < 3)
  251. return Quaternion::IDENTITY;
  252. else if (elements < 4)
  253. {
  254. // 3 coords specified: conversion from Euler angles
  255. float x, y, z;
  256. x = (float)strtod(ptr, &ptr);
  257. y = (float)strtod(ptr, &ptr);
  258. z = (float)strtod(ptr, &ptr);
  259. return Quaternion(x, y, z);
  260. }
  261. else
  262. {
  263. // 4 coords specified: full quaternion
  264. Quaternion ret;
  265. ret.w_ = (float)strtod(ptr, &ptr);
  266. ret.x_ = (float)strtod(ptr, &ptr);
  267. ret.y_ = (float)strtod(ptr, &ptr);
  268. ret.z_ = (float)strtod(ptr, &ptr);
  269. return ret;
  270. }
  271. }
  272. Vector2 ToVector2(const String& source)
  273. {
  274. return ToVector2(source.CString());
  275. }
  276. Vector2 ToVector2(const char* source)
  277. {
  278. Vector2 ret(Vector2::ZERO);
  279. unsigned elements = CountElements(source, ' ');
  280. if (elements < 2)
  281. return ret;
  282. auto* ptr = (char*)source;
  283. ret.x_ = (float)strtod(ptr, &ptr);
  284. ret.y_ = (float)strtod(ptr, &ptr);
  285. return ret;
  286. }
  287. Vector3 ToVector3(const String& source)
  288. {
  289. return ToVector3(source.CString());
  290. }
  291. Vector3 ToVector3(const char* source)
  292. {
  293. Vector3 ret(Vector3::ZERO);
  294. unsigned elements = CountElements(source, ' ');
  295. if (elements < 3)
  296. return ret;
  297. auto* ptr = (char*)source;
  298. ret.x_ = (float)strtod(ptr, &ptr);
  299. ret.y_ = (float)strtod(ptr, &ptr);
  300. ret.z_ = (float)strtod(ptr, &ptr);
  301. return ret;
  302. }
  303. Vector4 ToVector4(const String& source, bool allowMissingCoords)
  304. {
  305. return ToVector4(source.CString(), allowMissingCoords);
  306. }
  307. Vector4 ToVector4(const char* source, bool allowMissingCoords)
  308. {
  309. Vector4 ret(Vector4::ZERO);
  310. unsigned elements = CountElements(source, ' ');
  311. auto* ptr = (char*)source;
  312. if (!allowMissingCoords)
  313. {
  314. if (elements < 4)
  315. return ret;
  316. ret.x_ = (float)strtod(ptr, &ptr);
  317. ret.y_ = (float)strtod(ptr, &ptr);
  318. ret.z_ = (float)strtod(ptr, &ptr);
  319. ret.w_ = (float)strtod(ptr, &ptr);
  320. return ret;
  321. }
  322. else
  323. {
  324. if (elements > 0)
  325. ret.x_ = (float)strtod(ptr, &ptr);
  326. if (elements > 1)
  327. ret.y_ = (float)strtod(ptr, &ptr);
  328. if (elements > 2)
  329. ret.z_ = (float)strtod(ptr, &ptr);
  330. if (elements > 3)
  331. ret.w_ = (float)strtod(ptr, &ptr);
  332. return ret;
  333. }
  334. }
  335. Variant ToVectorVariant(const String& source)
  336. {
  337. return ToVectorVariant(source.CString());
  338. }
  339. Variant ToVectorVariant(const char* source)
  340. {
  341. Variant ret;
  342. unsigned elements = CountElements(source, ' ');
  343. switch (elements)
  344. {
  345. case 1:
  346. ret.FromString(VAR_FLOAT, source);
  347. break;
  348. case 2:
  349. ret.FromString(VAR_VECTOR2, source);
  350. break;
  351. case 3:
  352. ret.FromString(VAR_VECTOR3, source);
  353. break;
  354. case 4:
  355. ret.FromString(VAR_VECTOR4, source);
  356. break;
  357. case 9:
  358. ret.FromString(VAR_MATRIX3, source);
  359. break;
  360. case 12:
  361. ret.FromString(VAR_MATRIX3X4, source);
  362. break;
  363. case 16:
  364. ret.FromString(VAR_MATRIX4, source);
  365. break;
  366. default:
  367. // Illegal input. Return variant remains empty
  368. break;
  369. }
  370. return ret;
  371. }
  372. Matrix3 ToMatrix3(const String& source)
  373. {
  374. return ToMatrix3(source.CString());
  375. }
  376. Matrix3 ToMatrix3(const char* source)
  377. {
  378. Matrix3 ret(Matrix3::ZERO);
  379. unsigned elements = CountElements(source, ' ');
  380. if (elements < 9)
  381. return ret;
  382. auto* ptr = (char*)source;
  383. ret.m00_ = (float)strtod(ptr, &ptr);
  384. ret.m01_ = (float)strtod(ptr, &ptr);
  385. ret.m02_ = (float)strtod(ptr, &ptr);
  386. ret.m10_ = (float)strtod(ptr, &ptr);
  387. ret.m11_ = (float)strtod(ptr, &ptr);
  388. ret.m12_ = (float)strtod(ptr, &ptr);
  389. ret.m20_ = (float)strtod(ptr, &ptr);
  390. ret.m21_ = (float)strtod(ptr, &ptr);
  391. ret.m22_ = (float)strtod(ptr, &ptr);
  392. return ret;
  393. }
  394. Matrix3x4 ToMatrix3x4(const String& source)
  395. {
  396. return ToMatrix3x4(source.CString());
  397. }
  398. Matrix3x4 ToMatrix3x4(const char* source)
  399. {
  400. Matrix3x4 ret(Matrix3x4::ZERO);
  401. unsigned elements = CountElements(source, ' ');
  402. if (elements < 12)
  403. return ret;
  404. auto* ptr = (char*)source;
  405. ret.m00_ = (float)strtod(ptr, &ptr);
  406. ret.m01_ = (float)strtod(ptr, &ptr);
  407. ret.m02_ = (float)strtod(ptr, &ptr);
  408. ret.m03_ = (float)strtod(ptr, &ptr);
  409. ret.m10_ = (float)strtod(ptr, &ptr);
  410. ret.m11_ = (float)strtod(ptr, &ptr);
  411. ret.m12_ = (float)strtod(ptr, &ptr);
  412. ret.m13_ = (float)strtod(ptr, &ptr);
  413. ret.m20_ = (float)strtod(ptr, &ptr);
  414. ret.m21_ = (float)strtod(ptr, &ptr);
  415. ret.m22_ = (float)strtod(ptr, &ptr);
  416. ret.m23_ = (float)strtod(ptr, &ptr);
  417. return ret;
  418. }
  419. Matrix4 ToMatrix4(const String& source)
  420. {
  421. return ToMatrix4(source.CString());
  422. }
  423. Matrix4 ToMatrix4(const char* source)
  424. {
  425. Matrix4 ret(Matrix4::ZERO);
  426. unsigned elements = CountElements(source, ' ');
  427. if (elements < 16)
  428. return ret;
  429. auto* ptr = (char*)source;
  430. ret.m00_ = (float)strtod(ptr, &ptr);
  431. ret.m01_ = (float)strtod(ptr, &ptr);
  432. ret.m02_ = (float)strtod(ptr, &ptr);
  433. ret.m03_ = (float)strtod(ptr, &ptr);
  434. ret.m10_ = (float)strtod(ptr, &ptr);
  435. ret.m11_ = (float)strtod(ptr, &ptr);
  436. ret.m12_ = (float)strtod(ptr, &ptr);
  437. ret.m13_ = (float)strtod(ptr, &ptr);
  438. ret.m20_ = (float)strtod(ptr, &ptr);
  439. ret.m21_ = (float)strtod(ptr, &ptr);
  440. ret.m22_ = (float)strtod(ptr, &ptr);
  441. ret.m23_ = (float)strtod(ptr, &ptr);
  442. ret.m30_ = (float)strtod(ptr, &ptr);
  443. ret.m31_ = (float)strtod(ptr, &ptr);
  444. ret.m32_ = (float)strtod(ptr, &ptr);
  445. ret.m33_ = (float)strtod(ptr, &ptr);
  446. return ret;
  447. }
  448. String ToString(void* value)
  449. {
  450. return ToStringHex((unsigned)(size_t)value);
  451. }
  452. String ToStringHex(unsigned value)
  453. {
  454. char tempBuffer[CONVERSION_BUFFER_LENGTH];
  455. sprintf(tempBuffer, "%08x", value);
  456. return String(tempBuffer);
  457. }
  458. void BufferToString(String& dest, const void* data, unsigned size)
  459. {
  460. // Precalculate needed string size
  461. const auto* bytes = (const unsigned char*)data;
  462. unsigned length = 0;
  463. for (unsigned i = 0; i < size; ++i)
  464. {
  465. // Room for separator
  466. if (i)
  467. ++length;
  468. // Room for the value
  469. if (bytes[i] < 10)
  470. ++length;
  471. else if (bytes[i] < 100)
  472. length += 2;
  473. else
  474. length += 3;
  475. }
  476. dest.Resize(length);
  477. unsigned index = 0;
  478. // Convert values
  479. for (unsigned i = 0; i < size; ++i)
  480. {
  481. if (i)
  482. dest[index++] = ' ';
  483. if (bytes[i] < 10)
  484. {
  485. dest[index++] = '0' + bytes[i];
  486. }
  487. else if (bytes[i] < 100)
  488. {
  489. dest[index++] = (char)('0' + bytes[i] / 10);
  490. dest[index++] = (char)('0' + bytes[i] % 10);
  491. }
  492. else
  493. {
  494. dest[index++] = (char)('0' + bytes[i] / 100);
  495. dest[index++] = (char)('0' + bytes[i] % 100 / 10);
  496. dest[index++] = (char)('0' + bytes[i] % 10);
  497. }
  498. }
  499. }
  500. void StringToBuffer(PODVector<unsigned char>& dest, const String& source)
  501. {
  502. StringToBuffer(dest, source.CString());
  503. }
  504. void StringToBuffer(PODVector<unsigned char>& dest, const char* source)
  505. {
  506. if (!source)
  507. {
  508. dest.Clear();
  509. return;
  510. }
  511. unsigned size = CountElements(source, ' ');
  512. dest.Resize(size);
  513. bool inSpace = true;
  514. unsigned index = 0;
  515. unsigned value = 0;
  516. // Parse values
  517. const char* ptr = source;
  518. while (*ptr)
  519. {
  520. if (inSpace && *ptr != ' ')
  521. {
  522. inSpace = false;
  523. value = (unsigned)(*ptr - '0');
  524. }
  525. else if (!inSpace && *ptr != ' ')
  526. {
  527. value *= 10;
  528. value += *ptr - '0';
  529. }
  530. else if (!inSpace && *ptr == ' ')
  531. {
  532. dest[index++] = (unsigned char)value;
  533. inSpace = true;
  534. }
  535. ++ptr;
  536. }
  537. // Write the final value
  538. if (!inSpace && index < size)
  539. dest[index] = (unsigned char)value;
  540. }
  541. unsigned GetStringListIndex(const String& value, const String* strings, unsigned defaultIndex, bool caseSensitive)
  542. {
  543. return GetStringListIndex(value.CString(), strings, defaultIndex, caseSensitive);
  544. }
  545. unsigned GetStringListIndex(const char* value, const String* strings, unsigned defaultIndex, bool caseSensitive)
  546. {
  547. unsigned i = 0;
  548. while (!strings[i].Empty())
  549. {
  550. if (!strings[i].Compare(value, caseSensitive))
  551. return i;
  552. ++i;
  553. }
  554. return defaultIndex;
  555. }
  556. unsigned GetStringListIndex(const char* value, const char** strings, unsigned defaultIndex, bool caseSensitive)
  557. {
  558. unsigned i = 0;
  559. while (strings[i])
  560. {
  561. if (!String::Compare(value, strings[i], caseSensitive))
  562. return i;
  563. ++i;
  564. }
  565. return defaultIndex;
  566. }
  567. String ToString(const char* formatString, ...)
  568. {
  569. String ret;
  570. va_list args;
  571. va_start(args, formatString);
  572. ret.AppendWithFormatArgs(formatString, args);
  573. va_end(args);
  574. return ret;
  575. }
  576. bool IsAlpha(unsigned ch)
  577. {
  578. return ch < 256 ? isalpha(ch) != 0 : false;
  579. }
  580. bool IsDigit(unsigned ch)
  581. {
  582. return ch < 256 ? isdigit(ch) != 0 : false;
  583. }
  584. unsigned ToUpper(unsigned ch)
  585. {
  586. return (unsigned)toupper(ch);
  587. }
  588. unsigned ToLower(unsigned ch)
  589. {
  590. return (unsigned)tolower(ch);
  591. }
  592. String GetFileSizeString(unsigned long long memorySize)
  593. {
  594. static const char* memorySizeStrings = "kMGTPE";
  595. String output;
  596. if (memorySize < 1024)
  597. {
  598. output = String(memorySize) + " b";
  599. }
  600. else
  601. {
  602. const auto exponent = (int)(log((double)memorySize) / log(1024.0));
  603. const double majorValue = ((double)memorySize) / pow(1024.0, exponent);
  604. char buffer[64];
  605. memset(buffer, 0, 64);
  606. sprintf(buffer, "%.1f", majorValue);
  607. output = buffer;
  608. output += " ";
  609. output += memorySizeStrings[exponent - 1];
  610. }
  611. return output;
  612. }
  613. // Implementation of base64 decoding originally by Ren� Nyffenegger.
  614. // Modified by Konstantin Guschin and Lasse Oorni
  615. /*
  616. base64.cpp and base64.h
  617. Copyright (C) 2004-2017 Ren� Nyffenegger
  618. This source code is provided 'as-is', without any express or implied
  619. warranty. In no event will the author be held liable for any damages
  620. arising from the use of this software.
  621. Permission is granted to anyone to use this software for any purpose,
  622. including commercial applications, and to alter it and redistribute it
  623. freely, subject to the following restrictions:
  624. 1. The origin of this source code must not be misrepresented; you must not
  625. claim that you wrote the original source code. If you use this source code
  626. in a product, an acknowledgment in the product documentation would be
  627. appreciated but is not required.
  628. 2. Altered source versions must be plainly marked as such, and must not be
  629. misrepresented as being the original source code.
  630. 3. This notice may not be removed or altered from any source distribution.
  631. Ren� Nyffenegger [email protected]
  632. */
  633. static inline bool IsBase64(char c) {
  634. return (isalnum(c) || (c == '+') || (c == '/'));
  635. }
  636. PODVector<unsigned char> DecodeBase64(String encodedString)
  637. {
  638. int inLen = encodedString.Length();
  639. int i = 0;
  640. int j = 0;
  641. int in_ = 0;
  642. unsigned char charArray4[4], charArray3[3];
  643. PODVector<unsigned char> ret;
  644. while (inLen-- && (encodedString[in_] != '=') && IsBase64(encodedString[in_]))
  645. {
  646. charArray4[i++] = encodedString[in_];
  647. in_++;
  648. if (i == 4)
  649. {
  650. for (i = 0; i < 4; i++)
  651. charArray4[i] = base64_chars.Find(charArray4[i]);
  652. charArray3[0] = (charArray4[0] << 2) + ((charArray4[1] & 0x30) >> 4);
  653. charArray3[1] = ((charArray4[1] & 0xf) << 4) + ((charArray4[2] & 0x3c) >> 2);
  654. charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3];
  655. for (i = 0; (i < 3); i++)
  656. ret.Push(charArray3[i]);
  657. i = 0;
  658. }
  659. }
  660. if (i)
  661. {
  662. for (j = i; j <4; j++)
  663. charArray4[j] = 0;
  664. for (j = 0; j <4; j++)
  665. charArray4[j] = base64_chars.Find(charArray4[j]);
  666. charArray3[0] = (charArray4[0] << 2) + ((charArray4[1] & 0x30) >> 4);
  667. charArray3[1] = ((charArray4[1] & 0xf) << 4) + ((charArray4[2] & 0x3c) >> 2);
  668. charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3];
  669. for (j = 0; (j < i - 1); j++)
  670. ret.Push(charArray3[j]);
  671. }
  672. return ret;
  673. }
  674. }