PageRenderTime 58ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/DICK.B1/IronPython.Modules/array.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 1314 lines | 1063 code | 220 blank | 31 comment | 197 complexity | 6c0963ba97e09e8330e5fda73d2b2b8c MD5 | raw file

Large files files are truncated, but you can click here to view the full 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. * dlr@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.Diagnostics;
  19. using System.IO;
  20. using System.Runtime.InteropServices;
  21. using System.Text;
  22. using IronPython.Runtime;
  23. using IronPython.Runtime.Operations;
  24. using IronPython.Runtime.Types;
  25. using Microsoft.Scripting;
  26. using Microsoft.Scripting.Runtime;
  27. using Microsoft.Scripting.Utils;
  28. using SpecialName = System.Runtime.CompilerServices.SpecialNameAttribute;
  29. using System.Reflection;
  30. #if CLR2
  31. using Microsoft.Scripting.Math;
  32. #else
  33. using System.Numerics;
  34. #endif
  35. [assembly: PythonModule("array", typeof(IronPython.Modules.ArrayModule))]
  36. namespace IronPython.Modules {
  37. public static class ArrayModule {
  38. public const string __doc__ = "Provides arrays for native data types. These can be used for compact storage or native interop via ctypes";
  39. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  40. public static readonly PythonType/*!*/ ArrayType = DynamicHelpers.GetPythonTypeFromType(typeof(array));
  41. [PythonType]
  42. public class array : IPythonArray, IEnumerable, IWeakReferenceable, ICollection, ICodeFormattable, IList<object>, IStructuralEquatable
  43. #if CLR2
  44. , IValueEquality
  45. #endif
  46. {
  47. private ArrayData _data;
  48. private char _typeCode;
  49. private WeakRefTracker _tracker;
  50. public array([BytesConversion]string type, [Optional]object initializer) {
  51. if (type == null || type.Length != 1) {
  52. throw PythonOps.TypeError("expected character, got {0}", PythonTypeOps.GetName(type));
  53. }
  54. _typeCode = type[0];
  55. _data = CreateData(_typeCode);
  56. if (initializer != Missing.Value) extend(initializer);
  57. }
  58. private array(char typeCode, ArrayData data) {
  59. _typeCode = typeCode;
  60. _data = data;
  61. }
  62. private static ArrayData CreateData(char typecode) {
  63. ArrayData data;
  64. switch (typecode) {
  65. case 'c': data = new ArrayData<char>(); break;
  66. case 'b': data = new ArrayData<sbyte>(); break;
  67. case 'B': data = new ArrayData<byte>(); break;
  68. case 'u': data = new ArrayData<char>(); break;
  69. case 'h': data = new ArrayData<short>(); break;
  70. case 'H': data = new ArrayData<ushort>(); break;
  71. case 'l':
  72. case 'i': data = new ArrayData<int>(); break;
  73. case 'L':
  74. case 'I': data = new ArrayData<uint>(); break;
  75. case 'f': data = new ArrayData<float>(); break;
  76. case 'd': data = new ArrayData<double>(); break;
  77. default:
  78. throw PythonOps.ValueError("Bad type code (expected one of 'c', 'b', 'B', 'u', 'H', 'h', 'i', 'I', 'l', 'L', 'f', 'd')");
  79. }
  80. return data;
  81. }
  82. [SpecialName]
  83. public array InPlaceAdd(array other) {
  84. if (typecode != other.typecode) throw PythonOps.TypeError("cannot add different typecodes");
  85. if (other._data.Length != 0) {
  86. extend(other);
  87. }
  88. return this;
  89. }
  90. public static array operator +(array self, array other) {
  91. if (self.typecode != other.typecode) throw PythonOps.TypeError("cannot add different typecodes");
  92. array res = new array(self.typecode, Missing.Value);
  93. foreach (object o in self) {
  94. res.append(o);
  95. }
  96. foreach (object o in other) {
  97. res.append(o);
  98. }
  99. return res;
  100. }
  101. [SpecialName]
  102. public array InPlaceMultiply(int value) {
  103. if (value <= 0) {
  104. _data.Clear();
  105. } else {
  106. List myData = tolist();
  107. for (int i = 0; i < (value - 1); i++) {
  108. extend(myData);
  109. }
  110. }
  111. return this;
  112. }
  113. public static array operator *(array array, int value) {
  114. if ((BigInteger)value * array.__len__() * array.itemsize > SysModule.maxsize) {
  115. throw PythonOps.MemoryError("");
  116. }
  117. if (value <= 0) {
  118. return new array(array.typecode, Missing.Value);
  119. }
  120. return new array(array._typeCode, array._data.Multiply(value));
  121. }
  122. public static array operator *(array array, BigInteger value) {
  123. int intValue;
  124. if (!value.AsInt32(out intValue)) {
  125. throw PythonOps.OverflowError("cannot fit 'long' into an index-sized integer");
  126. } else if (value * array.__len__() * array.itemsize > SysModule.maxsize) {
  127. throw PythonOps.MemoryError("");
  128. }
  129. return array * intValue;
  130. }
  131. public static array operator *(int value, array array) {
  132. return array * value;
  133. }
  134. public static array operator *(BigInteger value, array array) {
  135. return array * value;
  136. }
  137. public void append(object iterable) {
  138. _data.Append(iterable);
  139. }
  140. internal IntPtr GetArrayAddress() {
  141. return _data.GetAddress();
  142. }
  143. public PythonTuple buffer_info() {
  144. return PythonTuple.MakeTuple(
  145. _data.GetAddress().ToPython(),
  146. _data.Length
  147. );
  148. }
  149. public void byteswap() {
  150. Stream s = ToStream();
  151. byte[] bytes = new byte[s.Length];
  152. s.Read(bytes, 0, bytes.Length);
  153. byte[] tmp = new byte[itemsize];
  154. for (int i = 0; i < bytes.Length; i += itemsize) {
  155. for (int j = 0; j < itemsize; j++) {
  156. tmp[j] = bytes[i + j];
  157. }
  158. for (int j = 0; j < itemsize; j++) {
  159. bytes[i + j] = tmp[itemsize - (j + 1)];
  160. }
  161. }
  162. _data.Clear();
  163. MemoryStream ms = new MemoryStream(bytes);
  164. FromStream(ms);
  165. }
  166. public int count(object x) {
  167. if (x == null) return 0;
  168. return _data.Count(x);
  169. }
  170. public void extend(object iterable) {
  171. array pa = iterable as array;
  172. if (pa != null && typecode != pa.typecode) {
  173. throw PythonOps.TypeError("cannot extend with different typecode");
  174. }
  175. string str = iterable as string;
  176. if (str != null && _typeCode != 'u') {
  177. fromstring(str);
  178. return;
  179. }
  180. Bytes bytes = iterable as Bytes;
  181. if (bytes != null) {
  182. fromstring(bytes);
  183. return;
  184. }
  185. PythonBuffer buf = iterable as PythonBuffer;
  186. if (buf != null) {
  187. fromstring(buf);
  188. return;
  189. }
  190. IEnumerator ie = PythonOps.GetEnumerator(iterable);
  191. while (ie.MoveNext()) {
  192. append(ie.Current);
  193. }
  194. }
  195. public void fromlist(object iterable) {
  196. IEnumerator ie = PythonOps.GetEnumerator(iterable);
  197. List<object> items = new List<object>();
  198. while (ie.MoveNext()) {
  199. if (!_data.CanStore(ie.Current)) {
  200. throw PythonOps.TypeError("expected {0}, got {1}",
  201. DynamicHelpers.GetPythonTypeFromType(_data.StorageType).Name,
  202. DynamicHelpers.GetPythonType(ie.Current).Name);
  203. }
  204. items.Add(ie.Current);
  205. }
  206. extend(items);
  207. }
  208. public void fromfile(PythonFile f, int n) {
  209. int bytesNeeded = n * itemsize;
  210. string bytes = f.read(bytesNeeded);
  211. if (bytes.Length < bytesNeeded) throw PythonOps.EofError("file not large enough");
  212. fromstring(bytes);
  213. }
  214. public void fromstring([NotNull]Bytes b) {
  215. if ((b.Count % itemsize) != 0) throw PythonOps.ValueError("string length not a multiple of itemsize");
  216. FromStream(new MemoryStream(b._bytes, false));
  217. }
  218. public void fromstring([NotNull]string s) {
  219. if ((s.Length % itemsize) != 0) throw PythonOps.ValueError("string length not a multiple of itemsize");
  220. byte[] bytes = new byte[s.Length];
  221. for (int i = 0; i < bytes.Length; i++) {
  222. bytes[i] = checked((byte)s[i]);
  223. }
  224. MemoryStream ms = new MemoryStream(bytes);
  225. FromStream(ms);
  226. }
  227. public void fromstring([NotNull]PythonBuffer buf) {
  228. fromstring(buf.ToString());
  229. }
  230. public void fromunicode(CodeContext/*!*/ context, string s) {
  231. if (s == null) {
  232. throw PythonOps.TypeError("expected string");
  233. } else if (_typeCode != 'u') {
  234. throw PythonOps.ValueError("fromunicode() may only be called on type 'u' arrays");
  235. }
  236. ArrayData<char> data = (ArrayData<char>)_data;
  237. data.EnsureSize(data.Length + s.Length);
  238. for (int i = 0; i < s.Length; i++) {
  239. data.Data[i + data.Length] = s[i];
  240. }
  241. data.Length += s.Length;
  242. }
  243. public int index(object x) {
  244. if (x == null) throw PythonOps.ValueError("got None, expected value");
  245. int res = _data.Index(x);
  246. if (res == -1) throw PythonOps.ValueError("x not found");
  247. return res;
  248. }
  249. public void insert(int i, object x) {
  250. if (i > _data.Length) i = _data.Length;
  251. if (i < 0) i = _data.Length + i;
  252. if (i < 0) i = 0;
  253. _data.Insert(i, x);
  254. }
  255. public int itemsize {
  256. get {
  257. switch (_typeCode) {
  258. case 'c': // char
  259. case 'b': // signed byte
  260. case 'B': // unsigned byte
  261. case 'x': // pad byte
  262. case 's': // null-terminated string
  263. case 'p': // Pascal string
  264. return 1;
  265. case 'u': // unicode char
  266. case 'h': // signed short
  267. case 'H': // unsigned short
  268. return 2;
  269. case 'i': // signed int
  270. case 'I': // unsigned int
  271. case 'l': // signed long
  272. case 'L': // unsigned long
  273. case 'f': // float
  274. return 4;
  275. case 'P': // pointer
  276. return IntPtr.Size;
  277. case 'q': // signed long long
  278. case 'Q': // unsigned long long
  279. case 'd': // double
  280. return 8;
  281. default:
  282. return 0;
  283. }
  284. }
  285. }
  286. public object pop() {
  287. return pop(-1);
  288. }
  289. public object pop(int i) {
  290. i = PythonOps.FixIndex(i, _data.Length);
  291. object res = _data.GetData(i);
  292. _data.RemoveAt(i);
  293. return res;
  294. }
  295. public void read(PythonFile f, int n) {
  296. fromfile(f, n);
  297. }
  298. public void remove(object value) {
  299. if (value == null) throw PythonOps.ValueError("got None, expected value");
  300. _data.Remove(value);
  301. }
  302. public void reverse() {
  303. for (int index = 0; index < _data.Length / 2; index++) {
  304. int left = index, right = _data.Length - (index + 1);
  305. Debug.Assert(left != right);
  306. _data.Swap(left, right);
  307. }
  308. }
  309. public virtual object this[int index] {
  310. get {
  311. object val = _data.GetData(PythonOps.FixIndex(index, _data.Length));
  312. switch (_typeCode) {
  313. case 'b': return (int)(sbyte)val;
  314. case 'B': return (int)(byte)val;
  315. case 'c':
  316. case 'u': return new string((char)val, 1);
  317. case 'h': return (int)(short)val;
  318. case 'H': return (int)(ushort)val;
  319. case 'l': return val;
  320. case 'i': return val;
  321. case 'L': return (BigInteger)(uint)val;
  322. case 'I':
  323. return (BigInteger)(uint)val;
  324. case 'f': return (double)(float)val;
  325. case 'd': return val;
  326. default:
  327. throw PythonOps.ValueError("Bad type code (expected one of 'c', 'b', 'B', 'u', 'H', 'h', 'i', 'I', 'l', 'L', 'f', 'd')");
  328. }
  329. }
  330. set {
  331. _data.SetData(PythonOps.FixIndex(index, _data.Length), value);
  332. }
  333. }
  334. internal byte[] RawGetItem(int index) {
  335. MemoryStream ms = new MemoryStream();
  336. BinaryWriter bw = new BinaryWriter(ms);
  337. switch (_typeCode) {
  338. case 'c': bw.Write((byte)(char)_data.GetData(index)); break;
  339. case 'b': bw.Write((sbyte)_data.GetData(index)); break;
  340. case 'B': bw.Write((byte)_data.GetData(index)); break;
  341. case 'u': bw.Write((char)_data.GetData(index)); break;
  342. case 'h': bw.Write((short)_data.GetData(index)); break;
  343. case 'H': bw.Write((ushort)_data.GetData(index)); break;
  344. case 'l':
  345. case 'i': bw.Write((int)_data.GetData(index)); break;
  346. case 'L':
  347. case 'I': bw.Write((uint)_data.GetData(index)); break;
  348. case 'f': bw.Write((float)_data.GetData(index)); break;
  349. case 'd': bw.Write((double)_data.GetData(index)); break;
  350. }
  351. return ms.ToArray();
  352. }
  353. public void __delitem__(int index) {
  354. _data.RemoveAt(PythonOps.FixIndex(index, _data.Length));
  355. }
  356. public void __delitem__(Slice slice) {
  357. if (slice == null) throw PythonOps.TypeError("expected Slice, got None");
  358. int start, stop, step;
  359. // slice is sealed, indices can't be user code...
  360. slice.indices(_data.Length, out start, out stop, out step);
  361. if (step > 0 && (start >= stop)) return;
  362. if (step < 0 && (start <= stop)) return;
  363. if (step == 1) {
  364. int i = start;
  365. for (int j = stop; j < _data.Length; j++, i++) {
  366. _data.SetData(i, _data.GetData(j));
  367. }
  368. for (i = 0; i < stop - start; i++) {
  369. _data.RemoveAt(_data.Length - 1);
  370. }
  371. return;
  372. }
  373. if (step == -1) {
  374. int i = stop + 1;
  375. for (int j = start + 1; j < _data.Length; j++, i++) {
  376. _data.SetData(i, _data.GetData(j));
  377. }
  378. for (i = 0; i < stop - start; i++) {
  379. _data.RemoveAt(_data.Length - 1);
  380. }
  381. return;
  382. }
  383. if (step < 0) {
  384. // find "start" we will skip in the 1,2,3,... order
  385. int i = start;
  386. while (i > stop) {
  387. i += step;
  388. }
  389. i -= step;
  390. // swap start/stop, make step positive
  391. stop = start + 1;
  392. start = i;
  393. step = -step;
  394. }
  395. int curr, skip, move;
  396. // skip: the next position we should skip
  397. // curr: the next position we should fill in data
  398. // move: the next position we will check
  399. curr = skip = move = start;
  400. while (curr < stop && move < stop) {
  401. if (move != skip) {
  402. _data.SetData(curr++, _data.GetData(move));
  403. } else
  404. skip += step;
  405. move++;
  406. }
  407. while (stop < _data.Length) {
  408. _data.SetData(curr++, _data.GetData(stop++));
  409. }
  410. while (_data.Length > curr) {
  411. _data.RemoveAt(_data.Length - 1);
  412. }
  413. }
  414. public object this[Slice index] {
  415. get {
  416. if (index == null) throw PythonOps.TypeError("expected Slice, got None");
  417. int start, stop, step;
  418. index.indices(_data.Length, out start, out stop, out step);
  419. array pa = new array(new string(_typeCode, 1), Missing.Value);
  420. if (step < 0) {
  421. for (int i = start; i > stop; i += step) {
  422. pa._data.Append(_data.GetData(i));
  423. }
  424. } else {
  425. for (int i = start; i < stop; i += step) {
  426. pa._data.Append(_data.GetData(i));
  427. }
  428. }
  429. return pa;
  430. }
  431. set {
  432. if (index == null) throw PythonOps.TypeError("expected Slice, got None");
  433. CheckSliceAssignType(value);
  434. if (index.step != null) {
  435. if (Object.ReferenceEquals(value, this)) value = this.tolist();
  436. index.DoSliceAssign(SliceAssign, _data.Length, value);
  437. } else {
  438. int start, stop, step;
  439. index.indices(_data.Length, out start, out stop, out step);
  440. if (stop < start) {
  441. stop = start;
  442. }
  443. SliceNoStep(value, start, stop);
  444. }
  445. }
  446. }
  447. private void CheckSliceAssignType(object value) {
  448. array pa = value as array;
  449. if (pa == null) {
  450. throw PythonOps.TypeError("can only assign array (not \"{0}\") to array slice", PythonTypeOps.GetName(value));
  451. } else if (pa != null && pa._typeCode != _typeCode) {
  452. throw PythonOps.TypeError("bad argument type for built-in operation");
  453. }
  454. }
  455. private void SliceNoStep(object value, int start, int stop) {
  456. // replace between start & stop w/ values
  457. IEnumerator ie = PythonOps.GetEnumerator(value);
  458. int length = _data.Length;
  459. ArrayData newData = CreateData(_typeCode);
  460. for (int i = 0; i < start; i++) {
  461. newData.Append(_data.GetData(i));
  462. }
  463. while (ie.MoveNext()) {
  464. newData.Append(ie.Current);
  465. }
  466. for (int i = Math.Max(stop, start); i < _data.Length; i++) {
  467. newData.Append(_data.GetData(i));
  468. }
  469. _data = newData;
  470. }
  471. public object __getslice__(object start, object stop) {
  472. return this[new Slice(start, stop)];
  473. }
  474. public void __setslice__(int start, int stop, object value) {
  475. CheckSliceAssignType(value);
  476. Slice.FixSliceArguments(_data.Length, ref start, ref stop);
  477. SliceNoStep(value, start, stop);
  478. }
  479. public void __delslice__(object start, object stop) {
  480. __delitem__(new Slice(start, stop));
  481. }
  482. public PythonTuple __reduce__() {
  483. return PythonOps.MakeTuple(
  484. DynamicHelpers.GetPythonType(this),
  485. PythonOps.MakeTuple(
  486. typecode,
  487. ToByteArray().MakeString()
  488. ),
  489. null
  490. );
  491. }
  492. public array __copy__() {
  493. return new array(typecode, this);
  494. }
  495. public array __deepcopy__() {
  496. // we only have simple data so this is the same as a copy
  497. return __copy__();
  498. }
  499. public PythonTuple __reduce_ex__(int version) {
  500. return __reduce__();
  501. }
  502. public PythonTuple __reduce_ex__() {
  503. return __reduce__();
  504. }
  505. private void SliceAssign(int index, object value) {
  506. _data.SetData(index, value);
  507. }
  508. public void tofile(PythonFile f) {
  509. f.write(tostring());
  510. }
  511. public List tolist() {
  512. List res = new List();
  513. for (int i = 0; i < _data.Length; i++) {
  514. res.AddNoLock(this[i]);
  515. }
  516. return res;
  517. }
  518. public string tostring() {
  519. Stream s = ToStream();
  520. byte[] bytes = new byte[s.Length];
  521. s.Read(bytes, 0, (int)s.Length);
  522. StringBuilder res = new StringBuilder();
  523. for (int i = 0; i < bytes.Length; i++) {
  524. res.Append((char)bytes[i]);
  525. }
  526. return res.ToString();
  527. }
  528. public string tounicode(CodeContext/*!*/ context) {
  529. if (_typeCode != 'u') throw PythonOps.ValueError("only 'u' arrays can be converted to unicode");
  530. return new string(((ArrayData<char>)_data).Data, 0, _data.Length);
  531. }
  532. public void write(PythonFile f) {
  533. tofile(f);
  534. }
  535. public string/*!*/ typecode {
  536. get { return ScriptingRuntimeHelpers.CharToString(_typeCode); }
  537. }
  538. private abstract class ArrayData {
  539. public abstract void SetData(int index, object value);
  540. public abstract object GetData(int index);
  541. public abstract void Append(object value);
  542. public abstract int Count(object value);
  543. public abstract bool CanStore(object value);
  544. public abstract Type StorageType { get; }
  545. public abstract int Index(object value);
  546. public abstract void Insert(int index, object value);
  547. public abstract void Remove(object value);
  548. public abstract void RemoveAt(int index);
  549. public abstract int Length { get; set; }
  550. public abstract void Swap(int x, int y);
  551. public abstract void Clear();
  552. public abstract IntPtr GetAddress();
  553. public abstract ArrayData Multiply(int count);
  554. }
  555. internal MemoryStream ToStream() {
  556. MemoryStream ms = new MemoryStream();
  557. ToStream(ms);
  558. ms.Seek(0, SeekOrigin.Begin);
  559. return ms;
  560. }
  561. internal void ToStream(Stream ms) {
  562. BinaryWriter bw = new BinaryWriter(ms, Encoding.Unicode);
  563. for (int i = 0; i < _data.Length; i++) {
  564. switch (_typeCode) {
  565. case 'c': bw.Write((byte)(char)_data.GetData(i)); break;
  566. case 'b': bw.Write((sbyte)_data.GetData(i)); break;
  567. case 'B': bw.Write((byte)_data.GetData(i)); break;
  568. case 'u': bw.Write((char)_data.GetData(i)); break;
  569. case 'h': bw.Write((short)_data.GetData(i)); break;
  570. case 'H': bw.Write((ushort)_data.GetData(i)); break;
  571. case 'l':
  572. case 'i': bw.Write((int)_data.GetData(i)); break;
  573. case 'L':
  574. case 'I': bw.Write((uint)_data.GetData(i)); break;
  575. case 'f': bw.Write((float)_data.GetData(i)); break;
  576. case 'd': bw.Write((double)_data.GetData(i)); break;
  577. }
  578. }
  579. }
  580. internal byte[] ToByteArray() {
  581. return ToStream().ToArray();
  582. }
  583. internal void Clear() {
  584. _data = CreateData(_typeCode);
  585. }
  586. internal void FromStream(Stream ms) {
  587. BinaryReader br = new BinaryReader(ms);
  588. for (int i = 0; i < ms.Length / itemsize; i++) {
  589. object value;
  590. switch (_typeCode) {
  591. case 'c': value = (char)br.ReadByte(); break;
  592. case 'b': value = (sbyte)br.ReadByte(); break;
  593. case 'B': value = br.ReadByte(); break;
  594. case 'u': value = ReadBinaryChar(br); break;
  595. case 'h': value = br.ReadInt16(); break;
  596. case 'H': value = br.ReadUInt16(); break;
  597. case 'i': value = br.ReadInt32(); break;
  598. case 'I': value = br.ReadUInt32(); break;
  599. case 'l': value = br.ReadInt32(); break;
  600. case 'L': value = br.ReadUInt32(); break;
  601. case 'f': value = br.ReadSingle(); break;
  602. case 'd': value = br.ReadDouble(); break;
  603. default: throw new InvalidOperationException(); // should never happen
  604. }
  605. _data.Append(value);
  606. }
  607. }
  608. // a version of FromStream that overwrites starting at 'index'
  609. internal void FromStream(Stream ms, int index) {
  610. BinaryReader br = new BinaryReader(ms);
  611. for (int i = index; i < ms.Length / itemsize + index; i++) {
  612. object value;
  613. switch (_typeCode) {
  614. case 'c': value = (char)br.ReadByte(); break;
  615. case 'b': value = (sbyte)br.ReadByte(); break;
  616. case 'B': value = br.ReadByte(); break;
  617. case 'u': value = ReadBinaryChar(br); break;
  618. case 'h': value = br.ReadInt16(); break;
  619. case 'H': value = br.ReadUInt16(); break;
  620. case 'i': value = br.ReadInt32(); break;
  621. case 'I': value = br.ReadUInt32(); break;
  622. case 'l': value = br.ReadInt32(); break;
  623. case 'L': value = br.ReadUInt32(); break;
  624. case 'f': value = br.ReadSingle(); break;
  625. case 'd': value = br.ReadDouble(); break;
  626. default: throw new InvalidOperationException(); // should never happen
  627. }
  628. _data.SetData(i, value);
  629. }
  630. }
  631. // a version of FromStream that overwrites up to 'nbytes' bytes, starting at 'index'
  632. // Returns the number of bytes written.
  633. internal long FromStream(Stream ms, int index, int nbytes) {
  634. BinaryReader br = new BinaryReader(ms);
  635. if (nbytes <= 0) {
  636. return 0;
  637. }
  638. int len = Math.Min((int)(ms.Length - ms.Position), nbytes);
  639. for (int i = index; i < len / itemsize + index; i++) {
  640. object value;
  641. switch (_typeCode) {
  642. case 'c': value = (char)br.ReadByte(); break;
  643. case 'b': value = (sbyte)br.ReadByte(); break;
  644. case 'B': value = br.ReadByte(); break;
  645. case 'u':
  646. value = ReadBinaryChar(br);
  647. break;
  648. case 'h': value = br.ReadInt16(); break;
  649. case 'H': value = br.ReadUInt16(); break;
  650. case 'i': value = br.ReadInt32(); break;
  651. case 'I': value = br.ReadUInt32(); break;
  652. case 'l': value = br.ReadInt32(); break;
  653. case 'L': value = br.ReadUInt32(); break;
  654. case 'f': value = br.ReadSingle(); break;
  655. case 'd': value = br.ReadDouble(); break;
  656. default: throw new InvalidOperationException(); // should never happen
  657. }
  658. _data.SetData(i, value);
  659. }
  660. if (len % itemsize > 0) {
  661. // we have some extra bytes that we need to do a partial read on.
  662. byte[] curBytes = ToBytes(len / itemsize + index);
  663. for (int i = 0; i < len % itemsize; i++) {
  664. curBytes[i] = br.ReadByte();
  665. }
  666. _data.SetData(len / itemsize + index, FromBytes(curBytes));
  667. }
  668. return len;
  669. }
  670. // br.ReadChar() doesn't read 16-bit chars, it reads 8-bit chars.
  671. private static object ReadBinaryChar(BinaryReader br) {
  672. object value;
  673. byte byteVal = br.ReadByte();
  674. value = (char)((br.ReadByte() << 8) | byteVal);
  675. return value;
  676. }
  677. private byte[] ToBytes(int index) {
  678. switch(_typeCode) {
  679. case 'c': return new[] { (byte)(char)_data.GetData(index) };
  680. case 'b': return new[] { (byte)(sbyte)_data.GetData(index) };
  681. case 'B': return new[] { (byte)_data.GetData(index) };
  682. case 'u': return BitConverter.GetBytes((char)_data.GetData(index));
  683. case 'h': return BitConverter.GetBytes((short)_data.GetData(index));
  684. case 'H': return BitConverter.GetBytes((ushort)_data.GetData(index));
  685. case 'l':
  686. case 'i': return BitConverter.GetBytes((int)_data.GetData(index));
  687. case 'L':
  688. case 'I': return BitConverter.GetBytes((uint)_data.GetData(index));
  689. case 'f': return BitConverter.GetBytes((float)_data.GetData(index));
  690. case 'd': return BitConverter.GetBytes((double)_data.GetData(index));
  691. default:
  692. throw PythonOps.ValueError("Bad type code (expected one of 'c', 'b', 'B', 'u', 'H', 'h', 'i', 'I', 'l', 'L', 'f', 'd')");
  693. }
  694. }
  695. private object FromBytes(byte[] bytes) {
  696. switch (_typeCode) {
  697. case 'c': return (char)bytes[0];
  698. case 'b': return (sbyte)bytes[0];
  699. case 'B': return bytes[0];
  700. case 'u': return BitConverter.ToChar(bytes, 0);
  701. case 'h': return BitConverter.ToInt16(bytes, 0);
  702. case 'H': return BitConverter.ToUInt16(bytes, 0);
  703. case 'l':
  704. case 'i': return BitConverter.ToInt32(bytes, 0);
  705. case 'L':
  706. case 'I': return BitConverter.ToUInt32(bytes, 0);
  707. case 'f': return BitConverter.ToSingle(bytes, 0);
  708. case 'd': return BitConverter.ToDouble(bytes, 0);
  709. default:
  710. throw PythonOps.ValueError("Bad type code (expected one of 'c', 'b', 'B', 'u', 'H', 'h', 'i', 'I', 'l', 'L', 'f', 'd')");
  711. }
  712. }
  713. private class ArrayData<T> : ArrayData {
  714. private T[] _data;
  715. private int _count;
  716. private GCHandle? _dataHandle;
  717. public ArrayData() {
  718. GC.SuppressFinalize(this);
  719. _data = new T[8];
  720. }
  721. private ArrayData(int size) {
  722. GC.SuppressFinalize(this);
  723. _data = new T[size];
  724. _count = size;
  725. }
  726. ~ArrayData() {
  727. Debug.Assert(_dataHandle.HasValue);
  728. _dataHandle.Value.Free();
  729. }
  730. public T[] Data {
  731. get {
  732. return _data;
  733. }
  734. set {
  735. _data = value;
  736. }
  737. }
  738. public override object GetData(int index) {
  739. return _data[index];
  740. }
  741. public override void SetData(int index, object value) {
  742. _data[index] = GetValue(value);
  743. }
  744. private static T GetValue(object value) {
  745. if (!(value is T)) {
  746. object newVal;
  747. if (!Converter.TryConvert(value, typeof(T), out newVal)) {
  748. if (value != null && typeof(T).IsPrimitive && typeof(T) != typeof(char))
  749. throw PythonOps.OverflowError("couldn't convert {1} to {0}",
  750. DynamicHelpers.GetPythonTypeFromType(typeof(T)).Name,
  751. DynamicHelpers.GetPythonType(value).Name);
  752. throw PythonOps.TypeError("expected {0}, got {1}",
  753. DynamicHelpers.GetPythonTypeFromType(typeof(T)).Name,
  754. DynamicHelpers.GetPythonType(value).Name);
  755. }
  756. value = newVal;
  757. }
  758. return (T)value;
  759. }
  760. public override void Append(object value) {
  761. EnsureSize(_count + 1);
  762. _data[_count++] = GetValue(value);
  763. }
  764. public void EnsureSize(int size) {
  765. if (_data.Length < size) {
  766. Array.Resize(ref _data, _data.Length * 2);
  767. if (_dataHandle != null) {
  768. _dataHandle.Value.Free();
  769. _dataHandle = null;
  770. GC.SuppressFinalize(this);
  771. }
  772. }
  773. }
  774. public override int Count(object value) {
  775. T other = GetValue(value);
  776. int count = 0;
  777. for (int i = 0; i < _count; i++) {
  778. if (_data[i].Equals(other)) {
  779. count++;
  780. }
  781. }
  782. return count;
  783. }
  784. public override void Insert(int index, object value) {
  785. EnsureSize(_count + 1);
  786. if (index < _count) {
  787. Array.Copy(_data, index, _data, index + 1, _count - index);
  788. }
  789. _data[index] = GetValue(value);
  790. _count++;
  791. }
  792. public override int Index(object value) {
  793. T other = GetValue(value);
  794. for (int i = 0; i < _count; i++) {
  795. if (_data[i].Equals(other)) return i;
  796. }
  797. return -1;
  798. }
  799. public override void Remove(object value) {
  800. T other = GetValue(value);
  801. for (int i = 0; i < _count; i++) {
  802. if (_data[i].Equals(other)) {
  803. RemoveAt(i);
  804. return;
  805. }
  806. }
  807. throw PythonOps.ValueError("couldn't find value to remove");
  808. }
  809. public override void RemoveAt(int index) {
  810. _count--;
  811. if (index < _count) {
  812. Array.Copy(_data, index + 1, _data, index, _count - index);
  813. }
  814. }
  815. public override void Swap(int x, int y) {
  816. T temp = _data[x];
  817. _data[x] = _data[y];
  818. _data[y] = temp;
  819. }
  820. public override int Length {
  821. get {
  822. return _count;
  823. }
  824. set {
  825. _count = value;
  826. }
  827. }
  828. public override void Clear() {
  829. _count = 0;
  830. }
  831. public override bool CanStore(object value) {
  832. object tmp;
  833. if (!(value is T) && !Converter.TryConvert(value, typeof(T), out tmp))
  834. return false;
  835. return true;
  836. }
  837. public override Type StorageType {
  838. get { return typeof(T); }
  839. }
  840. public override IntPtr GetAddress() {
  841. // slightly evil to pin our data array but it's only used in rare
  842. // interop cases. If this becomes a problem we can move the allocation
  843. // onto the unmanaged heap if we have full trust via a different subclass
  844. // of ArrayData.
  845. if (!_dataHandle.HasValue) {
  846. _dataHandle = GCHandle.Alloc(_data, GCHandleType.Pinned);
  847. GC.ReRegisterForFinalize(this);
  848. }
  849. return _dataHandle.Value.AddrOfPinnedObject();
  850. }
  851. public override ArrayData Multiply(int count) {
  852. var res = new ArrayData<T>(count * _count);
  853. if (count != 0) {
  854. Array.Copy(_data, res._data, _count);
  855. int newCount = count * _count;
  856. int block = _count;
  857. int pos = _count;
  858. while (pos < newCount) {
  859. Array.Copy(res._data, 0, res._data, pos, Math.Min(block, newCount - pos));
  860. pos += block;
  861. block *= 2;
  862. }
  863. }
  864. return res;
  865. }
  866. }
  867. #region IValueEquality Members
  868. #if CLR2
  869. int IValueEquality.GetValueHashCode() {
  870. throw PythonOps.TypeError("unhashable type");
  871. }
  872. bool IValueEquality.ValueEquals(object other) {
  873. array pa = other as array;
  874. if (pa == null) return false;
  875. if (_data.Length != pa._data.Length) return false;
  876. for (int i = 0; i < _data.Length; i++) {
  877. if (!_data.GetData(i).Equals(pa._data.GetData(i))) {
  878. return false;
  879. }
  880. }
  881. return true;
  882. }
  883. #endif
  884. #endregion
  885. #region IStructuralEquatable Members
  886. public const object __hash__ = null;
  887. int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
  888. IStructuralEquatable dataTuple;
  889. switch(_typeCode) {
  890. case 'c': dataTuple = PythonTuple.MakeTuple(((ArrayData<char>)_data).Data); break;
  891. case 'b': dataTuple = PythonTuple.MakeTuple(((ArrayData<sbyte>)_data).Data); break;
  892. case 'B': dataTuple = PythonTuple.MakeTuple(((ArrayData<byte>)_data).Data); break;
  893. case 'u': dataTuple = PythonTuple.MakeTuple(((ArrayData<char>)_data).Data); break;
  894. case 'h': dataTuple = PythonTuple.MakeTuple(((ArrayData<short>)_data).Data); break;
  895. case 'H': dataTuple = PythonTuple.MakeTuple(((ArrayData<ushort>)_data).Data); break;
  896. case 'l':
  897. case 'i': dataTuple = PythonTuple.MakeTuple(((ArrayData<int>)_data).Data); break;
  898. case 'L':
  899. case 'I': dataTuple = PythonTuple.MakeTuple(((ArrayData<uint>)_data).Data); break;
  900. case 'f': dataTuple = PythonTuple.MakeTuple(((ArrayData<float>)_data).Data); break;
  901. case 'd': dataTuple = PythonTuple.MakeTuple(((ArrayData<double>)_data).Data); break;
  902. default:
  903. throw PythonOps.ValueError("Bad type code (expected one of 'c', 'b', 'B', 'u', 'H', 'h', 'i', 'I', 'l', 'L', 'f', 'd')");
  904. }
  905. return dataTuple.GetHashCode(comparer);
  906. }
  907. bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer) {
  908. array pa = other as array;
  909. if (pa == null) return false;
  910. if (_data.Length != pa._data.Length) return false;
  911. for (int i = 0; i < _data.Length; i++) {
  912. if (!comparer.Equals(_data.GetData(i), pa._data.GetData(i))) {
  913. return false;
  914. }
  915. }
  916. return true;
  917. }
  918. #endregion
  919. #region IEnumerable Members
  920. IEnumerator IEnumerable.GetEnumerator() {
  921. for (int i = 0; i < _data.Length; i++) {
  922. yield return _data.GetData(i);
  923. }
  924. }
  925. #endregion
  926. #region ICodeFormattable Members
  927. public virtual string/*!*/ __repr__(CodeContext/*!*/ context) {
  928. string res = "array('" + typecode.ToString() + "'";
  929. if (_data.Length == 0) {
  930. return res + ")";
  931. }
  932. StringBuilder sb = new StringBuilder(res);
  933. if (_typeCode == 'c' || _typeCode == 'u') {
  934. char quote = '\'';
  935. string s = new string(((ArrayData<char>)_data).Data, 0, _data.Length);
  936. if (s.IndexOf('\'') != -1 && s.IndexOf('\"') == -1) {
  937. quote = '\"';
  938. }
  939. if (_typeCode == 'u') {
  940. sb.Append(", u");
  941. } else {
  942. sb.Append(", ");
  943. }
  944. sb.Append(quote);
  945. bool isUnicode = false;
  946. sb.Append(StringOps.ReprEncode(s, quote, ref isUnicode));
  947. sb.Append(quote);
  948. sb.Append(")");
  949. } else {
  950. sb.Append(", [");
  951. for (int i = 0; i < _data.Length; i++) {
  952. if (i > 0) {
  953. sb.Append(", ");
  954. }
  955. sb.Append(PythonOps.Repr(context, this[i]));
  956. }
  957. sb.Append("])");
  958. }
  959. return sb.ToString();
  960. }
  961. #endregion
  962. #region IWeakReferenceable Members
  963. WeakRefTracker IWeakReferenceable.GetWeakRef() {
  964. return _tracker;
  965. }
  966. bool IWeakReferenceable.SetWeakRef(WeakRefTracker value) {
  967. _tracker = value;
  968. return true;
  969. }
  970. void IWeakReferenceable.SetFinalizer(WeakRefTracker value) {
  971. _tracker = value;
  972. }
  973. #endregion
  974. #region IPythonContainer Members
  975. public int __len__() {
  976. return _data.Length;
  977. }
  978. public bool __contains__(object value) {
  979. return _data.Index(value) != -1;
  980. }
  981. #endregion
  982. #region IRichComparable Members
  983. private bool TryCompare(object other, out int res) {
  984. array pa = other as array;
  985. if (pa == null || pa.typecode != typecode) {
  986. res = 0;
  987. return false;
  988. }
  989. if (pa._data.Length != _data.Length) {
  990. res = _data.Length - pa._data.Length;
  991. } else {
  992. res = 0;
  993. for (int i = 0; i < pa._data.Length && res == 0; i++) {
  994. res = PythonOps.Compare(_data.GetData(i), pa._data.GetData(i));
  995. }
  996. }
  997. return true;
  998. }
  999. [return: MaybeNotImplemented]
  1000. public static object operator >(array self, object other) {
  1001. int res;
  1002. if (!self.TryCompare(other, out res)) {
  1003. return NotImplementedType.Value;
  1004. }
  1005. return ScriptingRuntimeHelpers.BooleanToObject(res > 0);
  1006. }
  1007. [return: MaybeNotImplemented]
  1008. public static object operator <(array self, object other) {
  1009. int res;
  1010. if (!self.TryCompare(other, out res)) {
  1011. return NotImplementedType.Value;
  1012. }
  1013. return ScriptingRuntimeHelpers.BooleanToObject(res < 0);
  1014. }
  1015. [return: MaybeNotImplemented]
  1016. public static object operator >=(array self, object other) {
  1017. int res;
  1018. if (!self.TryCompare(other, out res)) {
  1019. return NotImplementedType.Value;
  1020. }
  1021. return ScriptingRuntimeHelpers.BooleanToObject(res >= 0);
  1022. }
  1023. [return: MaybeNotImplemented]
  1024. public static object operator <=(array self, object other) {
  1025. int res;
  1026. if (!self.TryCompare(other, out res)) {
  1027. return NotImplementedType.Value;
  1028. }
  1029. return ScriptingRuntimeHelpers.BooleanToObject(res <= 0);
  1030. }
  1031. #endregion
  1032. #region ICollection Members
  1033. void ICollection.CopyTo(Array array, int index) {
  1034. throw new NotImplementedException();
  1035. }
  1036. int ICollection.Count {
  1037. get { return __len__(); }
  1038. }
  1039. bool ICollection.IsSynchronized {
  1040. get { return false; }
  1041. }
  1042. object ICollection.SyncRoot {
  1043. get { return this; }
  1044. }
  1045. #endregion
  1046. #region IList

Large files files are truncated, but you can click here to view the full file