PageRenderTime 64ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 1ms

/DICK.B1/IronPython.Modules/marshal.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 788 lines | 619 code | 103 blank | 66 comment | 166 complexity | 149937435e5b3616eb1d0ebed8abdacd 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;
  17. using System.Collections.Generic;
  18. using System.Text;
  19. using IronPython.Runtime;
  20. using IronPython.Runtime.Exceptions;
  21. using IronPython.Runtime.Operations;
  22. using Microsoft.Scripting.Runtime;
  23. using Microsoft.Scripting.Utils;
  24. #if CLR2
  25. using Microsoft.Scripting.Math;
  26. using Complex = Microsoft.Scripting.Math.Complex64;
  27. #else
  28. using System.Numerics;
  29. #endif
  30. [assembly: PythonModule("marshal", typeof(IronPython.Modules.PythonMarshal))]
  31. namespace IronPython.Modules {
  32. public static class PythonMarshal {
  33. public const string __doc__ = "Provides functions for serializing and deserializing primitive data types.";
  34. #region Public marshal APIs
  35. public static void dump(object value, PythonFile/*!*/ file) {
  36. dump(value, file, version);
  37. }
  38. public static void dump(object value, PythonFile/*!*/ file, int version) {
  39. if (file == null) throw PythonOps.TypeError("expected file, found None");
  40. file.write(dumps(value, version));
  41. }
  42. public static object load(PythonFile/*!*/ file) {
  43. if (file == null) throw PythonOps.TypeError("expected file, found None");
  44. return BytesToObject(FileEnumerator(file));
  45. }
  46. public static object dumps(object value) {
  47. return dumps(value, version);
  48. }
  49. public static string dumps(object value, int version) {
  50. byte[] bytes = ObjectToBytes(value, version);
  51. StringBuilder sb = new StringBuilder(bytes.Length);
  52. for (int i = 0; i < bytes.Length; i++) {
  53. sb.Append((char)bytes[i]);
  54. }
  55. return sb.ToString();
  56. }
  57. public static object loads(string @string) {
  58. return BytesToObject(StringEnumerator(@string));
  59. }
  60. public const int version = 2;
  61. #endregion
  62. #region Implementation details
  63. private static byte[] ObjectToBytes(object o, int version) {
  64. MarshalWriter mw = new MarshalWriter(version);
  65. mw.WriteObject(o);
  66. return mw.GetBytes();
  67. }
  68. private static object BytesToObject(IEnumerator<byte> bytes) {
  69. MarshalReader mr = new MarshalReader(bytes);
  70. return mr.ReadObject();
  71. }
  72. private static IEnumerator<byte> FileEnumerator(PythonFile/*!*/ file) {
  73. for (; ; ) {
  74. string data = file.read(1);
  75. if (data.Length == 0) {
  76. yield break;
  77. }
  78. yield return (byte)data[0];
  79. }
  80. }
  81. private static IEnumerator<byte> StringEnumerator(string/*!*/ str) {
  82. for (int i = 0; i < str.Length; i++) {
  83. yield return (byte)str[i];
  84. }
  85. }
  86. /*********************************************************
  87. * Format
  88. *
  89. * Tuple: '(',int cnt,tuple items
  90. * List: '[',int cnt, list items
  91. * Dict: '{',key item, value item, '0' terminator
  92. * Int : 'i',4 bytes
  93. * float: 'f', 1 byte len, float in string
  94. * float: 'g', 8 bytes - float in binary form
  95. * BigInt: 'l', int encodingSize
  96. * if the value is negative then the size is negative
  97. * and needs to be subtracted from int.MaxValue
  98. *
  99. * the bytes are encoded in 15 bit multiples, a size of
  100. * 0 represents a value of zero.
  101. *
  102. * True: 'T'
  103. * False: 'F'
  104. * Float: 'f', str len, float in str
  105. * string: 't', int len, bytes (ascii)
  106. * string: 'u', int len, bytes (unicode)
  107. * string: 'R' <id> - refer to interned string
  108. * StopIteration: 'S'
  109. * None: 'N'
  110. * Long: 'I' followed by 8 bytes (little endian 64-bit value)
  111. * complex: 'x', byte len, real str, byte len, imag str
  112. * Buffer (array.array too, but they don't round trip): 's', int len, buffer bytes
  113. * code: 'c', more stuff...
  114. *
  115. */
  116. private class MarshalWriter {
  117. private readonly List<byte> _bytes;
  118. private readonly int _version;
  119. private readonly Dictionary<string, int> _strings;
  120. public MarshalWriter(int version) {
  121. _bytes = new List<byte>();
  122. _version = version;
  123. if (_version > 0) {
  124. _strings = new Dictionary<string, int>();
  125. }
  126. }
  127. public void WriteObject(object o) {
  128. List<object> infinite = PythonOps.GetReprInfinite();
  129. if (infinite.Contains(o)) throw PythonOps.ValueError("Marshaled data contains infinite cycle");
  130. int index = infinite.Count;
  131. infinite.Add(o);
  132. try {
  133. if (o == null) _bytes.Add((byte)'N');
  134. else if (o == ScriptingRuntimeHelpers.True) _bytes.Add((byte)'T');
  135. else if (o == ScriptingRuntimeHelpers.False) _bytes.Add((byte)'F');
  136. else if (o is string) WriteString(o as string);
  137. else if (o is int) WriteInt((int)o);
  138. else if (o is float) WriteFloat((float)o);
  139. else if (o is double) WriteFloat((double)o);
  140. else if (o is long) WriteLong((long)o);
  141. else if (o.GetType() == typeof(List)) WriteList(o);
  142. else if (o.GetType() == typeof(PythonDictionary)) WriteDict(o);
  143. else if (o.GetType() == typeof(PythonTuple)) WriteTuple(o);
  144. else if (o.GetType() == typeof(SetCollection)) WriteSet(o);
  145. else if (o.GetType() == typeof(FrozenSetCollection)) WriteFrozenSet(o);
  146. else if (o is BigInteger) WriteInteger((BigInteger)o);
  147. else if (o is Complex) WriteComplex((Complex)o);
  148. else if (o is PythonBuffer) WriteBuffer((PythonBuffer)o);
  149. else if (o == PythonExceptions.StopIteration) WriteStopIteration();
  150. else throw PythonOps.ValueError("unmarshallable object");
  151. } finally {
  152. infinite.RemoveAt(index);
  153. }
  154. }
  155. private void WriteFloat(float f) {
  156. if (_version > 1) {
  157. _bytes.Add((byte)'g');
  158. _bytes.AddRange(BitConverter.GetBytes((double)f));
  159. } else {
  160. _bytes.Add((byte)'f');
  161. WriteDoubleString(f);
  162. }
  163. }
  164. private void WriteFloat(double f) {
  165. if (_version > 1) {
  166. _bytes.Add((byte)'g');
  167. _bytes.AddRange(BitConverter.GetBytes(f));
  168. } else {
  169. _bytes.Add((byte)'f');
  170. WriteDoubleString(f);
  171. }
  172. }
  173. private void WriteDoubleString(double d) {
  174. string s = DoubleOps.__repr__(DefaultContext.Default, d);
  175. _bytes.Add((byte)s.Length);
  176. for (int i = 0; i < s.Length; i++) {
  177. _bytes.Add((byte)s[i]);
  178. }
  179. }
  180. private void WriteInteger(BigInteger val) {
  181. _bytes.Add((byte)'l');
  182. int wordCount = 0, dir;
  183. if (val < BigInteger.Zero) {
  184. val *= -1;
  185. dir = -1;
  186. } else {
  187. dir = 1;
  188. }
  189. List<byte> bytes = new List<byte>();
  190. while (val != BigInteger.Zero) {
  191. int word = (int)(val & 0x7FFF);
  192. val = val >> 15;
  193. bytes.Add((byte)(word & 0xFF));
  194. bytes.Add((byte)((word >> 8) & 0xFF));
  195. wordCount += dir;
  196. }
  197. WriteInt32(wordCount);
  198. _bytes.AddRange(bytes);
  199. }
  200. private void WriteBuffer(PythonBuffer b) {
  201. _bytes.Add((byte)'s');
  202. List<byte> newBytes = new List<byte>();
  203. for (int i = 0; i < b.Size; i++) {
  204. if (b[i] is string) {
  205. string str = b[i] as string;
  206. byte[] utfBytes = Encoding.UTF8.GetBytes(str);
  207. if (utfBytes.Length != str.Length) {
  208. newBytes.AddRange(utfBytes);
  209. } else {
  210. byte[] strBytes = PythonAsciiEncoding.Instance.GetBytes(str);
  211. newBytes.AddRange(strBytes);
  212. }
  213. } else {
  214. newBytes.Add((byte)b[i]);
  215. }
  216. }
  217. WriteInt32(newBytes.Count);
  218. _bytes.AddRange(newBytes);
  219. }
  220. private void WriteLong(long l) {
  221. _bytes.Add((byte)'I');
  222. for (int i = 0; i < 8; i++) {
  223. _bytes.Add((byte)(l & 0xff));
  224. l = l >> 8;
  225. }
  226. }
  227. private void WriteComplex(Complex val) {
  228. _bytes.Add((byte)'x');
  229. WriteDoubleString(val.Real);
  230. WriteDoubleString(val.Imaginary());
  231. }
  232. private void WriteStopIteration() {
  233. _bytes.Add((byte)'S');
  234. }
  235. private void WriteInt(int val) {
  236. _bytes.Add((byte)'i');
  237. WriteInt32(val);
  238. }
  239. private void WriteInt32(int val) {
  240. _bytes.Add((byte)(val & 0xff));
  241. _bytes.Add((byte)((val >> 8) & 0xff));
  242. _bytes.Add((byte)((val >> 16) & 0xff));
  243. _bytes.Add((byte)((val >> 24) & 0xff));
  244. }
  245. private void WriteString(string s) {
  246. byte[] utfBytes = Encoding.UTF8.GetBytes(s);
  247. if (utfBytes.Length != s.Length) {
  248. _bytes.Add((byte)'u');
  249. WriteInt32(utfBytes.Length);
  250. for (int i = 0; i < utfBytes.Length; i++) {
  251. _bytes.Add(utfBytes[i]);
  252. }
  253. } else {
  254. int index;
  255. if (_strings != null && _strings.TryGetValue(s, out index)) {
  256. _bytes.Add((byte)'R');
  257. WriteInt32(index);
  258. } else {
  259. byte[] strBytes = PythonAsciiEncoding.Instance.GetBytes(s);
  260. if (_strings != null) {
  261. _bytes.Add((byte)'t');
  262. } else {
  263. _bytes.Add((byte)'s');
  264. }
  265. WriteInt32(strBytes.Length);
  266. for (int i = 0; i < strBytes.Length; i++) {
  267. _bytes.Add(strBytes[i]);
  268. }
  269. if (_strings != null) {
  270. _strings[s] = _strings.Count;
  271. }
  272. }
  273. }
  274. }
  275. private void WriteList(object o) {
  276. List l = o as List;
  277. _bytes.Add((byte)'[');
  278. WriteInt32(l.__len__());
  279. for (int i = 0; i < l.__len__(); i++) {
  280. WriteObject(l[i]);
  281. }
  282. }
  283. private void WriteDict(object o) {
  284. PythonDictionary d = o as PythonDictionary;
  285. _bytes.Add((byte)'{');
  286. IEnumerator<KeyValuePair<object, object>> ie = ((IEnumerable<KeyValuePair<object, object>>)d).GetEnumerator();
  287. while (ie.MoveNext()) {
  288. WriteObject(ie.Current.Key);
  289. WriteObject(ie.Current.Value);
  290. }
  291. _bytes.Add((byte)'0');
  292. }
  293. private void WriteTuple(object o) {
  294. PythonTuple t = o as PythonTuple;
  295. _bytes.Add((byte)'(');
  296. WriteInt32(t.__len__());
  297. for (int i = 0; i < t.__len__(); i++) {
  298. WriteObject(t[i]);
  299. }
  300. }
  301. private void WriteSet(object set) {
  302. SetCollection s = set as SetCollection;
  303. _bytes.Add((byte)'<');
  304. WriteInt32(s.__len__());
  305. foreach(object o in s) {
  306. WriteObject(o);
  307. }
  308. }
  309. private void WriteFrozenSet(object set) {
  310. FrozenSetCollection s = set as FrozenSetCollection;
  311. _bytes.Add((byte)'>');
  312. WriteInt32(s.__len__());
  313. foreach (object o in s) {
  314. WriteObject(o);
  315. }
  316. }
  317. public byte[] GetBytes() {
  318. return _bytes.ToArray();
  319. }
  320. }
  321. private class MarshalReader {
  322. private IEnumerator<byte> _myBytes;
  323. private Stack<ProcStack> _stack;
  324. private readonly Dictionary<int, string> _strings;
  325. private object _result;
  326. public MarshalReader(IEnumerator<byte> bytes) {
  327. _myBytes = bytes;
  328. _strings = new Dictionary<int, string>();
  329. }
  330. public object ReadObject() {
  331. while (_myBytes.MoveNext()) {
  332. byte cur = _myBytes.Current;
  333. object res;
  334. switch ((char)cur) {
  335. case '(': PushStack(StackType.Tuple); break;
  336. case '[': PushStack(StackType.List); break;
  337. case '{': PushStack(StackType.Dict); break;
  338. case '<': PushStack(StackType.Set); break;
  339. case '>': PushStack(StackType.FrozenSet); break;
  340. case '0':
  341. // end of dictionary
  342. if (_stack == null || _stack.Count == 0) {
  343. throw PythonOps.ValueError("bad marshal data");
  344. }
  345. _stack.Peek().StackCount = 0;
  346. break;
  347. // case 'c': break;
  348. default:
  349. res = YieldSimple();
  350. if (_stack == null) {
  351. return res;
  352. }
  353. do {
  354. res = UpdateStack(res);
  355. } while (res != null && _stack.Count > 0);
  356. if (_stack.Count == 0) {
  357. return _result;
  358. }
  359. continue;
  360. }
  361. // handle empty lists/tuples...
  362. if (_stack != null && _stack.Count > 0 && _stack.Peek().StackCount == 0) {
  363. ProcStack ps = _stack.Pop();
  364. res = ps.StackObj;
  365. if (ps.StackType == StackType.Tuple) {
  366. res = PythonTuple.Make(res);
  367. } else if (ps.StackType == StackType.FrozenSet) {
  368. res = FrozenSetCollection.Make(res);
  369. }
  370. if (_stack.Count > 0) {
  371. // empty list/tuple
  372. do {
  373. res = UpdateStack(res);
  374. } while (res != null && _stack.Count > 0);
  375. if (_stack.Count == 0) break;
  376. } else {
  377. _result = res;
  378. break;
  379. }
  380. }
  381. }
  382. return _result;
  383. }
  384. private void PushStack(StackType type) {
  385. ProcStack newStack = new ProcStack();
  386. newStack.StackType = type;
  387. switch (type) {
  388. case StackType.Dict:
  389. newStack.StackObj = new PythonDictionary();
  390. newStack.StackCount = -1;
  391. break;
  392. case StackType.List:
  393. newStack.StackObj = new List();
  394. newStack.StackCount = ReadInt32();
  395. break;
  396. case StackType.Tuple:
  397. newStack.StackCount = ReadInt32();
  398. newStack.StackObj = new List<object>(newStack.StackCount);
  399. break;
  400. case StackType.Set:
  401. newStack.StackObj = new SetCollection();
  402. newStack.StackCount = ReadInt32();
  403. break;
  404. case StackType.FrozenSet:
  405. newStack.StackCount = ReadInt32();
  406. newStack.StackObj = new List<object>(newStack.StackCount);
  407. break;
  408. }
  409. if (_stack == null) _stack = new Stack<ProcStack>();
  410. _stack.Push(newStack);
  411. }
  412. private object UpdateStack(object res) {
  413. ProcStack curStack = _stack.Peek();
  414. switch (curStack.StackType) {
  415. case StackType.Dict:
  416. PythonDictionary od = curStack.StackObj as PythonDictionary;
  417. if (curStack.HaveKey) {
  418. od[curStack.Key] = res;
  419. curStack.HaveKey = false;
  420. } else {
  421. curStack.HaveKey = true;
  422. curStack.Key = res;
  423. }
  424. break;
  425. case StackType.Tuple:
  426. List<object> objs = curStack.StackObj as List<object>;
  427. objs.Add(res);
  428. curStack.StackCount--;
  429. if (curStack.StackCount == 0) {
  430. _stack.Pop();
  431. object tuple = PythonTuple.Make(objs);
  432. if (_stack.Count == 0) {
  433. _result = tuple;
  434. }
  435. return tuple;
  436. }
  437. break;
  438. case StackType.List:
  439. List ol = curStack.StackObj as List;
  440. ol.AddNoLock(res);
  441. curStack.StackCount--;
  442. if (curStack.StackCount == 0) {
  443. _stack.Pop();
  444. if (_stack.Count == 0) {
  445. _result = ol;
  446. }
  447. return ol;
  448. }
  449. break;
  450. case StackType.Set:
  451. SetCollection os = curStack.StackObj as SetCollection;
  452. os.add(res);
  453. curStack.StackCount--;
  454. if (curStack.StackCount == 0) {
  455. _stack.Pop();
  456. if (_stack.Count == 0) {
  457. _result = os;
  458. }
  459. return os;
  460. }
  461. break;
  462. case StackType.FrozenSet:
  463. List<object> ofs = curStack.StackObj as List<object>;
  464. ofs.Add(res);
  465. curStack.StackCount--;
  466. if (curStack.StackCount == 0) {
  467. _stack.Pop();
  468. object frozenSet = FrozenSetCollection.Make(ofs);
  469. if (_stack.Count == 0) {
  470. _result = frozenSet;
  471. }
  472. return frozenSet;
  473. }
  474. break;
  475. }
  476. return null;
  477. }
  478. private enum StackType {
  479. Tuple,
  480. Dict,
  481. List,
  482. Set,
  483. FrozenSet
  484. }
  485. private class ProcStack {
  486. public StackType StackType;
  487. public object StackObj;
  488. public int StackCount;
  489. public bool HaveKey;
  490. public object Key;
  491. }
  492. private object YieldSimple() {
  493. object res;
  494. switch ((char)_myBytes.Current) {
  495. // simple ops to be read in
  496. case 'i': res = ReadInt(); break;
  497. case 'l': res = ReadBigInteger(); break;
  498. case 'T': res = ScriptingRuntimeHelpers.True; break;
  499. case 'F': res = ScriptingRuntimeHelpers.False; break;
  500. case 'f': res = ReadFloat(); break;
  501. case 't': res = ReadAsciiString(); break;
  502. case 'u': res = ReadUnicodeString(); break;
  503. case 'S': res = PythonExceptions.StopIteration; break;
  504. case 'N': res = null; break;
  505. case 'x': res = ReadComplex(); break;
  506. case 's': res = ReadBuffer(); break;
  507. case 'I': res = ReadLong(); break;
  508. case 'R': res = _strings[ReadInt32()]; break;
  509. case 'g': res = ReadBinaryFloat(); break;
  510. default: throw PythonOps.ValueError("bad marshal data");
  511. }
  512. return res;
  513. }
  514. private byte[] ReadBytes(int len) {
  515. byte[] bytes = new byte[len];
  516. for (int i = 0; i < len; i++) {
  517. if (!_myBytes.MoveNext()) {
  518. throw PythonOps.ValueError("bad marshal data");
  519. }
  520. bytes[i] = _myBytes.Current;
  521. }
  522. return bytes;
  523. }
  524. private int ReadInt32() {
  525. byte[] intBytes = ReadBytes(4);
  526. int res = intBytes[0] |
  527. (intBytes[1] << 8) |
  528. (intBytes[2] << 16) |
  529. (intBytes[3] << 24);
  530. return res;
  531. }
  532. private double ReadFloatStr() {
  533. MoveNext();
  534. string str = DecodeString(PythonAsciiEncoding.Instance, ReadBytes(_myBytes.Current));
  535. double res = 0;
  536. if (double.TryParse(str, out res)) {
  537. return res;
  538. }
  539. return 0;
  540. }
  541. private void MoveNext() {
  542. if (!_myBytes.MoveNext()) {
  543. throw PythonOps.EofError("EOF read where object expected");
  544. }
  545. }
  546. private string DecodeString(Encoding enc, byte[] bytes) {
  547. return enc.GetString(bytes, 0, bytes.Length);
  548. }
  549. object ReadInt() {
  550. // bytes not present are treated as being -1
  551. byte b1, b2, b3, b4;
  552. b1 = ReadIntPart();
  553. b2 = ReadIntPart();
  554. b3 = ReadIntPart();
  555. b4 = ReadIntPart();
  556. byte[] bytes = new byte[] { b1, b2, b3, b4 };
  557. return ScriptingRuntimeHelpers.Int32ToObject(BitConverter.ToInt32(bytes, 0));
  558. //return Ops.int2object(b1 | (b2 << 8) | (b3 << 16) | (b4 << 24));
  559. }
  560. private byte ReadIntPart() {
  561. byte b;
  562. if (_myBytes.MoveNext()) {
  563. b = _myBytes.Current;
  564. } else {
  565. b = 255;
  566. }
  567. return b;
  568. }
  569. object ReadFloat() {
  570. return ReadFloatStr();
  571. }
  572. private object ReadBinaryFloat() {
  573. return BitConverter.ToDouble(ReadBytes(8), 0);
  574. }
  575. private object ReadAsciiString() {
  576. string res = DecodeString(PythonAsciiEncoding.Instance, ReadBytes(ReadInt32()));
  577. _strings[_strings.Count] = res;
  578. return res;
  579. }
  580. private object ReadUnicodeString() {
  581. return DecodeString(Encoding.UTF8, ReadBytes(ReadInt32()));
  582. }
  583. private object ReadComplex() {
  584. double real = ReadFloatStr();
  585. double imag = ReadFloatStr();
  586. return new Complex(real, imag);
  587. }
  588. private object ReadBuffer() {
  589. return DecodeString(Encoding.UTF8, ReadBytes(ReadInt32()));
  590. }
  591. private object ReadLong() {
  592. byte[] bytes = ReadBytes(8);
  593. long res = 0;
  594. for (int i = 0; i < 8; i++) {
  595. res |= (((long)bytes[i]) << (i * 8));
  596. }
  597. return res;
  598. }
  599. private object ReadBigInteger() {
  600. int encodingSize = ReadInt32();
  601. if (encodingSize == 0) {
  602. return BigInteger.Zero;
  603. }
  604. int sign = 1;
  605. if (encodingSize < 0) {
  606. sign = -1;
  607. encodingSize *= -1;
  608. }
  609. int len = encodingSize * 2;
  610. byte[] bytes = ReadBytes(len);
  611. #if CLR2
  612. // first read the values in shorts so we can work
  613. // with them as 15-bit bytes easier...
  614. short[] shData = new short[encodingSize];
  615. for (int i = 0; i < shData.Length; i++) {
  616. shData[i] = (short)(bytes[i * 2] | (bytes[1 + i * 2] << 8));
  617. }
  618. // then convert the short's into BigInteger's 32-bit
  619. // format.
  620. uint[] numData = new uint[(shData.Length + 1) / 2];
  621. int bitWriteIndex = 0, shortIndex = 0, bitReadIndex = 0;
  622. while (shortIndex < shData.Length) {
  623. short val = shData[shortIndex];
  624. int shift = bitWriteIndex % 32;
  625. if (bitReadIndex != 0) {
  626. // we're read some bits, mask them off
  627. // and adjust the shift.
  628. int maskOff = ~((1 << bitReadIndex) - 1);
  629. val = (short)(val & maskOff);
  630. shift -= bitReadIndex;
  631. }
  632. // write the value into numData
  633. if (shift < 0) {
  634. numData[bitWriteIndex / 32] |= (uint)(val >> (shift * -1));
  635. } else {
  636. numData[bitWriteIndex / 32] |= (uint)(val << shift);
  637. }
  638. // and advance our indices
  639. if ((bitWriteIndex % 32) <= 16) {
  640. bitWriteIndex += (15 - bitReadIndex);
  641. bitReadIndex = 0;
  642. shortIndex++;
  643. } else {
  644. bitReadIndex = (32 - (bitWriteIndex % 32));
  645. bitWriteIndex += bitReadIndex;
  646. }
  647. }
  648. // and finally pass the data onto the big integer.
  649. return new BigInteger(sign, numData);
  650. #else
  651. // re-pack our 15-bit values into bytes
  652. byte[] data = new byte[bytes.Length];
  653. for (int bytesIndex = 0, dataIndex = 0, shift = 0; bytesIndex < len; bytesIndex++) {
  654. // write 8 bits
  655. if (shift == 0) {
  656. data[dataIndex] = bytes[bytesIndex];
  657. } else {
  658. data[dataIndex] = (byte)((bytes[bytesIndex] >> shift) | (bytes[bytesIndex + 1] << (8 - shift)));
  659. }
  660. //done
  661. dataIndex++;
  662. bytesIndex++;
  663. if (shift == 7) {
  664. shift = 0;
  665. continue;
  666. }
  667. // write 7 bits
  668. if (bytesIndex < len - 1) {
  669. data[dataIndex] = (byte)((bytes[bytesIndex] >> shift) | (bytes[bytesIndex + 1] << (7 - shift)));
  670. } else {
  671. data[dataIndex] = (byte)(bytes[bytesIndex] >> shift);
  672. }
  673. //done
  674. dataIndex++;
  675. shift++;
  676. }
  677. // and finally pass the data onto the big integer.
  678. BigInteger res = new BigInteger(data);
  679. return sign < 0 ? -res : res;
  680. #endif
  681. }
  682. }
  683. #endregion
  684. }
  685. }