PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/IronPython/IronPython/Runtime/Bytes.cs

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