PageRenderTime 81ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/DICK.B1/IronPython/Runtime/ByteArray.cs

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