PageRenderTime 51ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/Languages/IronPython/IronPython/Runtime/ByteArray.cs

http://github.com/IronLanguages/main
C# | 1527 lines | 1189 code | 278 blank | 60 comment | 220 complexity | bd729bf50eb6af05572b113d42681672 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. using System.Collections;
  16. using System.Collections.Generic;
  17. using System.Runtime.CompilerServices;
  18. using System.Runtime.InteropServices;
  19. using Microsoft.Scripting;
  20. using Microsoft.Scripting.Runtime;
  21. using Microsoft.Scripting.Utils;
  22. using IronPython.Runtime.Operations;
  23. using IronPython.Runtime.Types;
  24. #if FEATURE_NUMERICS
  25. using System.Numerics;
  26. #else
  27. using Microsoft.Scripting.Math;
  28. #endif
  29. namespace IronPython.Runtime {
  30. /// <summary>
  31. /// bytearray(string, encoding[, errors]) -> bytearray
  32. /// bytearray(iterable) -> bytearray
  33. ///
  34. /// Construct a mutable bytearray object from:
  35. /// - an iterable yielding values in range(256), including:
  36. /// + a list of integer values
  37. /// + a bytes, bytearray, buffer, or array object
  38. /// - a text string encoded using the specified encoding
  39. ///
  40. /// bytearray([int]) -> bytearray
  41. ///
  42. /// Construct a zero-ititialized bytearray of the specified length.
  43. /// (default=0)
  44. /// </summary>
  45. [PythonType("bytearray")]
  46. public class ByteArray : IList<byte>, ICodeFormattable, IBufferProtocol
  47. #if CLR2
  48. , IValueEquality
  49. #endif
  50. {
  51. internal List<byte>/*!*/ _bytes;
  52. public ByteArray() {
  53. _bytes = new List<byte>(0);
  54. }
  55. internal ByteArray(List<byte> bytes) {
  56. _bytes = bytes;
  57. }
  58. internal ByteArray (byte[] bytes) {
  59. _bytes = new List<byte>(bytes);
  60. }
  61. public void __init__() {
  62. _bytes = new List<byte>();
  63. }
  64. public void __init__(int source) {
  65. _bytes = new List<byte>(source);
  66. for (int i = 0; i < source; i++) {
  67. _bytes.Add(0);
  68. }
  69. }
  70. public void __init__(BigInteger source) {
  71. __init__((int)source);
  72. }
  73. public void __init__([NotNull]IList<byte>/*!*/ source) {
  74. _bytes = new List<byte>(source);
  75. }
  76. public void __init__(object source) {
  77. __init__(GetBytes(source));
  78. }
  79. public void __init__(CodeContext/*!*/ context, string source, string encoding, [DefaultParameterValue("strict")]string errors) {
  80. _bytes = new List<byte>(StringOps.encode(context, source, encoding, errors).MakeByteArray());
  81. }
  82. #region Public Mutable Sequence API
  83. public void append(int item) {
  84. lock (this) {
  85. _bytes.Add(item.ToByteChecked());
  86. }
  87. }
  88. public void append(object item) {
  89. lock(this) {
  90. _bytes.Add(GetByte(item));
  91. }
  92. }
  93. public void extend([NotNull]IEnumerable<byte>/*!*/ seq) {
  94. using (new OrderedLocker(this, seq)) {
  95. // use the original count for if we're extending this w/ this
  96. _bytes.AddRange(seq);
  97. }
  98. }
  99. public void extend(object seq) {
  100. extend(GetBytes(seq));
  101. }
  102. public void insert(int index, int value) {
  103. lock (this) {
  104. if (index >= Count) {
  105. append(value);
  106. return;
  107. }
  108. index = PythonOps.FixSliceIndex(index, Count);
  109. _bytes.Insert(index, value.ToByteChecked());
  110. }
  111. }
  112. public void insert(int index, object value) {
  113. insert(index, Converter.ConvertToIndex(value));
  114. }
  115. public int pop() {
  116. lock (this) {
  117. if (Count == 0) {
  118. throw PythonOps.IndexError("pop off of empty bytearray");
  119. }
  120. int res = _bytes[_bytes.Count - 1];
  121. _bytes.RemoveAt(_bytes.Count - 1);
  122. return res;
  123. }
  124. }
  125. public int pop(int index) {
  126. lock (this) {
  127. if (Count == 0) {
  128. throw PythonOps.IndexError("pop off of empty bytearray");
  129. }
  130. index = PythonOps.FixIndex(index, Count);
  131. int ret = _bytes[index];
  132. _bytes.RemoveAt(index);
  133. return ret;
  134. }
  135. }
  136. public void remove(int value) {
  137. lock (this) {
  138. _bytes.RemoveAt(_bytes.IndexOfByte(value.ToByteChecked(), 0, _bytes.Count));
  139. }
  140. }
  141. public void remove(object value) {
  142. lock (this) {
  143. if (value is ByteArray) {
  144. throw PythonOps.TypeError("an integer or string of size 1 is required");
  145. }
  146. _bytes.RemoveAt(_bytes.IndexOfByte(GetByte(value), 0, _bytes.Count));
  147. }
  148. }
  149. public void reverse() {
  150. lock (this) {
  151. List<byte> reversed = new List<byte>();
  152. for (int i = _bytes.Count - 1; i >= 0; i--) {
  153. reversed.Add(_bytes[i]);
  154. }
  155. _bytes = reversed;
  156. }
  157. }
  158. [SpecialName]
  159. public ByteArray InPlaceAdd(ByteArray other) {
  160. using (new OrderedLocker(this, other)) {
  161. _bytes.AddRange(other._bytes);
  162. return this;
  163. }
  164. }
  165. [SpecialName]
  166. public ByteArray InPlaceAdd(Bytes other) {
  167. lock (this) {
  168. _bytes.AddRange(other);
  169. return this;
  170. }
  171. }
  172. [SpecialName]
  173. public ByteArray InPlaceMultiply(int len) {
  174. lock (this) {
  175. _bytes = (this * len)._bytes;
  176. return this;
  177. }
  178. }
  179. #endregion
  180. #region Public Python API surface
  181. public ByteArray/*!*/ capitalize() {
  182. lock (this) {
  183. return new ByteArray(_bytes.Capitalize());
  184. }
  185. }
  186. public ByteArray/*!*/ center(int width) {
  187. return center(width, " ");
  188. }
  189. public ByteArray/*!*/ center(int width, [NotNull]string fillchar) {
  190. lock (this) {
  191. List<byte> res = _bytes.TryCenter(width, fillchar.ToByte("center", 2));
  192. if (res == null) {
  193. return CopyThis();
  194. }
  195. return new ByteArray(res);
  196. }
  197. }
  198. public ByteArray/*!*/ center(int width, [BytesConversion]IList<byte> fillchar) {
  199. lock (this) {
  200. List<byte> res = _bytes.TryCenter(width, fillchar.ToByte("center", 2));
  201. if (res == null) {
  202. return CopyThis();
  203. }
  204. return new ByteArray(res);
  205. }
  206. }
  207. public int count([BytesConversion]IList<byte>/*!*/ sub) {
  208. return count(sub, 0, _bytes.Count);
  209. }
  210. public int count([BytesConversion]IList<byte>/*!*/ sub, int start) {
  211. return count(sub, start, _bytes.Count);
  212. }
  213. public int count([BytesConversion]IList<byte>/*!*/ ssub, int start, int end) {
  214. lock (this) {
  215. return _bytes.CountOf(ssub, start, end);
  216. }
  217. }
  218. public string decode(CodeContext/*!*/ context, [Optional]object encoding, [DefaultParameterValue("strict")]string errors) {
  219. return StringOps.decode(context, _bytes.MakeString(), encoding, errors);
  220. }
  221. public bool endswith([BytesConversion]IList<byte>/*!*/ suffix) {
  222. lock (this) {
  223. return _bytes.EndsWith(suffix);
  224. }
  225. }
  226. public bool endswith([BytesConversion]IList<byte>/*!*/ suffix, int start) {
  227. lock (this) {
  228. return _bytes.EndsWith(suffix, start);
  229. }
  230. }
  231. public bool endswith([BytesConversion]IList<byte>/*!*/ suffix, int start, int end) {
  232. lock (this) {
  233. return _bytes.EndsWith(suffix, start, end);
  234. }
  235. }
  236. public bool endswith(PythonTuple/*!*/ suffix) {
  237. lock (this) {
  238. return _bytes.EndsWith(suffix);
  239. }
  240. }
  241. public bool endswith(PythonTuple/*!*/ suffix, int start) {
  242. lock (this) {
  243. return _bytes.EndsWith(suffix, start);
  244. }
  245. }
  246. public bool endswith(PythonTuple/*!*/ suffix, int start, int end) {
  247. lock (this) {
  248. return _bytes.EndsWith(suffix, start, end);
  249. }
  250. }
  251. public ByteArray/*!*/ expandtabs() {
  252. return expandtabs(8);
  253. }
  254. public ByteArray/*!*/ expandtabs(int tabsize) {
  255. lock (this) {
  256. return new ByteArray(_bytes.ExpandTabs(tabsize));
  257. }
  258. }
  259. public int find([BytesConversion]IList<byte>/*!*/ sub) {
  260. lock (this) {
  261. return _bytes.Find(sub);
  262. }
  263. }
  264. public int find([BytesConversion]IList<byte>/*!*/ sub, int start) {
  265. lock (this) {
  266. return _bytes.Find(sub, start);
  267. }
  268. }
  269. public int find([BytesConversion]IList<byte>/*!*/ sub, int start, int end) {
  270. lock (this) {
  271. return _bytes.Find(sub, start, end);
  272. }
  273. }
  274. public static ByteArray/*!*/ fromhex(string/*!*/ @string) {
  275. return new ByteArray(IListOfByteOps.FromHex(@string));
  276. }
  277. public int index([BytesConversion]IList<byte>/*!*/ item) {
  278. return index(item, 0, _bytes.Count);
  279. }
  280. public int index([BytesConversion]IList<byte>/*!*/ item, int start) {
  281. return index(item, start, _bytes.Count);
  282. }
  283. public int index([BytesConversion]IList<byte>/*!*/ item, int start, int stop) {
  284. lock (this) {
  285. int res = find(item, start, stop);
  286. if (res == -1) {
  287. throw PythonOps.ValueError("bytearray.index(item): item not in bytearray");
  288. }
  289. return res;
  290. }
  291. }
  292. public bool isalnum() {
  293. lock (this) {
  294. return _bytes.IsAlphaNumeric();
  295. }
  296. }
  297. public bool isalpha() {
  298. lock (this) {
  299. return _bytes.IsLetter();
  300. }
  301. }
  302. public bool isdigit() {
  303. lock (this) {
  304. return _bytes.IsDigit();
  305. }
  306. }
  307. public bool islower() {
  308. lock (this) {
  309. return _bytes.IsLower();
  310. }
  311. }
  312. public bool isspace() {
  313. lock (this) {
  314. return _bytes.IsWhiteSpace();
  315. }
  316. }
  317. /// <summary>
  318. /// return true if self is a titlecased string and there is at least one
  319. /// character in self; also, uppercase characters may only follow uncased
  320. /// characters (e.g. whitespace) and lowercase characters only cased ones.
  321. /// return false otherwise.
  322. /// </summary>
  323. public bool istitle() {
  324. lock (this) {
  325. return _bytes.IsTitle();
  326. }
  327. }
  328. public bool isupper() {
  329. lock (this) {
  330. return _bytes.IsUpper();
  331. }
  332. }
  333. /// <summary>
  334. /// Return a string which is the concatenation of the strings
  335. /// in the sequence seq. The separator between elements is the
  336. /// string providing this method
  337. /// </summary>
  338. public ByteArray/*!*/ join(object/*!*/ sequence) {
  339. IEnumerator seq = PythonOps.GetEnumerator(sequence);
  340. if (!seq.MoveNext()) {
  341. return new ByteArray();
  342. }
  343. // check if we have just a sequnce of just one value - if so just
  344. // return that value.
  345. object curVal = seq.Current;
  346. if (!seq.MoveNext()) {
  347. return JoinOne(curVal);
  348. }
  349. List<byte> ret = new List<byte>();
  350. ByteOps.AppendJoin(curVal, 0, ret);
  351. int index = 1;
  352. do {
  353. ret.AddRange(this);
  354. ByteOps.AppendJoin(seq.Current, index, ret);
  355. index++;
  356. } while (seq.MoveNext());
  357. return new ByteArray(ret);
  358. }
  359. public ByteArray/*!*/ join([NotNull]List/*!*/ sequence) {
  360. if (sequence.__len__() == 0) {
  361. return new ByteArray();
  362. }
  363. lock (this) {
  364. if (sequence.__len__() == 1) {
  365. return JoinOne(sequence[0]);
  366. }
  367. List<byte> ret = new List<byte>();
  368. ByteOps.AppendJoin(sequence._data[0], 0, ret);
  369. for (int i = 1; i < sequence._size; i++) {
  370. ret.AddRange(this);
  371. ByteOps.AppendJoin(sequence._data[i], i, ret);
  372. }
  373. return new ByteArray(ret);
  374. }
  375. }
  376. public ByteArray/*!*/ ljust(int width) {
  377. return ljust(width, (byte)' ');
  378. }
  379. public ByteArray/*!*/ ljust(int width, [NotNull]string/*!*/ fillchar) {
  380. return ljust(width, fillchar.ToByte("ljust", 2));
  381. }
  382. public ByteArray/*!*/ ljust(int width, IList<byte>/*!*/ fillchar) {
  383. return ljust(width, fillchar.ToByte("ljust", 2));
  384. }
  385. private ByteArray/*!*/ ljust(int width, byte fillchar) {
  386. lock (this) {
  387. int spaces = width - _bytes.Count;
  388. List<byte> ret = new List<byte>(width);
  389. ret.AddRange(_bytes);
  390. for (int i = 0; i < spaces; i++) {
  391. ret.Add(fillchar);
  392. }
  393. return new ByteArray(ret);
  394. }
  395. }
  396. public ByteArray/*!*/ lower() {
  397. lock (this) {
  398. return new ByteArray(_bytes.ToLower());
  399. }
  400. }
  401. public ByteArray/*!*/ lstrip() {
  402. lock (this) {
  403. List<byte> res = _bytes.LeftStrip();
  404. if (res == null) {
  405. return CopyThis();
  406. }
  407. return new ByteArray(res);
  408. }
  409. }
  410. public ByteArray/*!*/ lstrip([BytesConversionNoString]IList<byte> bytes) {
  411. lock (this) {
  412. List<byte> res = _bytes.LeftStrip(bytes);
  413. if (res == null) {
  414. return CopyThis();
  415. }
  416. return new ByteArray(res);
  417. }
  418. }
  419. public PythonTuple/*!*/ partition(IList<byte>/*!*/ sep) {
  420. if (sep == null) {
  421. throw PythonOps.TypeError("expected string, got NoneType");
  422. } else if (sep.Count == 0) {
  423. throw PythonOps.ValueError("empty separator");
  424. }
  425. object[] obj = new object[3] { new ByteArray(), new ByteArray(), new ByteArray() };
  426. if (_bytes.Count != 0) {
  427. int index = find(sep);
  428. if (index == -1) {
  429. obj[0] = CopyThis();
  430. } else {
  431. obj[0] = new ByteArray(_bytes.Substring(0, index));
  432. obj[1] = sep;
  433. obj[2] = new ByteArray(_bytes.Substring(index + sep.Count, _bytes.Count - index - sep.Count));
  434. }
  435. }
  436. return new PythonTuple(obj);
  437. }
  438. public PythonTuple/*!*/ partition([NotNull]List/*!*/ sep) {
  439. return partition(GetBytes(sep));
  440. }
  441. public ByteArray/*!*/ replace([BytesConversion]IList<byte>/*!*/ old, [BytesConversion]IList<byte> @new) {
  442. if (old == null) {
  443. throw PythonOps.TypeError("expected bytes or bytearray, got NoneType");
  444. }
  445. return replace(old, @new, _bytes.Count);
  446. }
  447. public ByteArray/*!*/ replace([BytesConversion]IList<byte>/*!*/ old, [BytesConversion]IList<byte>/*!*/ @new, int count) {
  448. if (old == null) {
  449. throw PythonOps.TypeError("expected bytes or bytearray, got NoneType");
  450. } else if (count == 0) {
  451. return CopyThis();
  452. }
  453. return new ByteArray(_bytes.Replace(old, @new, count));
  454. }
  455. public int rfind([BytesConversion]IList<byte>/*!*/ sub) {
  456. return rfind(sub, 0, _bytes.Count);
  457. }
  458. public int rfind([BytesConversion]IList<byte>/*!*/ sub, int start) {
  459. return rfind(sub, start, _bytes.Count);
  460. }
  461. public int rfind([BytesConversion]IList<byte>/*!*/ sub, int start, int end) {
  462. lock (this) {
  463. return _bytes.ReverseFind(sub, start, end);
  464. }
  465. }
  466. public int rindex([BytesConversion]IList<byte>/*!*/ sub) {
  467. return rindex(sub, 0, _bytes.Count);
  468. }
  469. public int rindex([BytesConversion]IList<byte>/*!*/ sub, int start) {
  470. return rindex(sub, start, _bytes.Count);
  471. }
  472. public int rindex([BytesConversion]IList<byte>/*!*/ sub, int start, int end) {
  473. int ret = rfind(sub, start, end);
  474. if (ret == -1) {
  475. throw PythonOps.ValueError("substring {0} not found in {1}", sub, this);
  476. }
  477. return ret;
  478. }
  479. public ByteArray/*!*/ rjust(int width) {
  480. return rjust(width, (byte)' ');
  481. }
  482. public ByteArray/*!*/ rjust(int width, [NotNull]string/*!*/ fillchar) {
  483. return rjust(width, fillchar.ToByte("rjust", 2));
  484. }
  485. public ByteArray/*!*/ rjust(int width, [BytesConversion]IList<byte>/*!*/ fillchar) {
  486. return rjust(width, fillchar.ToByte("rjust", 2));
  487. }
  488. private ByteArray/*!*/ rjust(int width, int fillchar) {
  489. byte fill = fillchar.ToByteChecked();
  490. lock (this) {
  491. int spaces = width - _bytes.Count;
  492. if (spaces <= 0) {
  493. return CopyThis();
  494. }
  495. List<byte> ret = new List<byte>(width);
  496. for (int i = 0; i < spaces; i++) {
  497. ret.Add(fill);
  498. }
  499. ret.AddRange(_bytes);
  500. return new ByteArray(ret);
  501. }
  502. }
  503. public PythonTuple/*!*/ rpartition(IList<byte>/*!*/ sep) {
  504. if (sep == null) {
  505. throw PythonOps.TypeError("expected string, got NoneType");
  506. } else if (sep.Count == 0) {
  507. throw PythonOps.ValueError("empty separator");
  508. }
  509. lock (this) {
  510. object[] obj = new object[3] { new ByteArray(), new ByteArray(), new ByteArray() };
  511. if (_bytes.Count != 0) {
  512. int index = rfind(sep);
  513. if (index == -1) {
  514. obj[2] = CopyThis();
  515. } else {
  516. obj[0] = new ByteArray(_bytes.Substring(0, index));
  517. obj[1] = new ByteArray(new List<byte>(sep));
  518. obj[2] = new ByteArray(_bytes.Substring(index + sep.Count, Count - index - sep.Count));
  519. }
  520. }
  521. return new PythonTuple(obj);
  522. }
  523. }
  524. public PythonTuple/*!*/ rpartition([NotNull]List/*!*/ sep) {
  525. return rpartition(GetBytes(sep));
  526. }
  527. public List/*!*/ rsplit() {
  528. lock (this) {
  529. return _bytes.SplitInternal((byte[])null, -1, x => new ByteArray(x));
  530. }
  531. }
  532. public List/*!*/ rsplit([BytesConversionNoString]IList<byte>/*!*/ sep) {
  533. return rsplit(sep, -1);
  534. }
  535. public List/*!*/ rsplit([BytesConversionNoString]IList<byte>/*!*/ sep, int maxsplit) {
  536. return _bytes.RightSplit(sep, maxsplit, x => new ByteArray(new List<byte>(x)));
  537. }
  538. public ByteArray/*!*/ rstrip() {
  539. lock (this) {
  540. List<byte> res = _bytes.RightStrip();
  541. if (res == null) {
  542. return CopyThis();
  543. }
  544. return new ByteArray(res);
  545. }
  546. }
  547. public ByteArray/*!*/ rstrip([BytesConversionNoString]IList<byte> bytes) {
  548. lock (this) {
  549. List<byte> res = _bytes.RightStrip(bytes);
  550. if (res == null) {
  551. return CopyThis();
  552. }
  553. return new ByteArray(res);
  554. }
  555. }
  556. public List/*!*/ split() {
  557. lock (this) {
  558. return _bytes.SplitInternal((byte[])null, -1, x => new ByteArray(x));
  559. }
  560. }
  561. public List/*!*/ split([BytesConversionNoString]IList<byte> sep) {
  562. return split(sep, -1);
  563. }
  564. public List/*!*/ split([BytesConversionNoString]IList<byte> sep, int maxsplit) {
  565. lock (this) {
  566. return _bytes.Split(sep, maxsplit, x => new ByteArray(x));
  567. }
  568. }
  569. public List/*!*/ splitlines() {
  570. return splitlines(false);
  571. }
  572. public List/*!*/ splitlines(bool keepends) {
  573. lock (this) {
  574. return _bytes.SplitLines(keepends, x => new ByteArray(x));
  575. }
  576. }
  577. public bool startswith([BytesConversion]IList<byte>/*!*/ prefix) {
  578. lock (this) {
  579. return _bytes.StartsWith(prefix);
  580. }
  581. }
  582. public bool startswith([BytesConversion]IList<byte>/*!*/ prefix, int start) {
  583. lock (this) {
  584. int len = Count;
  585. if (start > len) {
  586. return false;
  587. } else if (start < 0) {
  588. start += len;
  589. if (start < 0) start = 0;
  590. }
  591. return _bytes.Substring(start).StartsWith(prefix);
  592. }
  593. }
  594. public bool startswith([BytesConversion]IList<byte>/*!*/ prefix, int start, int end) {
  595. lock (this) {
  596. return _bytes.StartsWith(prefix, start, end);
  597. }
  598. }
  599. public bool startswith(PythonTuple/*!*/ prefix) {
  600. lock (this) {
  601. return _bytes.StartsWith(prefix);
  602. }
  603. }
  604. public bool startswith(PythonTuple/*!*/ prefix, int start) {
  605. lock (this) {
  606. return _bytes.StartsWith(prefix, start);
  607. }
  608. }
  609. public bool startswith(PythonTuple/*!*/ prefix, int start, int end) {
  610. lock (this) {
  611. return _bytes.StartsWith(prefix, start, end);
  612. }
  613. }
  614. public ByteArray/*!*/ strip() {
  615. lock (this) {
  616. List<byte> res = _bytes.Strip();
  617. if (res == null) {
  618. return CopyThis();
  619. }
  620. return new ByteArray(res);
  621. }
  622. }
  623. public ByteArray/*!*/ strip([BytesConversionNoString]IList<byte> chars) {
  624. lock (this) {
  625. List<byte> res = _bytes.Strip(chars);
  626. if (res == null) {
  627. return CopyThis();
  628. }
  629. return new ByteArray(res);
  630. }
  631. }
  632. public ByteArray/*!*/ swapcase() {
  633. lock (this) {
  634. return new ByteArray(_bytes.SwapCase());
  635. }
  636. }
  637. public ByteArray/*!*/ title() {
  638. lock (this) {
  639. List<byte> res = _bytes.Title();
  640. if (res == null) {
  641. return CopyThis();
  642. }
  643. return new ByteArray(res);
  644. }
  645. }
  646. public ByteArray/*!*/ translate([BytesConversion]IList<byte>/*!*/ table) {
  647. lock (this) {
  648. if (table != null) {
  649. if (table.Count != 256) {
  650. throw PythonOps.ValueError("translation table must be 256 characters long");
  651. }
  652. else if (Count == 0) {
  653. return CopyThis();
  654. }
  655. }
  656. return new ByteArray(_bytes.Translate(table, null));
  657. }
  658. }
  659. public ByteArray/*!*/ translate([BytesConversion]IList<byte>/*!*/ table, [BytesConversion]IList<byte>/*!*/ deletechars) {
  660. if (table == null && deletechars == null) {
  661. throw PythonOps.TypeError("expected bytearray or bytes, got NoneType");
  662. }
  663. else if (deletechars == null) {
  664. throw PythonOps.TypeError("expected bytes or bytearray, got None");
  665. }
  666. lock (this) {
  667. return new ByteArray(_bytes.Translate(table, deletechars));
  668. }
  669. }
  670. public ByteArray/*!*/ upper() {
  671. lock (this) {
  672. return new ByteArray(_bytes.ToUpper());
  673. }
  674. }
  675. public ByteArray/*!*/ zfill(int width) {
  676. lock (this) {
  677. int spaces = width - Count;
  678. if (spaces <= 0) {
  679. return CopyThis();
  680. }
  681. return new ByteArray(_bytes.ZeroFill(width, spaces));
  682. }
  683. }
  684. public int __alloc__() {
  685. if (_bytes.Count == 0) {
  686. return 0;
  687. }
  688. return _bytes.Count + 1;
  689. }
  690. public bool __contains__([BytesConversionNoString]IList<byte> bytes) {
  691. return this.IndexOf(bytes, 0) != -1;
  692. }
  693. public bool __contains__(int value) {
  694. return IndexOf(value.ToByteChecked()) != -1;
  695. }
  696. public bool __contains__(CodeContext/*!*/ context, object value) {
  697. if (value is Extensible<int>) {
  698. return IndexOf(((Extensible<int>)value).Value.ToByteChecked()) != -1;
  699. } else if (value is BigInteger) {
  700. return IndexOf(((BigInteger)value).ToByteChecked()) != -1;
  701. } else if (value is Extensible<BigInteger>) {
  702. return IndexOf(((Extensible<BigInteger>)value).Value.ToByteChecked()) != -1;
  703. }
  704. throw PythonOps.TypeError("Type {0} doesn't support the buffer API",
  705. PythonContext.GetContext(context).PythonOptions.Python30 ? PythonTypeOps.GetOldName(value) : PythonTypeOps.GetName(value));
  706. }
  707. public PythonTuple __reduce__(CodeContext/*!*/ context) {
  708. return PythonTuple.MakeTuple(
  709. DynamicHelpers.GetPythonType(this),
  710. PythonTuple.MakeTuple(
  711. PythonOps.MakeString(this),
  712. "latin-1"
  713. ),
  714. GetType() == typeof(ByteArray) ? null : ObjectOps.ReduceProtocol0(context, this)[2]
  715. );
  716. }
  717. public virtual string/*!*/ __repr__(CodeContext/*!*/ context) {
  718. lock (this) {
  719. return "bytearray(" + _bytes.BytesRepr() + ")";
  720. }
  721. }
  722. public static ByteArray operator +(ByteArray self, ByteArray other) {
  723. if (self == null) {
  724. throw PythonOps.TypeError("expected ByteArray, got None");
  725. }
  726. List<byte> bytes;
  727. lock (self) {
  728. bytes = new List<byte>(self._bytes);
  729. }
  730. lock (other) {
  731. bytes.AddRange(other._bytes);
  732. }
  733. return new ByteArray(bytes);
  734. }
  735. public static ByteArray operator +(ByteArray self, Bytes other) {
  736. List<byte> bytes;
  737. lock (self) {
  738. bytes = new List<byte>(self._bytes);
  739. }
  740. bytes.AddRange(other);
  741. return new ByteArray(bytes);
  742. }
  743. public static ByteArray operator *(ByteArray x, int y) {
  744. lock (x) {
  745. if (y == 1) {
  746. return x.CopyThis();
  747. }
  748. return new ByteArray(x._bytes.Multiply(y));
  749. }
  750. }
  751. public static ByteArray operator *(int x, ByteArray y) {
  752. return y * x;
  753. }
  754. public static bool operator >(ByteArray/*!*/ x, ByteArray y) {
  755. if (y == null) {
  756. return true;
  757. }
  758. using (new OrderedLocker(x, y)) {
  759. return x._bytes.Compare(y._bytes) > 0;
  760. }
  761. }
  762. public static bool operator <(ByteArray/*!*/ x, ByteArray y) {
  763. if (y == null) {
  764. return false;
  765. }
  766. using (new OrderedLocker(x, y)) {
  767. return x._bytes.Compare(y._bytes) < 0;
  768. }
  769. }
  770. public static bool operator >=(ByteArray/*!*/ x, ByteArray y) {
  771. if (y == null) {
  772. return true;
  773. }
  774. using (new OrderedLocker(x, y)) {
  775. return x._bytes.Compare(y._bytes) >= 0;
  776. }
  777. }
  778. public static bool operator <=(ByteArray/*!*/ x, ByteArray y) {
  779. if (y == null) {
  780. return false;
  781. }
  782. using (new OrderedLocker(x, y)) {
  783. return x._bytes.Compare(y._bytes) <= 0;
  784. }
  785. }
  786. public static bool operator >(ByteArray/*!*/ x, Bytes y) {
  787. if (y == null) {
  788. return true;
  789. }
  790. lock (x) {
  791. return x._bytes.Compare(y) > 0;
  792. }
  793. }
  794. public static bool operator <(ByteArray/*!*/ x, Bytes y) {
  795. if (y == null) {
  796. return false;
  797. }
  798. lock (x) {
  799. return x._bytes.Compare(y) < 0;
  800. }
  801. }
  802. public static bool operator >=(ByteArray/*!*/ x, Bytes y) {
  803. if (y == null) {
  804. return true;
  805. }
  806. lock (x) {
  807. return x._bytes.Compare(y) >= 0;
  808. }
  809. }
  810. public static bool operator <=(ByteArray/*!*/ x, Bytes y) {
  811. if (y == null) {
  812. return false;
  813. }
  814. lock (x) {
  815. return x._bytes.Compare(y) <= 0;
  816. }
  817. }
  818. public object this[int index] {
  819. get {
  820. lock (this) {
  821. return ScriptingRuntimeHelpers.Int32ToObject((int)_bytes[PythonOps.FixIndex(index, _bytes.Count)]);
  822. }
  823. }
  824. set {
  825. lock (this) {
  826. _bytes[PythonOps.FixIndex(index, _bytes.Count)] = GetByte(value);
  827. }
  828. }
  829. }
  830. public object this[BigInteger index] {
  831. get {
  832. int iVal;
  833. if (index.AsInt32(out iVal)) {
  834. return this[iVal];
  835. }
  836. throw PythonOps.IndexError("cannot fit long in index");
  837. }
  838. set {
  839. int iVal;
  840. if (index.AsInt32(out iVal)) {
  841. this[iVal] = value;
  842. return;
  843. }
  844. throw PythonOps.IndexError("cannot fit long in index");
  845. }
  846. }
  847. public object this[Slice/*!*/ slice] {
  848. get {
  849. lock (this) {
  850. List<byte> res = _bytes.Slice(slice);
  851. if (res == null) {
  852. return new ByteArray();
  853. }
  854. return new ByteArray(res);
  855. }
  856. }
  857. set {
  858. if (slice == null) {
  859. throw PythonOps.TypeError("bytearray indices must be integer or slice, not None");
  860. }
  861. // get a list of the bytes we're going to assign into the slice. We accept:
  862. // integers, longs, etc... - fill in an array of 0 bytes
  863. // list of bytes, indexables, etc...
  864. IList<byte> list = value as IList<byte>;
  865. if (list == null) {
  866. int? iVal = null;
  867. if (value is int) {
  868. iVal = (int)value;
  869. } else if (value is Extensible<int>) {
  870. iVal = ((Extensible<int>)value).Value;
  871. } else if (value is BigInteger) {
  872. int intval;
  873. if (((BigInteger)value).AsInt32(out intval)) {
  874. iVal = intval;
  875. }
  876. }
  877. if (iVal != null) {
  878. List<byte> newlist = new List<byte>();
  879. newlist.Capacity = iVal.Value;
  880. for (int i = 0; i < iVal; i++) {
  881. newlist.Add(0);
  882. }
  883. list = newlist;
  884. } else {
  885. IEnumerator ie = PythonOps.GetEnumerator(value);
  886. list = new List<byte>();
  887. while (ie.MoveNext()) {
  888. list.Add(GetByte(ie.Current));
  889. }
  890. }
  891. }
  892. lock (this) {
  893. if (slice.step != null) {
  894. // try to assign back to self: make a copy first
  895. if (this == list) {
  896. value = CopyThis();
  897. } else if (list.Count == 0) {
  898. DeleteItem(slice);
  899. return;
  900. }
  901. IList<byte> castedVal = GetBytes(value);
  902. int start, stop, step;
  903. slice.indices(_bytes.Count, out start, out stop, out step);
  904. int n = (step > 0 ? (stop - start + step - 1) : (stop - start + step + 1)) / step;
  905. // we don't use slice.Assign* helpers here because bytearray has different assignment semantics.
  906. if (list.Count < n) {
  907. throw PythonOps.ValueError("too few items in the enumerator. need {0} have {1}", n, castedVal.Count);
  908. }
  909. for (int i = 0, index = start; i < castedVal.Count; i++, index += step) {
  910. if (i >= n) {
  911. if (index == _bytes.Count) {
  912. _bytes.Add(castedVal[i]);
  913. } else {
  914. _bytes.Insert(index, castedVal[i]);
  915. }
  916. } else {
  917. _bytes[index] = castedVal[i];
  918. }
  919. }
  920. } else {
  921. int start, stop, step;
  922. slice.indices(_bytes.Count, out start, out stop, out step);
  923. SliceNoStep(start, stop, list);
  924. }
  925. }
  926. }
  927. }
  928. [SpecialName]
  929. public void DeleteItem(int index) {
  930. _bytes.RemoveAt(PythonOps.FixIndex(index, _bytes.Count));
  931. }
  932. [SpecialName]
  933. public void DeleteItem(Slice/*!*/ slice) {
  934. if (slice == null) {
  935. throw PythonOps.TypeError("list indices must be integers or slices");
  936. }
  937. lock (this) {
  938. int start, stop, step;
  939. // slice is sealed, indices can't be user code...
  940. slice.indices(_bytes.Count, out start, out stop, out step);
  941. if (step > 0 && (start >= stop)) return;
  942. if (step < 0 && (start <= stop)) return;
  943. if (step == 1) {
  944. int i = start;
  945. for (int j = stop; j < _bytes.Count; j++, i++) {
  946. _bytes[i] = _bytes[j];
  947. }
  948. _bytes.RemoveRange(i, stop - start);
  949. return;
  950. } else if (step == -1) {
  951. int i = stop + 1;
  952. for (int j = start + 1; j < _bytes.Count; j++, i++) {
  953. _bytes[i] = _bytes[j];
  954. }
  955. _bytes.RemoveRange(i, start - stop);
  956. return;
  957. } else if (step < 0) {
  958. // find "start" we will skip in the 1,2,3,... order
  959. int i = start;
  960. while (i > stop) {
  961. i += step;
  962. }
  963. i -= step;
  964. // swap start/stop, make step positive
  965. stop = start + 1;
  966. start = i;
  967. step = -step;
  968. }
  969. int curr, skip, move;
  970. // skip: the next position we should skip
  971. // curr: the next position we should fill in data
  972. // move: the next position we will check
  973. curr = skip = move = start;
  974. while (curr < stop && move < stop) {
  975. if (move != skip) {
  976. _bytes[curr++] = _bytes[move];
  977. } else
  978. skip += step;
  979. move++;
  980. }
  981. while (stop < _bytes.Count) {
  982. _bytes[curr++] = _bytes[stop++];
  983. }
  984. _bytes.RemoveRange(curr, _bytes.Count - curr);
  985. }
  986. }
  987. #endregion
  988. #region Implementation Details
  989. private static ByteArray/*!*/ JoinOne(object/*!*/ curVal) {
  990. if (!(curVal is IList<byte>)) {
  991. throw PythonOps.TypeError("can only join an iterable of bytes");
  992. }
  993. return new ByteArray(new List<byte>(curVal as IList<byte>));
  994. }
  995. private ByteArray/*!*/ CopyThis() {
  996. return new ByteArray(new List<byte>(_bytes));
  997. }
  998. private void SliceNoStep(int start, int stop, IList<byte>/*!*/ value) {
  999. // always copy from a List object, even if it's a copy of some user defined enumerator. This
  1000. // makes it easy to hold the lock for the duration fo the copy.
  1001. IList<byte> other = GetBytes(value);
  1002. lock (this) {
  1003. if (start > stop) {
  1004. int newSize = Count + other.Count;
  1005. List<byte> newData = new List<byte>(newSize);
  1006. int reading = 0;
  1007. for (reading = 0; reading < start; reading++) {
  1008. newData.Add(_bytes[reading]);
  1009. }
  1010. for (int i = 0; i < other.Count; i++) {
  1011. newData.Add(other[i]);
  1012. }
  1013. for (; reading < Count; reading++) {
  1014. newData.Add(_bytes[reading]);
  1015. }
  1016. _bytes = newData;
  1017. } else if ((stop - start) == other.Count) {
  1018. // we are simply replacing values, this is fast...
  1019. for (int i = 0; i < other.Count; i++) {
  1020. _bytes[i + start] = other[i];
  1021. }
  1022. } else {
  1023. // we are resizing the array (either bigger or smaller), we
  1024. // will copy the data array and replace it all at once.
  1025. int newSize = Count - (stop - start) + other.Count;
  1026. List<byte> newData = new List<byte>(newSize);
  1027. for (int i = 0; i < start; i++) {
  1028. newData.Add(_bytes[i]);
  1029. }
  1030. for (int i = 0; i < other.Count; i++) {
  1031. newData.Add(other[i]);
  1032. }
  1033. for (int i = stop; i < Count; i++) {
  1034. newData.Add(_bytes[i]);
  1035. }
  1036. _bytes = newData;
  1037. }
  1038. }
  1039. }
  1040. private static byte GetByte(object/*!*/ value) {
  1041. if (value is double || value is Extensible<double> || value is float) {
  1042. throw PythonOps.TypeError("an integer or string of size 1 is required");
  1043. }
  1044. return ByteOps.GetByteListOk(value);
  1045. }
  1046. private static IList<byte>/*!*/ GetBytes(object/*!*/ value) {
  1047. ListGenericWrapper<byte> genWrapper = value as ListGenericWrapper<byte>;
  1048. if (genWrapper == null && value is IList<byte>) {
  1049. return (IList<byte>)value;
  1050. }
  1051. var strValue = value as string;
  1052. if (strValue != null) {
  1053. return strValue.MakeByteArray();
  1054. }
  1055. var esValue = value as Extensible<string>;
  1056. if (esValue != null) {
  1057. return esValue.Value.MakeByteArray();
  1058. }
  1059. List<byte> ret = new List<byte>();
  1060. IEnumerator ie = PythonOps.GetEnumerator(value);
  1061. while (ie.MoveNext()) {
  1062. ret.Add(GetByte(ie.Current));
  1063. }
  1064. return ret;
  1065. }
  1066. #endregion
  1067. #region IList<byte> Members
  1068. [PythonHidden]
  1069. public int IndexOf(byte item) {
  1070. lock (this) {
  1071. return _bytes.IndexOf(item);
  1072. }
  1073. }
  1074. [PythonHidden]
  1075. public void Insert(int index, byte item) {
  1076. _bytes.Insert(index, item);
  1077. }
  1078. [PythonHidden]
  1079. public void RemoveAt(int index) {
  1080. _bytes.RemoveAt(index);
  1081. }
  1082. byte IList<byte>.this[int index] {
  1083. get {
  1084. return _bytes[index];
  1085. }
  1086. set {
  1087. _bytes[index] = value;
  1088. }
  1089. }
  1090. #endregion
  1091. #region ICollection<byte> Members
  1092. [PythonHidden]
  1093. public void Add(byte item) {
  1094. lock (this) {
  1095. _bytes.Add(item);
  1096. }
  1097. }
  1098. [PythonHidden]
  1099. public void Clear() {
  1100. lock (this) {
  1101. _bytes.Clear();
  1102. }
  1103. }
  1104. [PythonHidden]
  1105. public bool Contains(byte item) {
  1106. lock (this) {
  1107. return _bytes.Contains(item);
  1108. }
  1109. }
  1110. [PythonHidden]
  1111. public void CopyTo(byte[]/*!*/ array, int arrayIndex) {
  1112. lock (this) {
  1113. _bytes.CopyTo(array, arrayIndex);
  1114. }
  1115. }
  1116. public int Count {
  1117. [PythonHidden]
  1118. get {
  1119. lock (this) {
  1120. return _bytes.Count;
  1121. }
  1122. }
  1123. }
  1124. public bool IsReadOnly {
  1125. [PythonHidden]
  1126. get { return false; }
  1127. }
  1128. [PythonHidden]
  1129. public bool Remove(byte item) {
  1130. lock (this) {
  1131. return _bytes.Remove(item);
  1132. }
  1133. }
  1134. #endregion
  1135. public IEnumerator __iter__() {
  1136. return PythonOps.BytesIntEnumerator(this).Key;
  1137. }
  1138. #region IEnumerable<byte> Members
  1139. [PythonHidden]
  1140. public IEnumerator<byte>/*!*/ GetEnumerator() {
  1141. return _bytes.GetEnumerator();
  1142. }
  1143. #endregion
  1144. #region IEnumerable Members
  1145. System.Collections.IEnumerator/*!*/ System.Collections.IEnumerable.GetEnumerator()
  1146. {
  1147. foreach (var _byte in _bytes)
  1148. {
  1149. yield return (int)_byte;
  1150. }
  1151. }
  1152. #endregion
  1153. #region IValueEquality Members
  1154. #if CLR2
  1155. int IValueEquality.GetValueHashCode() {
  1156. throw PythonOps.TypeError("bytearray object is unhashable");
  1157. }
  1158. bool IValueEquality.ValueEquals(object other) {
  1159. return Equals(other);
  1160. }
  1161. #endif
  1162. public const object __hash__ = null;
  1163. public override int GetHashCode() {
  1164. return (PythonTuple.MakeTuple(_bytes.ToArray())).GetHashCode();
  1165. }
  1166. public override bool Equals(object other) {
  1167. IList<byte> bytes ;
  1168. if (other is string)
  1169. bytes = PythonOps.MakeBytes(((string)other).MakeByteArray());
  1170. else if (other is Extensible<string>)
  1171. bytes = PythonOps.MakeBytes(((Extensible<string>)other).Value.MakeByteArray());
  1172. else
  1173. bytes = other as IList<byte>;
  1174. if (bytes == null || Count != bytes.Count) {
  1175. return false;
  1176. } else if (Count == 0) {
  1177. // 2 empty ByteArrays are equal
  1178. return true;
  1179. }
  1180. using (new OrderedLocker(this, other)) {
  1181. for (int i = 0; i < Count; i++) {
  1182. if (_bytes[i] != bytes[i]) {
  1183. return false;
  1184. }
  1185. }
  1186. }
  1187. return true;
  1188. }
  1189. #endregion
  1190. public override string ToString() {
  1191. return _bytes.MakeString();
  1192. }
  1193. #region IBufferProtocol Members
  1194. Bytes IBufferProtocol.GetItem(int index) {
  1195. lock (this) {
  1196. return new Bytes(new[] { _bytes[PythonOps.FixIndex(index, _bytes.Count)] });
  1197. }
  1198. }
  1199. void IBufferProtocol.SetItem(int index, object value) {
  1200. this[index] = value;
  1201. }
  1202. void IBufferProtocol.SetSlice(Slice index, object value) {
  1203. this[index] = value;
  1204. }
  1205. int IBufferProtocol.ItemCount {
  1206. get {
  1207. return _bytes.Count;
  1208. }
  1209. }
  1210. string IBufferProtocol.Format {
  1211. get { return "B"; }
  1212. }
  1213. BigInteger IBufferProtocol.ItemSize {
  1214. get { return 1; }
  1215. }
  1216. BigInteger IBufferProtocol.NumberDimensions {
  1217. get { return 1; }
  1218. }
  1219. bool IBufferProtocol.ReadOnly {
  1220. get { return false; }
  1221. }
  1222. IList<BigInteger> IBufferProtocol.GetShape(int start, int? end) {
  1223. if (end != null) {
  1224. return new[] { (BigInteger)end - start };
  1225. }
  1226. return new[] { (BigInteger)this._bytes.Count - start };
  1227. }
  1228. PythonTuple IBufferProtocol.Strides {
  1229. get { return PythonTuple.MakeTuple(1); }
  1230. }
  1231. object IBufferProtocol.SubOffsets {
  1232. get { return null; }
  1233. }
  1234. Bytes IBufferProtocol.ToBytes(int start, int? end) {
  1235. if (start == 0 && end == null) {
  1236. return new Bytes(this);
  1237. }
  1238. return new Bytes((ByteArray)this[new Slice(start, end)]);
  1239. }
  1240. List IBufferProtocol.ToList(int start, int? end) {
  1241. List<byte> res = _bytes.Slice(new Slice(start, end));
  1242. if (res == null) {
  1243. return new List();
  1244. }
  1245. return new List(res.ToArray());
  1246. }
  1247. #endregion
  1248. }
  1249. }