PageRenderTime 29ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/DLR_Main/Languages/IronPython/IronPython.Modules/marshal.cs

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