PageRenderTime 43ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/DICK.B1/IronPython/Runtime/Bytes.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 935 lines | 704 code | 200 blank | 31 comment | 124 complexity | 47482886db3151ace68a4daa3f74b05b 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. * 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. #if !CLR2
  16. using System.Linq.Expressions;
  17. using System.Numerics;
  18. #else
  19. using Microsoft.Scripting.Ast;
  20. using Microsoft.Scripting.Math;
  21. #endif
  22. using System;
  23. using System.Collections;
  24. using System.Collections.Generic;
  25. using System.Reflection.Emit;
  26. using System.Runtime.InteropServices;
  27. using System.Text;
  28. using System.Threading;
  29. using Microsoft.Scripting.Runtime;
  30. using Microsoft.Scripting.Utils;
  31. using IronPython.Runtime.Operations;
  32. using IronPython.Runtime.Types;
  33. namespace IronPython.Runtime {
  34. [PythonType("bytes")]
  35. public class Bytes : IList<byte>, ICodeFormattable, IExpressionSerializable {
  36. internal byte[]/*!*/ _bytes;
  37. internal static Bytes/*!*/ Empty = new Bytes();
  38. public Bytes() {
  39. _bytes = new byte[0];
  40. }
  41. public Bytes([BytesConversion, NotNull]IList<byte>/*!*/ bytes) {
  42. _bytes = ArrayUtils.ToArray(bytes);
  43. }
  44. public Bytes([NotNull]List bytes) {
  45. _bytes = ByteOps.GetBytes(bytes, ByteOps.GetByteListOk).ToArray();
  46. }
  47. public Bytes(int size) {
  48. _bytes = new byte[size];
  49. }
  50. private Bytes(byte[] bytes) {
  51. _bytes = bytes;
  52. }
  53. public Bytes(CodeContext/*!*/ context, [NotNull]string/*!*/ unicode, [NotNull]string/*!*/ encoding) {
  54. _bytes = StringOps.encode(context, unicode, encoding, "strict").MakeByteArray();
  55. }
  56. internal static Bytes Make(byte[] bytes) {
  57. return new Bytes(bytes);
  58. }
  59. #region Public Python API surface
  60. public Bytes capitalize() {
  61. if (Count == 0) {
  62. return this;
  63. }
  64. return new Bytes(_bytes.Capitalize());
  65. }
  66. public Bytes/*!*/ center(int width) {
  67. return center(width, " ");
  68. }
  69. public Bytes/*!*/ center(int width, [NotNull]string/*!*/ fillchar) {
  70. List<byte> res = _bytes.TryCenter(width, fillchar.ToByte("center", 2));
  71. if (res == null) {
  72. return this;
  73. }
  74. return new Bytes(res);
  75. }
  76. public Bytes/*!*/ center(int width, [BytesConversion]IList<byte>/*!*/ fillchar) {
  77. List<byte> res = _bytes.TryCenter(width, fillchar.ToByte("center", 2));
  78. if (res == null) {
  79. return this;
  80. }
  81. return new Bytes(res);
  82. }
  83. // necessary to avoid bad conversion of List -> IList<Byte>
  84. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  85. public ByteArray/*!*/ center(int width, List fillchar) {
  86. throw PythonOps.TypeError("center() argument 2 must be byte, not list");
  87. }
  88. public int count([BytesConversion]IList<byte>/*!*/ sub) {
  89. return count(sub, 0, Count);
  90. }
  91. public int count([BytesConversion]IList<byte>/*!*/ sub, int start) {
  92. return count(sub, start, Count);
  93. }
  94. public int count([BytesConversion]IList<byte/*!*/> ssub, int start, int end) {
  95. IList<byte> bytes = _bytes;
  96. return _bytes.CountOf(ssub, start, end);
  97. }
  98. // overloads to avoid automatic generic conversion
  99. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  100. public int count(List/*!*/ sub) {
  101. throw PythonOps.TypeError("expected bytes or bytearray, got list");
  102. }
  103. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  104. public int count(List/*!*/ sub, int start) {
  105. throw PythonOps.TypeError("expected bytes or bytearray, got list");
  106. }
  107. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  108. public int count(List/*!*/ ssub, int start, int end) {
  109. throw PythonOps.TypeError("expected bytes or bytearray, got list");
  110. }
  111. public string decode(CodeContext/*!*/ context, [Optional]string/*!*/ encoding, [DefaultParameterValue("strict")][NotNull]string/*!*/ errors) {
  112. return StringOps.decode(context, _bytes.MakeString(), encoding, errors);
  113. }
  114. public bool endswith([BytesConversion]IList<byte>/*!*/ suffix) {
  115. return _bytes.EndsWith(suffix);
  116. }
  117. public bool endswith([BytesConversion]IList<byte>/*!*/ suffix, int start) {
  118. return _bytes.EndsWith(suffix, start);
  119. }
  120. public bool endswith([BytesConversion]IList<byte>/*!*/ suffix, int start, int end) {
  121. return _bytes.EndsWith(suffix, start, end);
  122. }
  123. // overloads to avoid automatic generic conversion
  124. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  125. public bool endswith(List/*!*/ suffix) {
  126. throw PythonOps.TypeError("expected bytes or bytearray, got list");
  127. }
  128. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  129. public bool endswith(List/*!*/ suffix, int start) {
  130. throw PythonOps.TypeError("expected bytes or bytearray, got list");
  131. }
  132. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  133. public bool endswith(List/*!*/ suffix, int start, int end) {
  134. throw PythonOps.TypeError("expected bytes or bytearray, got list");
  135. }
  136. public bool endswith(PythonTuple/*!*/ suffix) {
  137. return _bytes.EndsWith(suffix);
  138. }
  139. public bool endswith(PythonTuple/*!*/ suffix, int start) {
  140. return _bytes.EndsWith(suffix, start);
  141. }
  142. public bool endswith(PythonTuple/*!*/ suffix, int start, int end) {
  143. return _bytes.EndsWith(suffix, start, end);
  144. }
  145. public Bytes/*!*/ expandtabs() {
  146. return expandtabs(8);
  147. }
  148. public Bytes/*!*/ expandtabs(int tabsize) {
  149. return new Bytes(_bytes.ExpandTabs(tabsize));
  150. }
  151. public int find([BytesConversion]IList<byte>/*!*/ sub) {
  152. return _bytes.Find(sub);
  153. }
  154. public int find([BytesConversion]IList<byte>/*!*/ sub, int? start) {
  155. return _bytes.Find(sub, start);
  156. }
  157. public int find([BytesConversion]IList<byte>/*!*/ sub, int? start, int? end) {
  158. return _bytes.Find(sub, start, end);
  159. }
  160. public static Bytes/*!*/ fromhex(string/*!*/ @string) {
  161. return new Bytes(IListOfByteOps.FromHex(@string).ToArray());
  162. }
  163. public int index([BytesConversion]IList<byte>/*!*/ item) {
  164. return index(item, 0, Count);
  165. }
  166. public int index([BytesConversion]IList<byte>/*!*/ item, int? start) {
  167. return index(item, start, Count);
  168. }
  169. public int index([BytesConversion]IList<byte>/*!*/ item, int? start, int? stop) {
  170. int res = find(item, start, stop);
  171. if (res == -1) {
  172. throw PythonOps.ValueError("bytes.index(item): item not in bytes");
  173. }
  174. return res;
  175. }
  176. public bool isalnum() {
  177. return _bytes.IsAlphaNumeric();
  178. }
  179. public bool isalpha() {
  180. return _bytes.IsLetter();
  181. }
  182. public bool isdigit() {
  183. return _bytes.IsDigit();
  184. }
  185. public bool islower() {
  186. return _bytes.IsLower();
  187. }
  188. public bool isspace() {
  189. return _bytes.IsWhiteSpace();
  190. }
  191. /// <summary>
  192. /// return true if self is a titlecased string and there is at least one
  193. /// character in self; also, uppercase characters may only follow uncased
  194. /// characters (e.g. whitespace) and lowercase characters only cased ones.
  195. /// return false otherwise.
  196. /// </summary>
  197. public bool istitle() {
  198. return _bytes.IsTitle();
  199. }
  200. public bool isupper() {
  201. return _bytes.IsUpper();
  202. }
  203. /// <summary>
  204. /// Return a string which is the concatenation of the strings
  205. /// in the sequence seq. The separator between elements is the
  206. /// string providing this method
  207. /// </summary>
  208. public Bytes join(object/*!*/ sequence) {
  209. IEnumerator seq = PythonOps.GetEnumerator(sequence);
  210. if (!seq.MoveNext()) {
  211. return Empty;
  212. }
  213. // check if we have just a sequnce of just one value - if so just
  214. // return that value.
  215. object curVal = seq.Current;
  216. if (!seq.MoveNext()) {
  217. return JoinOne(curVal);
  218. }
  219. List<byte> ret = new List<byte>();
  220. ByteOps.AppendJoin(curVal, 0, ret);
  221. int index = 1;
  222. do {
  223. ret.AddRange(this);
  224. ByteOps.AppendJoin(seq.Current, index, ret);
  225. index++;
  226. } while (seq.MoveNext());
  227. return new Bytes(ret);
  228. }
  229. public Bytes join([NotNull]List/*!*/ sequence) {
  230. if (sequence.__len__() == 0) {
  231. return new Bytes();
  232. } else if (sequence.__len__() == 1) {
  233. return JoinOne(sequence[0]);
  234. }
  235. List<byte> ret = new List<byte>();
  236. ByteOps.AppendJoin(sequence._data[0], 0, ret);
  237. for (int i = 1; i < sequence._size; i++) {
  238. ret.AddRange(this);
  239. ByteOps.AppendJoin(sequence._data[i], i, ret);
  240. }
  241. return new Bytes(ret);
  242. }
  243. public Bytes ljust(int width) {
  244. return ljust(width, (byte)' ');
  245. }
  246. public Bytes ljust(int width, [NotNull]string/*!*/ fillchar) {
  247. return ljust(width, fillchar.ToByte("ljust", 2));
  248. }
  249. public Bytes ljust(int width, [BytesConversion]IList<byte>/*!*/ fillchar) {
  250. return ljust(width, fillchar.ToByte("ljust", 2));
  251. }
  252. private Bytes/*!*/ ljust(int width, byte fillchar) {
  253. int spaces = width - Count;
  254. if (spaces <= 0) {
  255. return this;
  256. }
  257. List<byte> ret = new List<byte>(width);
  258. ret.AddRange(_bytes);
  259. for (int i = 0; i < spaces; i++) {
  260. ret.Add(fillchar);
  261. }
  262. return new Bytes(ret);
  263. }
  264. public Bytes/*!*/ lower() {
  265. return new Bytes(_bytes.ToLower());
  266. }
  267. public Bytes/*!*/ lstrip() {
  268. List<byte> res = _bytes.LeftStrip();
  269. if (res == null) {
  270. return this;
  271. }
  272. return new Bytes(res);
  273. }
  274. public Bytes/*!*/ lstrip([BytesConversion]IList<byte> bytes) {
  275. lock (this) {
  276. List<byte> res = _bytes.LeftStrip(bytes);
  277. if (res == null) {
  278. return this;
  279. }
  280. return new Bytes(res);
  281. }
  282. }
  283. public PythonTuple partition([BytesConversion]IList<byte>/*!*/ sep) {
  284. if (sep == null) {
  285. throw PythonOps.TypeError("expected string, got NoneType");
  286. } else if (sep.Count == 0) {
  287. throw PythonOps.ValueError("empty separator");
  288. }
  289. object[] obj = new object[3] { Empty, Empty, Empty };
  290. if (Count != 0) {
  291. int index = find(sep);
  292. if (index == -1) {
  293. obj[0] = this;
  294. } else {
  295. obj[0] = new Bytes(_bytes.Substring(0, index));
  296. obj[1] = sep;
  297. obj[2] = new Bytes(_bytes.Substring(index + sep.Count, Count - index - sep.Count));
  298. }
  299. }
  300. return new PythonTuple(obj);
  301. }
  302. public Bytes replace([BytesConversion]IList<byte>/*!*/ old, [BytesConversion]IList<byte>/*!*/ new_) {
  303. if (old == null) {
  304. throw PythonOps.TypeError("expected bytes or bytearray, got NoneType");
  305. }
  306. return replace(old, new_, _bytes.Length);
  307. }
  308. public Bytes replace([BytesConversion]IList<byte>/*!*/ old, [BytesConversion]IList<byte>/*!*/ new_, int maxsplit) {
  309. if (old == null) {
  310. throw PythonOps.TypeError("expected bytes or bytearray, got NoneType");
  311. } else if (maxsplit == 0) {
  312. return this;
  313. }
  314. return new Bytes(_bytes.Replace(old, new_, maxsplit));
  315. }
  316. public int rfind([BytesConversion]IList<byte>/*!*/ sub) {
  317. return rfind(sub, 0, Count);
  318. }
  319. public int rfind([BytesConversion]IList<byte>/*!*/ sub, int? start) {
  320. return rfind(sub, start, Count);
  321. }
  322. public int rfind([BytesConversion]IList<byte>/*!*/ sub, int? start, int? end) {
  323. return _bytes.ReverseFind(sub, start, end);
  324. }
  325. public int rindex([BytesConversion]IList<byte>/*!*/ sub) {
  326. return rindex(sub, 0, Count);
  327. }
  328. public int rindex([BytesConversion]IList<byte>/*!*/ sub, int? start) {
  329. return rindex(sub, start, Count);
  330. }
  331. public int rindex([BytesConversion]IList<byte>/*!*/ sub, int? start, int? end) {
  332. int ret = rfind(sub, start, end);
  333. if (ret == -1) {
  334. throw PythonOps.ValueError("substring {0} not found in {1}", sub, this);
  335. }
  336. return ret;
  337. }
  338. public Bytes/*!*/ rjust(int width) {
  339. return rjust(width, (byte)' ');
  340. }
  341. public Bytes/*!*/ rjust(int width, [NotNull]string/*!*/ fillchar) {
  342. return rjust(width, fillchar.ToByte("rjust", 2));
  343. }
  344. public Bytes/*!*/ rjust(int width, [BytesConversion]IList<byte>/*!*/ fillchar) {
  345. return rjust(width, fillchar.ToByte("rjust", 2));
  346. }
  347. private Bytes/*!*/ rjust(int width, byte fillchar) {
  348. int spaces = width - Count;
  349. if (spaces <= 0) {
  350. return this;
  351. }
  352. List<byte> ret = new List<byte>(width);
  353. for (int i = 0; i < spaces; i++) {
  354. ret.Add(fillchar);
  355. }
  356. ret.AddRange(_bytes);
  357. return new Bytes(ret);
  358. }
  359. public PythonTuple/*!*/ rpartition([BytesConversion]IList<byte>/*!*/ sep) {
  360. if (sep == null) {
  361. throw PythonOps.TypeError("expected string, got NoneType");
  362. } else if (sep.Count == 0) {
  363. throw PythonOps.ValueError("empty separator");
  364. }
  365. object[] obj = new object[3] { Empty, Empty, Empty };
  366. if (Count != 0) {
  367. int index = rfind(sep);
  368. if (index == -1) {
  369. obj[2] = this;
  370. } else {
  371. obj[0] = new Bytes(_bytes.Substring(0, index));
  372. obj[1] = sep;
  373. obj[2] = new Bytes(_bytes.Substring(index + sep.Count, Count - index - sep.Count));
  374. }
  375. }
  376. return new PythonTuple(obj);
  377. }
  378. public List/*!*/ rsplit() {
  379. return _bytes.SplitInternal((byte[])null, -1, x => new Bytes(x));
  380. }
  381. public List/*!*/ rsplit([BytesConversion]IList<byte> sep) {
  382. return rsplit(sep, -1);
  383. }
  384. public List/*!*/ rsplit([BytesConversion]IList<byte> sep, int maxsplit) {
  385. return _bytes.RightSplit(sep, maxsplit, x => new Bytes(new List<byte>(x)));
  386. }
  387. public Bytes/*!*/ rstrip() {
  388. List<byte> res = _bytes.RightStrip();
  389. if (res == null) {
  390. return this;
  391. }
  392. return new Bytes(res);
  393. }
  394. public Bytes/*!*/ rstrip([BytesConversion]IList<byte> bytes) {
  395. lock (this) {
  396. List<byte> res = _bytes.RightStrip(bytes);
  397. if (res == null) {
  398. return this;
  399. }
  400. return new Bytes(res);
  401. }
  402. }
  403. public List/*!*/ split() {
  404. return _bytes.SplitInternal((byte[])null, -1, x => new Bytes(x));
  405. }
  406. public List/*!*/ split([BytesConversion]IList<byte> sep) {
  407. return split(sep, -1);
  408. }
  409. public List/*!*/ split([BytesConversion]IList<byte> sep, int maxsplit) {
  410. return _bytes.Split(sep, maxsplit, x => new Bytes(x));
  411. }
  412. public List/*!*/ splitlines() {
  413. return splitlines(false);
  414. }
  415. public List/*!*/ splitlines(bool keepends) {
  416. return _bytes.SplitLines(keepends, x => new Bytes(x));
  417. }
  418. public bool startswith([BytesConversion]IList<byte>/*!*/ prefix) {
  419. return _bytes.StartsWith(prefix);
  420. }
  421. public bool startswith([BytesConversion]IList<byte>/*!*/ prefix, int start) {
  422. int len = Count;
  423. if (start > len) return false;
  424. if (start < 0) {
  425. start += len;
  426. if (start < 0) start = 0;
  427. }
  428. return _bytes.Substring(start).StartsWith(prefix);
  429. }
  430. public bool startswith([BytesConversion]IList<byte>/*!*/ prefix, int start, int end) {
  431. return _bytes.StartsWith(prefix, start, end);
  432. }
  433. public bool startswith(PythonTuple/*!*/ prefix) {
  434. return _bytes.StartsWith(prefix);
  435. }
  436. public bool startswith(PythonTuple/*!*/ prefix, int start) {
  437. return _bytes.StartsWith(prefix, start);
  438. }
  439. public bool startswith(PythonTuple/*!*/ prefix, int start, int end) {
  440. return _bytes.StartsWith(prefix, start, end);
  441. }
  442. public Bytes/*!*/ strip() {
  443. List<byte> res = _bytes.Strip();
  444. if (res == null) {
  445. return this;
  446. }
  447. return new Bytes(res);
  448. }
  449. public Bytes/*!*/ strip([BytesConversion]IList<byte> chars) {
  450. lock (this) {
  451. List<byte> res = _bytes.Strip(chars);
  452. if (res == null) {
  453. return this;
  454. }
  455. return new Bytes(res);
  456. }
  457. }
  458. public Bytes/*!*/ swapcase() {
  459. return new Bytes(_bytes.SwapCase());
  460. }
  461. public Bytes/*!*/ title() {
  462. lock (this) {
  463. List<byte> res = _bytes.Title();
  464. if (res == null) {
  465. return this;
  466. }
  467. return new Bytes(res.ToArray());
  468. }
  469. }
  470. public Bytes/*!*/ translate([BytesConversion]IList<byte> table) {
  471. if (table == null) {
  472. return this;
  473. } else if (table.Count != 256) {
  474. throw PythonOps.ValueError("translation table must be 256 characters long");
  475. } else if (Count == 0) {
  476. return this;
  477. }
  478. return new Bytes(_bytes.Translate(table, null));
  479. }
  480. public Bytes/*!*/ translate([BytesConversion]IList<byte> table, [BytesConversion]IList<byte>/*!*/ deletechars) {
  481. if (deletechars == null) {
  482. throw PythonOps.TypeError("expected bytes or bytearray, got None");
  483. } else if (Count == 0) {
  484. return this;
  485. }
  486. return new Bytes(_bytes.Translate(table, deletechars));
  487. }
  488. public Bytes/*!*/ upper() {
  489. return new Bytes(_bytes.ToUpper());
  490. }
  491. public Bytes/*!*/ zfill(int width) {
  492. int spaces = width - Count;
  493. if (spaces <= 0) {
  494. return this;
  495. }
  496. return new Bytes(_bytes.ZeroFill(width, spaces));
  497. }
  498. public bool __contains__([BytesConversion]IList<byte> bytes) {
  499. return this.IndexOf(bytes, 0) != -1;
  500. }
  501. public bool __contains__(CodeContext/*!*/ context, int value) {
  502. if (!PythonContext.GetContext(context).PythonOptions.Python30) {
  503. throw PythonOps.TypeError("'in <bytes>' requires string or bytes as left operand, not int");
  504. }
  505. return IndexOf(value.ToByteChecked()) != -1;
  506. }
  507. public bool __contains__(CodeContext/*!*/ context, object value) {
  508. if (!PythonContext.GetContext(context).PythonOptions.Python30) {
  509. throw PythonOps.TypeError("'in <bytes>' requires string or bytes as left operand, not {0}", PythonTypeOps.GetName(value));
  510. }
  511. if (value is Extensible<int>) {
  512. return IndexOf(((Extensible<int>)value).Value.ToByteChecked()) != -1;
  513. } else if (value is BigInteger) {
  514. return IndexOf(((BigInteger)value).ToByteChecked()) != -1;
  515. } else if (value is Extensible<BigInteger>) {
  516. return IndexOf(((Extensible<BigInteger>)value).Value.ToByteChecked()) != -1;
  517. }
  518. // 3.0 error message
  519. throw PythonOps.TypeError("Type {0} doesn't support the buffer API", PythonTypeOps.GetOldName(value));
  520. }
  521. public PythonTuple __reduce__(CodeContext/*!*/ context) {
  522. return PythonTuple.MakeTuple(
  523. DynamicHelpers.GetPythonType(this),
  524. PythonTuple.MakeTuple(
  525. PythonOps.MakeString(this),
  526. "latin-1"
  527. ),
  528. GetType() == typeof(Bytes) ? null : ObjectOps.ReduceProtocol0(context, this)[2]
  529. );
  530. }
  531. public virtual string/*!*/ __repr__(CodeContext context) {
  532. return _bytes.BytesRepr();
  533. }
  534. public override string/*!*/ ToString() {
  535. return PythonOps.MakeString(this);
  536. }
  537. public static Bytes/*!*/ operator +(Bytes/*!*/ self, Bytes/*!*/ other) {
  538. if (self == null) {
  539. throw PythonOps.TypeError("expected bytes, got None");
  540. }
  541. List<byte> bytes;
  542. bytes = new List<byte>(self._bytes);
  543. bytes.AddRange(other._bytes);
  544. return new Bytes(bytes);
  545. }
  546. public static ByteArray/*!*/ operator +(Bytes/*!*/ self, ByteArray/*!*/ other) {
  547. List<byte> bytes;
  548. bytes = new List<byte>(self._bytes);
  549. lock (other) {
  550. bytes.AddRange(other);
  551. }
  552. return new ByteArray(bytes);
  553. }
  554. public static string/*!*/ operator +(Bytes/*!*/ self, string/*!*/ other) {
  555. return self.ToString() + other;
  556. }
  557. public static string/*!*/ operator +(string/*!*/ other, Bytes/*!*/ self) {
  558. return other + self.ToString();
  559. }
  560. public static Bytes/*!*/ operator *(Bytes/*!*/ x, int y) {
  561. if (y == 1) {
  562. return x;
  563. }
  564. return new Bytes(x._bytes.Multiply(y));
  565. }
  566. public static Bytes/*!*/ operator *(int x, Bytes/*!*/ y) {
  567. return y * x;
  568. }
  569. public static bool operator >(Bytes/*!*/ x, Bytes/*!*/ y) {
  570. if (y == null) {
  571. return true;
  572. }
  573. return x._bytes.Compare(y._bytes) > 0;
  574. }
  575. public static bool operator <(Bytes/*!*/ x, Bytes/*!*/ y) {
  576. if (y == null) {
  577. return false;
  578. }
  579. return x._bytes.Compare(y._bytes) < 0;
  580. }
  581. public static bool operator >=(Bytes/*!*/ x, Bytes/*!*/ y) {
  582. if (y == null) {
  583. return true;
  584. }
  585. return x._bytes.Compare(y._bytes) >= 0;
  586. }
  587. public static bool operator <=(Bytes/*!*/ x, Bytes/*!*/ y) {
  588. if (y == null) {
  589. return false;
  590. }
  591. return x._bytes.Compare(y._bytes) <= 0;
  592. }
  593. public object this[CodeContext/*!*/ context, int index] {
  594. get {
  595. byte res = _bytes[PythonOps.FixIndex(index, _bytes.Length)];
  596. if (PythonContext.GetContext(context).PythonOptions.Python30) {
  597. return (int)res;
  598. }
  599. return new Bytes(new byte[] { res });
  600. }
  601. [PythonHidden]
  602. set {
  603. throw new InvalidOperationException();
  604. }
  605. }
  606. public object this[BigInteger index] {
  607. get {
  608. int iVal;
  609. if (index.AsInt32(out iVal)) {
  610. return this[iVal];
  611. }
  612. throw PythonOps.IndexError("cannot fit long in index");
  613. }
  614. }
  615. public Bytes this[Slice slice] {
  616. get {
  617. List<byte> res = _bytes.Slice(slice);
  618. if (res == null) {
  619. return Empty;
  620. }
  621. return new Bytes(res.ToArray());
  622. }
  623. }
  624. #endregion
  625. #region Implementation Details
  626. private static Bytes/*!*/ JoinOne(object curVal) {
  627. if (!(curVal is IList<byte>)) {
  628. throw PythonOps.TypeError("can only join an iterable of bytes");
  629. }
  630. return curVal as Bytes ?? new Bytes(curVal as IList<byte>);
  631. }
  632. #endregion
  633. #region IList<byte> Members
  634. [PythonHidden]
  635. public int IndexOf(byte item) {
  636. for (int i = 0; i < _bytes.Length; i++) {
  637. if (_bytes[i] == item) {
  638. return i;
  639. }
  640. }
  641. return -1;
  642. }
  643. [PythonHidden]
  644. public void Insert(int index, byte item) {
  645. throw new InvalidOperationException();
  646. }
  647. [PythonHidden]
  648. public void RemoveAt(int index) {
  649. throw new InvalidOperationException();
  650. }
  651. byte IList<byte>.this[int index] {
  652. get {
  653. return _bytes[index];
  654. }
  655. set {
  656. throw new InvalidOperationException();
  657. }
  658. }
  659. #endregion
  660. #region ICollection<byte> Members
  661. [PythonHidden]
  662. public void Add(byte item) {
  663. throw new InvalidOperationException();
  664. }
  665. [PythonHidden]
  666. public void Clear() {
  667. throw new InvalidOperationException();
  668. }
  669. [PythonHidden]
  670. public bool Contains(byte item) {
  671. return ((IList<byte>)_bytes).Contains(item);
  672. }
  673. [PythonHidden]
  674. public void CopyTo(byte[] array, int arrayIndex) {
  675. _bytes.CopyTo(array, arrayIndex);
  676. }
  677. public int Count {
  678. [PythonHidden]
  679. get { return _bytes.Length; }
  680. }
  681. public bool IsReadOnly {
  682. [PythonHidden]
  683. get { return true; }
  684. }
  685. [PythonHidden]
  686. public bool Remove(byte item) {
  687. throw new InvalidOperationException();
  688. }
  689. #endregion
  690. #region IEnumerable<byte> Members
  691. [PythonHidden]
  692. public IEnumerator<byte>/*!*/ GetEnumerator() {
  693. return ((IEnumerable<byte>)_bytes).GetEnumerator();
  694. }
  695. #endregion
  696. #region IEnumerable Members
  697. System.Collections.IEnumerator/*!*/ System.Collections.IEnumerable.GetEnumerator() {
  698. return _bytes.GetEnumerator();
  699. }
  700. #endregion
  701. #region Equality Members
  702. public override bool Equals(object obj) {
  703. IList<byte> bytes = obj as IList<byte>;
  704. if (bytes != null) {
  705. return _bytes.Compare(bytes) == 0;
  706. }
  707. string s = obj as string;
  708. if (s == null) {
  709. Extensible<string> es = obj as Extensible<string>;
  710. if (es != null) {
  711. s = es.Value;
  712. }
  713. }
  714. if (s != null) {
  715. return ToString() == s;
  716. }
  717. return false;
  718. }
  719. public override int GetHashCode() {
  720. return ToString().GetHashCode();
  721. }
  722. #endregion
  723. #region IExpressionSerializable Members
  724. Expression IExpressionSerializable.CreateExpression() {
  725. return Expression.Call(
  726. typeof(PythonOps).GetMethod("MakeBytes"),
  727. Expression.NewArrayInit(
  728. typeof(byte),
  729. ArrayUtils.ConvertAll(_bytes, (b) => Expression.Constant(b))
  730. )
  731. );
  732. }
  733. #endregion
  734. }
  735. }