/CoolEngine/IronPython/Src/IronPython.Modules/struct.cs

# · C# · 759 lines · 668 code · 76 blank · 15 comment · 118 complexity · 6be8065d975847109496b870bf8486a3 MD5 · raw file

  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Microsoft Public License, please send an email to
  8. * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Text;
  18. using System.IO;
  19. using IronPython.Runtime;
  20. using IronPython.Runtime.Exceptions;
  21. using Microsoft.Scripting.Math;
  22. using IronPython.Runtime.Types;
  23. [assembly: PythonModule("struct", typeof(IronPython.Modules.PythonStruct))]
  24. namespace IronPython.Modules {
  25. public static class PythonStruct {
  26. #region Public API Surface
  27. public static string pack(string fmt, params object[] values) {
  28. int count = 1;
  29. int curObj = 0;
  30. StringBuilder res = new StringBuilder();
  31. bool fLittleEndian = BitConverter.IsLittleEndian;
  32. bool fStandardized = false;
  33. for (int i = 0; i < fmt.Length; i++) {
  34. switch (fmt[i]) {
  35. case 'x': // pad byte
  36. res.Append('\0');
  37. break;
  38. case 'c': // char
  39. for (int j = 0; j < count; j++) res.Append(GetCharValue(curObj++, values));
  40. count = 1;
  41. break;
  42. case 'b': // signed char
  43. for (int j = 0; j < count; j++) res.Append((char)(byte)GetSByteValue(curObj++, values));
  44. count = 1;
  45. break;
  46. case 'B': // unsigned char
  47. for (int j = 0; j < count; j++) res.Append((char)GetByteValue(curObj++, values));
  48. count = 1;
  49. break;
  50. case 'h': // short
  51. for (int j = 0; j < count; j++) WriteShort(res, fLittleEndian, GetShortValue(curObj++, values));
  52. count = 1;
  53. break;
  54. case 'H': // unsigned short
  55. for (int j = 0; j < count; j++) WriteUShort(res, fLittleEndian, GetUShortValue(curObj++, values));
  56. count = 1;
  57. break;
  58. case 'i': // int
  59. case 'l': // long
  60. for (int j = 0; j < count; j++) WriteInt(res, fLittleEndian, GetIntValue(curObj++, values));
  61. count = 1;
  62. break;
  63. case 'I': // unsigned int
  64. case 'L': // unsigned long
  65. for (int j = 0; j < count; j++) WriteUInt(res, fLittleEndian, GetUIntValue(curObj++, values));
  66. count = 1;
  67. break;
  68. case 'q': // long long
  69. for (int j = 0; j < count; j++) WriteLong(res, fLittleEndian, GetLongValue(curObj++, values));
  70. count = 1;
  71. break;
  72. case 'Q': // unsigned long long
  73. for (int j = 0; j < count; j++) WriteULong(res, fLittleEndian, GetULongValue(curObj++, values));
  74. count = 1;
  75. break;
  76. case 'f': // float
  77. for (int j = 0; j < count; j++) WriteFloat(res, fLittleEndian, (float)GetDoubleValue(curObj++, values));
  78. count = 1;
  79. break;
  80. case 'd': // double
  81. for (int j = 0; j < count; j++) WriteDouble(res, fLittleEndian, GetDoubleValue(curObj++, values));
  82. count = 1;
  83. break;
  84. case 's': // char[]
  85. WriteString(res, count, GetStringValue(curObj++, values));
  86. count = 1;
  87. break;
  88. case 'p': // char[]
  89. WritePascalString(res, count - 1, GetStringValue(curObj++, values));
  90. count = 1;
  91. break;
  92. case 'P': // void *
  93. if (IntPtr.Size == 4) goto case 'I';
  94. goto case 'Q';
  95. case ' ': // white space, ignore
  96. case '\t':
  97. break;
  98. case '=': // native
  99. if (i != 0) throw Error("unexpected byte order");
  100. fStandardized = true;
  101. break;
  102. case '@': // native
  103. if (i != 0) throw Error("unexpected byte order");
  104. break;
  105. case '<': // little endian
  106. if (i != 0) throw Error("unexpected byte order");
  107. fLittleEndian = true;
  108. fStandardized = true;
  109. break;
  110. case '>': // big endian
  111. case '!': // big endian
  112. if (i != 0) throw Error("unexpected byte order");
  113. fLittleEndian = false;
  114. fStandardized = true;
  115. break;
  116. default:
  117. if (Char.IsDigit(fmt[i])) {
  118. count = 0;
  119. while (Char.IsDigit(fmt[i])) {
  120. count = count * 10 + (fmt[i] - '0');
  121. i++;
  122. }
  123. if (Char.IsWhiteSpace(fmt[i])) Error("white space not allowed between count and format");
  124. i--;
  125. break;
  126. }
  127. throw Error("bad format string");
  128. }
  129. }
  130. if (curObj != values.Length) throw Error("not all arguments used");
  131. if (fStandardized) return res.ToString();
  132. return res.ToString();
  133. }
  134. public static PythonTuple unpack(string fmt, string @string) {
  135. string data = @string;
  136. int count = 1;
  137. int curIndex = 0;
  138. List<object> res = new List<object>();
  139. bool fLittleEndian = BitConverter.IsLittleEndian;
  140. bool fStandardized = false;
  141. for (int i = 0; i < fmt.Length; i++) {
  142. switch (fmt[i]) {
  143. case 'x': // pad byte
  144. curIndex += count;
  145. count = 1;
  146. break;
  147. case 'c': // char
  148. for (int j = 0; j < count; j++) res.Add(CreateCharValue(ref curIndex, data).ToString());
  149. count = 1;
  150. break;
  151. case 'b': // signed char
  152. for (int j = 0; j < count; j++) res.Add((int)(sbyte)CreateCharValue(ref curIndex, data));
  153. count = 1;
  154. break;
  155. case 'B': // unsigned char
  156. for (int j = 0; j < count; j++) res.Add((int)CreateCharValue(ref curIndex, data));
  157. count = 1;
  158. break;
  159. case 'h': // short
  160. for (int j = 0; j < count; j++) res.Add((int)CreateShortValue(ref curIndex, fLittleEndian, data));
  161. count = 1;
  162. break;
  163. case 'H': // unsigned short
  164. for (int j = 0; j < count; j++) res.Add((int)CreateUShortValue(ref curIndex, fLittleEndian, data));
  165. count = 1;
  166. break;
  167. case 'i': // int
  168. case 'l': // long
  169. for (int j = 0; j < count; j++) res.Add(CreateIntValue(ref curIndex, fLittleEndian, data));
  170. count = 1;
  171. break;
  172. case 'I': // unsigned int
  173. case 'L': // unsigned long
  174. for (int j = 0; j < count; j++) res.Add(BigInteger.Create(CreateUIntValue(ref curIndex, fLittleEndian, data)));
  175. count = 1;
  176. break;
  177. case 'q': // long long
  178. for (int j = 0; j < count; j++) res.Add(BigInteger.Create(CreateLongValue(ref curIndex, fLittleEndian, data)));
  179. count = 1;
  180. break;
  181. case 'Q': // unsigned long long
  182. for (int j = 0; j < count; j++) res.Add(BigInteger.Create(CreateULongValue(ref curIndex, fLittleEndian, data)));
  183. count = 1;
  184. break;
  185. case 'f': // float
  186. for (int j = 0; j < count; j++) res.Add((double)CreateFloatValue(ref curIndex, fLittleEndian, data));
  187. count = 1;
  188. break;
  189. case 'd': // double
  190. for (int j = 0; j < count; j++) res.Add(CreateDoubleValue(ref curIndex, fLittleEndian, data));
  191. count = 1;
  192. break;
  193. case 's': // char[]
  194. res.Add(CreateString(ref curIndex, count, data));
  195. count = 1;
  196. break;
  197. case 'p': // char[]
  198. res.Add(CreatePascalString(ref curIndex, count - 1, data));
  199. count = 1;
  200. break;
  201. case 'P': // void *
  202. if (IntPtr.Size == 4) goto case 'I';
  203. goto case 'Q';
  204. case ' ': // white space, ignore
  205. case '\t':
  206. break;
  207. case '=': // native
  208. if (i != 0) Error("unexpected byte order");
  209. fStandardized = true;
  210. break;
  211. case '@': // native
  212. if (i != 0) Error("unexpected byte order");
  213. break;
  214. case '<': // little endian
  215. if (i != 0) Error("unexpected byte order");
  216. fLittleEndian = true;
  217. fStandardized = true;
  218. break;
  219. case '>': // big endian
  220. case '!': // big endian
  221. if (i != 0) Error("unexpected byte order");
  222. fLittleEndian = false;
  223. fStandardized = true;
  224. break;
  225. default:
  226. if (Char.IsDigit(fmt[i])) {
  227. count = 0;
  228. while (Char.IsDigit(fmt[i])) {
  229. count = count * 10 + (fmt[i] - '0');
  230. i++;
  231. }
  232. if (Char.IsWhiteSpace(fmt[i])) Error("white space not allowed between count and format");
  233. i--;
  234. break;
  235. }
  236. throw Error("bad format string");
  237. }
  238. }
  239. if (curIndex != data.Length) throw Error("not all data used");
  240. if (fStandardized)
  241. return new PythonTuple(res);
  242. return new PythonTuple(res);
  243. }
  244. private static int Align(int length, int size) {
  245. return length + (size - 1) & ~(size - 1);
  246. }
  247. public static int calcsize(string fmt) {
  248. int len = 0;
  249. int count = 1;
  250. for (int i = 0; i < fmt.Length; i++) {
  251. switch (fmt[i]) {
  252. case 'x': // pad byte
  253. case 'c': // char
  254. case 'b': // signed char
  255. case 'B': // unsigned char
  256. case 's': // char[]
  257. len += (count);
  258. count = 1;
  259. break;
  260. case 'h': // short
  261. case 'H': // unsigned short
  262. len = Align(len, 2);
  263. len += 2 * count;
  264. count = 1;
  265. break;
  266. case 'i': // int
  267. case 'I': // unsigned int
  268. case 'l': // long
  269. case 'L': // unsigned long
  270. len = Align(len, 4);
  271. len += 4 * count;
  272. count = 1;
  273. break;
  274. case 'q': // long long
  275. case 'Q': // unsigned long long
  276. len = Align(len, 8);
  277. len += 8 * count;
  278. count = 1;
  279. break;
  280. case 'f': // float
  281. len = Align(len, 4);
  282. len += 4 * count;
  283. count = 1;
  284. break;
  285. case 'd': // double
  286. len = Align(len, 8);
  287. len += 8 * count;
  288. count = 1;
  289. break;
  290. case 'p': // char[]
  291. len += count + 1;
  292. break;
  293. case 'P': // void *
  294. len = Align(len, IntPtr.Size);
  295. len += IntPtr.Size;
  296. break;
  297. case ' ':
  298. case '\t':
  299. break;
  300. case '=': // native
  301. case '@': // native
  302. case '<': // little endian
  303. case '>': // big endian
  304. case '!': // big endian
  305. if (i != 0) PythonExceptions.CreateThrowable(error, "unexpected byte order");
  306. break;
  307. default:
  308. if (Char.IsDigit(fmt[i])) {
  309. count = 0;
  310. while (Char.IsDigit(fmt[i])) {
  311. count = count * 10 + (fmt[i] - '0');
  312. i++;
  313. }
  314. i--;
  315. break;
  316. }
  317. throw Error("bad format string");
  318. }
  319. }
  320. return len;
  321. }
  322. public static PythonType error = PythonExceptions.CreateSubType(PythonExceptions.Exception, "error", "struct", "");
  323. #endregion
  324. #region Write Helpers
  325. private static void WriteShort(StringBuilder res, bool fLittleEndian, short val) {
  326. if (fLittleEndian) {
  327. res.Append((char)(val & 0xff));
  328. res.Append((char)((val >> 8) & 0xff));
  329. } else {
  330. res.Append((char)((val >> 8) & 0xff));
  331. res.Append((char)(val & 0xff));
  332. }
  333. }
  334. private static void WriteUShort(StringBuilder res, bool fLittleEndian, ushort val) {
  335. if (fLittleEndian) {
  336. res.Append((char)(val & 0xff));
  337. res.Append((char)((val >> 8) & 0xff));
  338. } else {
  339. res.Append((char)((val >> 8) & 0xff));
  340. res.Append((char)(val & 0xff));
  341. }
  342. }
  343. private static void WriteInt(StringBuilder res, bool fLittleEndian, int val) {
  344. if (fLittleEndian) {
  345. res.Append((char)(val & 0xff));
  346. res.Append((char)((val >> 8) & 0xff));
  347. res.Append((char)((val >> 16) & 0xff));
  348. res.Append((char)((val >> 24) & 0xff));
  349. } else {
  350. res.Append((char)((val >> 24) & 0xff));
  351. res.Append((char)((val >> 16) & 0xff));
  352. res.Append((char)((val >> 8) & 0xff));
  353. res.Append((char)(val & 0xff));
  354. }
  355. }
  356. private static void WriteUInt(StringBuilder res, bool fLittleEndian, uint val) {
  357. if (fLittleEndian) {
  358. res.Append((char)(val & 0xff));
  359. res.Append((char)((val >> 8) & 0xff));
  360. res.Append((char)((val >> 16) & 0xff));
  361. res.Append((char)((val >> 24) & 0xff));
  362. } else {
  363. res.Append((char)((val >> 24) & 0xff));
  364. res.Append((char)((val >> 16) & 0xff));
  365. res.Append((char)((val >> 8) & 0xff));
  366. res.Append((char)(val & 0xff));
  367. }
  368. }
  369. private static void WriteFloat(StringBuilder res, bool fLittleEndian, float val) {
  370. byte[] bytes = BitConverter.GetBytes(val);
  371. if (fLittleEndian) {
  372. res.Append((char)bytes[0]);
  373. res.Append((char)bytes[1]);
  374. res.Append((char)bytes[2]);
  375. res.Append((char)bytes[3]);
  376. } else {
  377. res.Append((char)bytes[3]);
  378. res.Append((char)bytes[2]);
  379. res.Append((char)bytes[1]);
  380. res.Append((char)bytes[0]);
  381. }
  382. }
  383. private static void WriteLong(StringBuilder res, bool fLittleEndian, long val) {
  384. if (fLittleEndian) {
  385. res.Append((char)(val & 0xff));
  386. res.Append((char)((val >> 8) & 0xff));
  387. res.Append((char)((val >> 16) & 0xff));
  388. res.Append((char)((val >> 24) & 0xff));
  389. res.Append((char)((val >> 32) & 0xff));
  390. res.Append((char)((val >> 40) & 0xff));
  391. res.Append((char)((val >> 48) & 0xff));
  392. res.Append((char)((val >> 56) & 0xff));
  393. } else {
  394. res.Append((char)((val >> 56) & 0xff));
  395. res.Append((char)((val >> 48) & 0xff));
  396. res.Append((char)((val >> 40) & 0xff));
  397. res.Append((char)((val >> 32) & 0xff));
  398. res.Append((char)((val >> 24) & 0xff));
  399. res.Append((char)((val >> 16) & 0xff));
  400. res.Append((char)((val >> 8) & 0xff));
  401. res.Append((char)(val & 0xff));
  402. }
  403. }
  404. private static void WriteULong(StringBuilder res, bool fLittleEndian, ulong val) {
  405. if (fLittleEndian) {
  406. res.Append((char)(val & 0xff));
  407. res.Append((char)((val >> 8) & 0xff));
  408. res.Append((char)((val >> 16) & 0xff));
  409. res.Append((char)((val >> 24) & 0xff));
  410. res.Append((char)((val >> 32) & 0xff));
  411. res.Append((char)((val >> 40) & 0xff));
  412. res.Append((char)((val >> 48) & 0xff));
  413. res.Append((char)((val >> 56) & 0xff));
  414. } else {
  415. res.Append((char)((val >> 56) & 0xff));
  416. res.Append((char)((val >> 48) & 0xff));
  417. res.Append((char)((val >> 40) & 0xff));
  418. res.Append((char)((val >> 32) & 0xff));
  419. res.Append((char)((val >> 24) & 0xff));
  420. res.Append((char)((val >> 16) & 0xff));
  421. res.Append((char)((val >> 8) & 0xff));
  422. res.Append((char)(val & 0xff));
  423. }
  424. }
  425. private static void WriteDouble(StringBuilder res, bool fLittleEndian, double val) {
  426. byte[] bytes = BitConverter.GetBytes(val);
  427. if (fLittleEndian) {
  428. res.Append((char)bytes[0]);
  429. res.Append((char)bytes[1]);
  430. res.Append((char)bytes[2]);
  431. res.Append((char)bytes[3]);
  432. res.Append((char)bytes[4]);
  433. res.Append((char)bytes[5]);
  434. res.Append((char)bytes[6]);
  435. res.Append((char)bytes[7]);
  436. } else {
  437. res.Append((char)bytes[7]);
  438. res.Append((char)bytes[6]);
  439. res.Append((char)bytes[5]);
  440. res.Append((char)bytes[4]);
  441. res.Append((char)bytes[3]);
  442. res.Append((char)bytes[2]);
  443. res.Append((char)bytes[1]);
  444. res.Append((char)bytes[0]);
  445. }
  446. }
  447. private static void WriteString(StringBuilder res, int len, string val) {
  448. for (int i = 0; i < val.Length && i < len; i++) {
  449. res.Append(val[i]);
  450. }
  451. for (int i = val.Length; i < len; i++) {
  452. res.Append('\0');
  453. }
  454. }
  455. private static void WritePascalString(StringBuilder res, int len, string val) {
  456. int lenByte = Math.Min(255, Math.Min(val.Length, len));
  457. res.Append((char)lenByte);
  458. for (int i = 0; i < val.Length && i < len; i++) {
  459. res.Append(val[i]);
  460. }
  461. for (int i = val.Length; i < len; i++) {
  462. res.Append('\0');
  463. }
  464. }
  465. #endregion
  466. #region Data getter helpers
  467. internal static char GetCharValue(int index, object[] args) {
  468. string val = GetValue(index, args) as string;
  469. if (val == null || val.Length != 1) throw Error("char format requires string of length 1");
  470. return val[0];
  471. }
  472. internal static sbyte GetSByteValue(int index, object[] args) {
  473. object val = GetValue(index, args);
  474. sbyte res;
  475. if (Converter.TryConvertToSByte(val, out res)) {
  476. return res;
  477. }
  478. throw Error("expected sbyte value got " + val.ToString());
  479. }
  480. internal static byte GetByteValue(int index, object[] args) {
  481. object val = GetValue(index, args);
  482. byte res;
  483. if (Converter.TryConvertToByte(val, out res)) return res;
  484. char cres;
  485. if (Converter.TryConvertToChar(val, out cres)) return (byte)cres;
  486. throw Error("expected byte value got " + val.ToString());
  487. }
  488. internal static short GetShortValue(int index, object[] args) {
  489. object val = GetValue(index, args);
  490. short res;
  491. if (Converter.TryConvertToInt16(val, out res)) return res;
  492. throw Error("expected short value");
  493. }
  494. internal static ushort GetUShortValue(int index, object[] args) {
  495. object val = GetValue(index, args);
  496. ushort res;
  497. if (Converter.TryConvertToUInt16(val, out res)) return res;
  498. throw Error("expected ushort value");
  499. }
  500. internal static int GetIntValue(int index, object[] args) {
  501. object val = GetValue(index, args);
  502. int res;
  503. if (Converter.TryConvertToInt32(val, out res)) return res;
  504. throw Error("expected int value");
  505. }
  506. internal static uint GetUIntValue(int index, object[] args) {
  507. object val = GetValue(index, args);
  508. uint res;
  509. if (Converter.TryConvertToUInt32(val, out res)) return res;
  510. throw Error("expected uint value");
  511. }
  512. internal static long GetLongValue(int index, object[] args) {
  513. object val = GetValue(index, args);
  514. long res;
  515. if (Converter.TryConvertToInt64(val, out res)) return res;
  516. throw Error("expected long value");
  517. }
  518. internal static ulong GetULongValue(int index, object[] args) {
  519. object val = GetValue(index, args);
  520. ulong res;
  521. if (Converter.TryConvertToUInt64(val, out res)) return res;
  522. throw Error("expected ulong value");
  523. }
  524. internal static double GetDoubleValue(int index, object[] args) {
  525. object val = GetValue(index, args);
  526. double res;
  527. if (Converter.TryConvertToDouble(val, out res)) return res;
  528. throw Error("expected double value");
  529. }
  530. internal static string GetStringValue(int index, object[] args) {
  531. object val = GetValue(index, args);
  532. string res;
  533. if (Converter.TryConvertToString(val, out res)) return res;
  534. throw Error("expected string value");
  535. }
  536. internal static object GetValue(int index, object[] args) {
  537. if (index >= args.Length) throw Error("not enough arguments");
  538. return args[index];
  539. }
  540. #endregion
  541. #region Data creater helpers
  542. internal static char CreateCharValue(ref int index, string data) {
  543. return ReadData(ref index, data);
  544. }
  545. internal static short CreateShortValue(ref int index, bool fLittleEndian, string data) {
  546. byte b1 = (byte)ReadData(ref index, data);
  547. byte b2 = (byte)ReadData(ref index, data);
  548. if (fLittleEndian) {
  549. return (short)((b2 << 8) | b1);
  550. } else {
  551. return (short)((b1 << 8) | b2);
  552. }
  553. }
  554. internal static ushort CreateUShortValue(ref int index, bool fLittleEndian, string data) {
  555. byte b1 = (byte)ReadData(ref index, data);
  556. byte b2 = (byte)ReadData(ref index, data);
  557. if (fLittleEndian) {
  558. return (ushort)((b2 << 8) | b1);
  559. } else {
  560. return (ushort)((b1 << 8) | b2);
  561. }
  562. }
  563. internal static float CreateFloatValue(ref int index, bool fLittleEndian, string data) {
  564. byte[] bytes = new byte[4];
  565. if (fLittleEndian) {
  566. bytes[0] = (byte)ReadData(ref index, data);
  567. bytes[1] = (byte)ReadData(ref index, data);
  568. bytes[2] = (byte)ReadData(ref index, data);
  569. bytes[3] = (byte)ReadData(ref index, data);
  570. } else {
  571. bytes[3] = (byte)ReadData(ref index, data);
  572. bytes[2] = (byte)ReadData(ref index, data);
  573. bytes[1] = (byte)ReadData(ref index, data);
  574. bytes[0] = (byte)ReadData(ref index, data);
  575. }
  576. return BitConverter.ToSingle(bytes, 0);
  577. }
  578. internal static int CreateIntValue(ref int index, bool fLittleEndian, string data) {
  579. byte b1 = (byte)ReadData(ref index, data);
  580. byte b2 = (byte)ReadData(ref index, data);
  581. byte b3 = (byte)ReadData(ref index, data);
  582. byte b4 = (byte)ReadData(ref index, data);
  583. if (fLittleEndian)
  584. return (int)((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
  585. else
  586. return (int)((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
  587. }
  588. internal static uint CreateUIntValue(ref int index, bool fLittleEndian, string data) {
  589. byte b1 = (byte)ReadData(ref index, data);
  590. byte b2 = (byte)ReadData(ref index, data);
  591. byte b3 = (byte)ReadData(ref index, data);
  592. byte b4 = (byte)ReadData(ref index, data);
  593. if (fLittleEndian)
  594. return (uint)((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
  595. else
  596. return (uint)((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
  597. }
  598. internal static long CreateLongValue(ref int index, bool fLittleEndian, string data) {
  599. long b1 = (byte)ReadData(ref index, data);
  600. long b2 = (byte)ReadData(ref index, data);
  601. long b3 = (byte)ReadData(ref index, data);
  602. long b4 = (byte)ReadData(ref index, data);
  603. long b5 = (byte)ReadData(ref index, data);
  604. long b6 = (byte)ReadData(ref index, data);
  605. long b7 = (byte)ReadData(ref index, data);
  606. long b8 = (byte)ReadData(ref index, data);
  607. if (fLittleEndian)
  608. return (long)((b8 << 56) | (b7 << 48) | (b6 << 40) | (b5 << 32) |
  609. (b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
  610. else
  611. return (long)((b1 << 56) | (b2 << 48) | (b3 << 40) | (b4 << 32) |
  612. (b5 << 24) | (b6 << 16) | (b7 << 8) | b8);
  613. }
  614. internal static ulong CreateULongValue(ref int index, bool fLittleEndian, string data) {
  615. ulong b1 = (byte)ReadData(ref index, data);
  616. ulong b2 = (byte)ReadData(ref index, data);
  617. ulong b3 = (byte)ReadData(ref index, data);
  618. ulong b4 = (byte)ReadData(ref index, data);
  619. ulong b5 = (byte)ReadData(ref index, data);
  620. ulong b6 = (byte)ReadData(ref index, data);
  621. ulong b7 = (byte)ReadData(ref index, data);
  622. ulong b8 = (byte)ReadData(ref index, data);
  623. if (fLittleEndian)
  624. return (ulong)((b8 << 56) | (b7 << 48) | (b6 << 40) | (b5 << 32) |
  625. (b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
  626. else
  627. return (ulong)((b1 << 56) | (b2 << 48) | (b3 << 40) | (b4 << 32) |
  628. (b5 << 24) | (b6 << 16) | (b7 << 8) | b8);
  629. }
  630. internal static double CreateDoubleValue(ref int index, bool fLittleEndian, string data) {
  631. byte[] bytes = new byte[8];
  632. if (fLittleEndian) {
  633. bytes[0] = (byte)ReadData(ref index, data);
  634. bytes[1] = (byte)ReadData(ref index, data);
  635. bytes[2] = (byte)ReadData(ref index, data);
  636. bytes[3] = (byte)ReadData(ref index, data);
  637. bytes[4] = (byte)ReadData(ref index, data);
  638. bytes[5] = (byte)ReadData(ref index, data);
  639. bytes[6] = (byte)ReadData(ref index, data);
  640. bytes[7] = (byte)ReadData(ref index, data);
  641. } else {
  642. bytes[7] = (byte)ReadData(ref index, data);
  643. bytes[6] = (byte)ReadData(ref index, data);
  644. bytes[5] = (byte)ReadData(ref index, data);
  645. bytes[4] = (byte)ReadData(ref index, data);
  646. bytes[3] = (byte)ReadData(ref index, data);
  647. bytes[2] = (byte)ReadData(ref index, data);
  648. bytes[1] = (byte)ReadData(ref index, data);
  649. bytes[0] = (byte)ReadData(ref index, data);
  650. }
  651. return BitConverter.ToDouble(bytes, 0);
  652. }
  653. internal static string CreateString(ref int index, int count, string data) {
  654. StringBuilder res = new StringBuilder();
  655. for (int i = 0; i < count; i++) {
  656. res.Append(ReadData(ref index, data));
  657. }
  658. return res.ToString();
  659. }
  660. internal static string CreatePascalString(ref int index, int count, string data) {
  661. int realLen = (int)ReadData(ref index, data);
  662. StringBuilder res = new StringBuilder();
  663. for (int i = 0; i < realLen; i++) {
  664. res.Append(ReadData(ref index, data));
  665. }
  666. for (int i = realLen; i < count; i++) {
  667. // throw away null bytes
  668. ReadData(ref index, data);
  669. }
  670. return res.ToString();
  671. }
  672. private static char ReadData(ref int index, string data) {
  673. if (index >= data.Length) throw Error("not enough data while reading");
  674. return data[index++];
  675. }
  676. #endregion
  677. #region Misc. Private APIs
  678. private static Exception Error(string msg) {
  679. return PythonExceptions.CreateThrowable(error, msg);
  680. }
  681. #endregion
  682. }
  683. }