/IronPython_1_0/Src/IronPython/Modules/cStringIO.cs

# · C# · 509 lines · 424 code · 70 blank · 15 comment · 53 complexity · 26cdb5a49cf48f55d27e0aa0191551c8 MD5 · raw file

  1. /* **********************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation. All rights reserved.
  4. *
  5. * This source code is subject to terms and conditions of the Shared Source License
  6. * for IronPython. A copy of the license can be found in the License.html file
  7. * at the root of this distribution. If you can not locate the Shared Source License
  8. * for IronPython, please send an email to ironpy@microsoft.com.
  9. * By using this source code in any fashion, you are agreeing to be bound by
  10. * the terms of the Shared Source License for IronPython.
  11. *
  12. * You must not remove this notice, or any other, from this software.
  13. *
  14. * **********************************************************************************/
  15. using System;
  16. using System.Collections;
  17. using System.IO;
  18. using System.Text;
  19. using IronPython.Runtime;
  20. using IronPython.Runtime.Operations;
  21. [assembly: PythonModule("cStringIO", typeof(IronPython.Modules.PythonStringIO))]
  22. namespace IronPython.Modules {
  23. class StringStream {
  24. private string data;
  25. private int position;
  26. private int length;
  27. public StringStream(string data) {
  28. this.data = data;
  29. this.position = 0;
  30. this.length = data == null ? 0 : data.Length;
  31. }
  32. public bool EOF {
  33. get { return position >= length; }
  34. }
  35. public int Position {
  36. get { return position; }
  37. }
  38. public string Data {
  39. get {
  40. return data;
  41. }
  42. set {
  43. data = value;
  44. if (data == null) {
  45. length = position = 0;
  46. } else {
  47. length = data.Length;
  48. if (position > length) {
  49. position = length;
  50. }
  51. }
  52. }
  53. }
  54. public string Prefix {
  55. get {
  56. return data.Substring(0, position);
  57. }
  58. }
  59. public int Read() {
  60. if (position < length) {
  61. return data[position++];
  62. } else {
  63. return -1;
  64. }
  65. }
  66. public string Read(int i) {
  67. if (position + i > length) {
  68. i = length - position;
  69. }
  70. string ret = data.Substring(position, i);
  71. position += i;
  72. return ret;
  73. }
  74. public string ReadLine() {
  75. int i = position;
  76. while (i < length) {
  77. char c = data[i];
  78. if (c == '\n' || c == '\r') {
  79. i++;
  80. if (c == '\r' && position < length && data[i] == '\n') {
  81. i++;
  82. }
  83. // preserve newline character like StringIO
  84. string res = data.Substring(position, i - position);
  85. position = i;
  86. return res;
  87. }
  88. i++;
  89. }
  90. if (i > position) {
  91. string res = data.Substring(position, i - position);
  92. position = i;
  93. return res;
  94. }
  95. return "";
  96. }
  97. public string ReadToEnd() {
  98. if (position < length) {
  99. string res = data.Substring(position);
  100. position = length;
  101. return res;
  102. } else return "";
  103. }
  104. public void Reset() {
  105. position = 0;
  106. }
  107. public int Seek(int offset, SeekOrigin origin) {
  108. switch (origin) {
  109. case SeekOrigin.Begin:
  110. position = offset; break;
  111. case SeekOrigin.Current:
  112. position = position + offset; break;
  113. case SeekOrigin.End:
  114. position = length + offset; break;
  115. default:
  116. throw new ArgumentException("origin");
  117. }
  118. return position;
  119. }
  120. public void Truncate() {
  121. data = data.Substring(0, position);
  122. length = data.Length;
  123. }
  124. public void Truncate(int size) {
  125. data = data.Substring(0, size);
  126. position = size;
  127. length = data.Length;
  128. }
  129. internal void Write(string s) {
  130. string newData;
  131. int newPosition;
  132. if (position > 0) {
  133. newData = data.Substring(0, position) + s;
  134. } else {
  135. newData = s;
  136. }
  137. newPosition = newData.Length;
  138. if (position + s.Length < length) {
  139. newData = newData + data.Substring(position + s.Length);
  140. }
  141. data = newData;
  142. position = newPosition;
  143. length = data.Length;
  144. }
  145. }
  146. [PythonType("cStringIO")]
  147. public static class PythonStringIO {
  148. public static object InputType = Ops.GetDynamicType(typeof(StringI));
  149. public static object OutputType = Ops.GetDynamicType(typeof(StringO));
  150. public class StringI {
  151. private StringStream sr;
  152. internal StringI(string data) {
  153. sr = new StringStream(data);
  154. }
  155. [PythonName("close")]
  156. public void Close() {
  157. sr = null;
  158. }
  159. public bool Closed {
  160. [PythonName("closed")]
  161. get {
  162. return sr == null;
  163. }
  164. }
  165. [PythonName("flush")]
  166. public void Flush() {
  167. ThrowIfClosed();
  168. }
  169. [PythonName("getvalue")]
  170. public string GetValue() {
  171. ThrowIfClosed();
  172. return sr.Data;
  173. }
  174. [PythonName("getvalue")]
  175. public string GetValue(bool usePos) {
  176. return sr.Prefix;
  177. }
  178. [PythonName("__iter__")]
  179. public object Iter() {
  180. return this;
  181. }
  182. [PythonName("next")]
  183. public string Next() {
  184. ThrowIfClosed();
  185. if (sr.EOF) {
  186. throw Ops.StopIteration();
  187. }
  188. return ReadLine();
  189. }
  190. [PythonName("read")]
  191. public string Read() {
  192. ThrowIfClosed();
  193. return sr.ReadToEnd();
  194. }
  195. [PythonName("read")]
  196. public string Read(int s) {
  197. ThrowIfClosed();
  198. return sr.Read(s);
  199. }
  200. [PythonName("readline")]
  201. public string ReadLine() {
  202. ThrowIfClosed();
  203. return sr.ReadLine();
  204. }
  205. [PythonName("readlines")]
  206. public List ReadLines() {
  207. ThrowIfClosed();
  208. List list = List.Make();
  209. while (!sr.EOF) {
  210. list.AddNoLock(ReadLine());
  211. }
  212. return list;
  213. }
  214. [PythonName("readlines")]
  215. public List ReadLines(int size) {
  216. ThrowIfClosed();
  217. List list = List.Make();
  218. while (!sr.EOF) {
  219. string line = ReadLine();
  220. list.AddNoLock(line);
  221. if (line.Length >= size) break;
  222. size -= line.Length;
  223. }
  224. return list;
  225. }
  226. [PythonName("reset")]
  227. public void Reset() {
  228. ThrowIfClosed();
  229. sr.Reset();
  230. }
  231. [PythonName("seek")]
  232. public void Seek(int position) {
  233. Seek(position, 0);
  234. }
  235. [PythonName("seek")]
  236. public void Seek(int position, int mode) {
  237. ThrowIfClosed();
  238. SeekOrigin so;
  239. switch (mode) {
  240. case 1: so = SeekOrigin.Current; break;
  241. case 2: so = SeekOrigin.End; break;
  242. default: so = SeekOrigin.Begin; break;
  243. }
  244. sr.Seek(position, so);
  245. }
  246. [PythonName("tell")]
  247. public int Tell() {
  248. ThrowIfClosed();
  249. return sr.Position;
  250. }
  251. [PythonName("truncate")]
  252. public void Truncate() {
  253. ThrowIfClosed();
  254. sr.Truncate();
  255. }
  256. [PythonName("truncate")]
  257. public void Truncate(int size) {
  258. ThrowIfClosed();
  259. sr.Truncate(size);
  260. }
  261. private void ThrowIfClosed() {
  262. if (Closed) {
  263. throw Ops.ValueError("I/O operation on closed file");
  264. }
  265. }
  266. }
  267. public class StringO {
  268. private StringWriter sw = new StringWriter();
  269. private StringStream sr = new StringStream("");
  270. private int softspace;
  271. internal StringO() {
  272. }
  273. [PythonName("__iter__")]
  274. public object Iter() {
  275. return this;
  276. }
  277. [PythonName("close")]
  278. public void Close() {
  279. if (sw != null) { sw.Close(); sw = null; }
  280. if (sr != null) { sr = null; }
  281. }
  282. public bool Closed {
  283. [PythonName("closed")]
  284. get {
  285. return sw == null || sr == null;
  286. }
  287. }
  288. [PythonName("flush")]
  289. public void Flush() {
  290. FixStreams();
  291. }
  292. [PythonName("getvalue")]
  293. public string GetValue() {
  294. ThrowIfClosed();
  295. FixStreams();
  296. return sr.Data;
  297. }
  298. [PythonName("getvalue")]
  299. public string GetValue(bool usePos) {
  300. ThrowIfClosed();
  301. FixStreams();
  302. return sr.Prefix;
  303. }
  304. [PythonName("next")]
  305. public string Next() {
  306. ThrowIfClosed();
  307. FixStreams();
  308. if (sr.EOF) {
  309. throw Ops.StopIteration();
  310. }
  311. return ReadLine();
  312. }
  313. [PythonName("read")]
  314. public string Read() {
  315. ThrowIfClosed();
  316. FixStreams();
  317. return sr.ReadToEnd();
  318. }
  319. [PythonName("read")]
  320. public string Read(int i) {
  321. ThrowIfClosed();
  322. FixStreams();
  323. return sr.Read(i);
  324. }
  325. [PythonName("readline")]
  326. public string ReadLine() {
  327. ThrowIfClosed();
  328. FixStreams();
  329. return sr.ReadLine();
  330. }
  331. [PythonName("readlines")]
  332. public List ReadLines() {
  333. ThrowIfClosed();
  334. List list = List.Make();
  335. while (!sr.EOF) {
  336. list.AddNoLock(ReadLine());
  337. }
  338. return list;
  339. }
  340. [PythonName("readlines")]
  341. public List ReadLines(int size) {
  342. ThrowIfClosed();
  343. List list = List.Make();
  344. while (!sr.EOF) {
  345. string line = ReadLine();
  346. list.AddNoLock(line);
  347. if (line.Length >= size) break;
  348. size -= line.Length;
  349. }
  350. return list;
  351. }
  352. [PythonName("reset")]
  353. public void Reset() {
  354. ThrowIfClosed();
  355. FixStreams();
  356. sr.Reset();
  357. }
  358. [PythonName("seek")]
  359. public void Seek(int position) {
  360. Seek(position, 0);
  361. }
  362. [PythonName("seek")]
  363. public void Seek(int offset, int origin) {
  364. ThrowIfClosed();
  365. FixStreams();
  366. SeekOrigin so;
  367. switch (origin) {
  368. case 1: so = SeekOrigin.Current; break;
  369. case 2: so = SeekOrigin.End; break;
  370. default: so = SeekOrigin.Begin; break;
  371. }
  372. sr.Seek(offset, so);
  373. }
  374. public int SoftSpace {
  375. [PythonName("softspace")]
  376. get { return softspace; }
  377. [PythonName("softspace")]
  378. set { softspace = value; }
  379. }
  380. [PythonName("tell")]
  381. public int Tell() {
  382. ThrowIfClosed();
  383. FixStreams();
  384. return sr.Position;
  385. }
  386. [PythonName("truncate")]
  387. public void Truncate() {
  388. ThrowIfClosed();
  389. FixStreams();
  390. sr.Truncate();
  391. }
  392. [PythonName("truncate")]
  393. public void Truncate(int size) {
  394. ThrowIfClosed();
  395. FixStreams();
  396. sr.Truncate(size);
  397. }
  398. [PythonName("write")]
  399. public void Write(string s) {
  400. ThrowIfClosed();
  401. sw.Write(s);
  402. }
  403. [PythonName("writelines")]
  404. public void WriteLines(object o) {
  405. ThrowIfClosed();
  406. IEnumerator e = Ops.GetEnumerator(o);
  407. while (e.MoveNext()) {
  408. string s = e.Current as string;
  409. if (s == null) {
  410. throw Ops.ValueError("string expected");
  411. }
  412. Write(s);
  413. }
  414. }
  415. private void FixStreams() {
  416. if (sr != null) {
  417. StringBuilder sb = sw.GetStringBuilder();
  418. if (sb != null && sb.Length > 0) {
  419. sr.Write(sb.ToString());
  420. sb.Length = 0;
  421. }
  422. }
  423. }
  424. private void ThrowIfClosed() {
  425. if (Closed) {
  426. throw Ops.ValueError("I/O operation on closed file");
  427. }
  428. }
  429. }
  430. [PythonName("StringIO")]
  431. public static object StringIO() {
  432. return new StringO();
  433. }
  434. [PythonName("StringIO")]
  435. public static object StringIO(string data) {
  436. return new StringI(data);
  437. }
  438. }
  439. }