001: /*
002: * Copyright 1998 Finn Bock.
003: *
004: * This program contains material copyrighted by:
005: * Copyright (c) 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
006: * The Netherlands.
007: */
008:
009: package org.python.modules;
010:
011: import org.python.core.Py;
012: import org.python.core.PyCallIter;
013: import org.python.core.PyList;
014: import org.python.core.PyObject;
015: import org.python.core.PyString;
016:
017: /**
018: * This module implements a file-like class, StringIO, that reads and
019: * writes a string buffer (also known as memory files).
020: * See the description on file objects for operations.
021: * @author Finn Bock, bckfnn@pipmail.dknet.dk
022: * @version cStringIO.java,v 1.10 1999/05/20 18:03:20 fb Exp
023: */
024: public class cStringIO {
025: /**
026: * Create an empty StringIO object
027: * @return a new StringIO object.
028: */
029: public static StringIO StringIO() {
030: return new StringIO();
031: }
032:
033: /**
034: * Create a StringIO object, initialized by the value.
035: * @param buf The initial value.
036: * @return a new StringIO object.
037: */
038: public static StringIO StringIO(String buf) {
039: return new StringIO(buf);
040: }
041:
042: /**
043: * The StringIO object
044: * @see cStringIO#StringIO()
045: * @see cStringIO#StringIO(String)
046: */
047: public static class StringIO extends PyObject {
048: transient public boolean softspace = false;
049: //transient public String name = "<cStringIO>";
050: //transient public String mode = "w";
051: transient public boolean closed = false;
052:
053: transient private char[] buf;
054: transient private int count;
055: transient private int pos;
056:
057: StringIO() {
058: this .buf = new char[16];
059: }
060:
061: StringIO(String buf) {
062: this .buf = new char[buf.length() + 16];
063: write(buf);
064: seek(0);
065: }
066:
067: public void __setattr__(String name, PyObject value) {
068: if (name == "softspace") {
069: softspace = value.__nonzero__();
070: return;
071: }
072: super .__setattr__(name, value);
073: }
074:
075: public PyObject __iter__() {
076: return new PyCallIter(__getattr__("readline"), Py
077: .newString(""));
078: }
079:
080: /**
081: * Free the memory buffer.
082: */
083: public void close() {
084: buf = null;
085: closed = true;
086: }
087:
088: /**
089: * Return false.
090: * @return false.
091: */
092: public boolean isatty() {
093: return false;
094: }
095:
096: /**
097: * Position the file pointer to the absolute position.
098: * @param pos the position in the file.
099: */
100: public void seek(long pos) {
101: seek(pos, 0);
102: }
103:
104: /**
105: * Position the file pointer to the position in the .
106: * @param pos the position in the file.
107: * @param mode; 0=from the start, 1=relative, 2=from the end.
108: */
109: public void seek(long pos, int mode) {
110: if (mode == 1)
111: this .pos = (int) pos + this .pos;
112: else if (mode == 2)
113: this .pos = (int) pos + count;
114: else
115: this .pos = Math.max(0, (int) pos);
116: }
117:
118: /**
119: * Reset the file position to the beginning of the file.
120: */
121: public void reset() {
122: pos = 0;
123: }
124:
125: /**
126: * Return the file position.
127: * @returns the position in the file.
128: */
129: public long tell() {
130: return pos;
131: }
132:
133: /**
134: * Read all data until EOF is reached.
135: * An empty string is returned when EOF is encountered immediately.
136: * @returns A string containing the data.
137: */
138: public String read() {
139: return read(-1);
140: }
141:
142: /**
143: * Read at most size bytes from the file (less if the read hits EOF).
144: * If the size argument is negative, read all data until EOF is
145: * reached. An empty string is returned when EOF is encountered
146: * immediately.
147: * @param size the number of characters to read.
148: * @returns A string containing the data read.
149: */
150: public String read(int size) {
151: opencheck();
152: int newpos = (size < 0) ? count : Math.min(pos + size,
153: count);
154: String r = null;
155: if (size == 1 && newpos > pos) {
156: r = cStringIO.getString(buf[pos]);
157: } else {
158: r = new String(buf, pos, newpos - pos);
159: }
160: pos = newpos;
161: return r;
162: }
163:
164: private int indexOf(char ch, int pos) {
165: for (int i = pos; i < count; i++) {
166: if (buf[i] == ch)
167: return i;
168: }
169: return -1;
170: }
171:
172: /**
173: * Read one entire line from the file. A trailing newline character
174: * is kept in the string (but may be absent when a file ends with
175: * an incomplete line).
176: * An empty string is returned when EOF is hit immediately.
177: * @returns data from the file up to and including the newline.
178: */
179: public String readline() {
180: return readline(-1);
181: }
182:
183: /**
184: * Read one entire line from the file. A trailing newline character
185: * is kept in the string (but may be absent when a file ends with an
186: * incomplete line).
187: * If the size argument is non-negative, it is a maximum byte count
188: * (including the trailing newline) and an incomplete line may be
189: * returned.
190: * @returns data from the file up to and including the newline.
191: */
192: public String readline(int length) {
193: opencheck();
194: int i = indexOf('\n', pos);
195: int newpos = (i < 0) ? count : i + 1;
196: if (length != -1 && pos + length < newpos)
197: newpos = pos + length;
198: String r = new String(buf, pos, newpos - pos);
199: pos = newpos;
200: return r;
201: }
202:
203: /**
204: * Read and return a line without the trailing newling.
205: * Usind by cPickle as an optimization.
206: */
207: public String readlineNoNl() {
208: int i = indexOf('\n', pos);
209: int newpos = (i < 0) ? count : i;
210: String r = new String(buf, pos, newpos - pos);
211: pos = newpos;
212: if (pos < count) // Skip the newline
213: pos++;
214: return r;
215: }
216:
217: /**
218: * Read until EOF using readline() and return a list containing
219: * the lines thus read.
220: * @return a list of the lines.
221: */
222: public PyObject readlines() {
223: return readlines(0);
224: }
225:
226: /**
227: * Read until EOF using readline() and return a list containing
228: * the lines thus read.
229: * @return a list of the lines.
230: */
231: public PyObject readlines(int sizehint) {
232: opencheck();
233: int total = 0;
234: PyList lines = new PyList();
235: String line = readline();
236: while (line.length() > 0) {
237: lines.append(new PyString(line));
238: total += line.length();
239: if (0 < sizehint && sizehint <= total)
240: break;
241: line = readline();
242: }
243: return lines;
244: }
245:
246: /**
247: * truncate the file at the current position.
248: */
249: public void truncate() {
250: truncate(-1);
251: }
252:
253: /**
254: * truncate the file at the position pos.
255: */
256: public void truncate(int pos) {
257: opencheck();
258: if (pos < 0)
259: pos = this .pos;
260: if (count > pos)
261: count = pos;
262: }
263:
264: private void expandCapacity(int newLength) {
265: int newCapacity = (buf.length + 1) * 2;
266: if (newLength > newCapacity) {
267: newCapacity = newLength;
268: }
269:
270: char newBuf[] = new char[newCapacity];
271: System.arraycopy(buf, 0, newBuf, 0, count);
272: buf = newBuf;
273: //System.out.println("newleng:" + newCapacity);
274: }
275:
276: /**
277: * Write a string to the file.
278: * @param s The data to write.
279: */
280: public void write(String s) {
281: opencheck();
282: int newpos = pos + s.length();
283:
284: if (newpos >= buf.length)
285: expandCapacity(newpos);
286: if (newpos > count)
287: count = newpos;
288:
289: s.getChars(0, s.length(), buf, pos);
290: pos = newpos;
291: }
292:
293: /**
294: * Write a char to the file. Used by cPickle as an optimization.
295: * @param ch The data to write.
296: */
297: public void writeChar(char ch) {
298: if (pos + 1 >= buf.length)
299: expandCapacity(pos + 1);
300: buf[pos++] = ch;
301: if (pos > count)
302: count = pos;
303: }
304:
305: /**
306: * Write a list of strings to the file.
307: */
308: public void writelines(String[] lines) {
309: for (int i = 0; i < lines.length; i++) {
310: write(lines[i]);
311: }
312: }
313:
314: /**
315: * Flush the internal buffer. Does nothing.
316: */
317: public void flush() {
318: opencheck();
319: }
320:
321: /**
322: * Retrieve the entire contents of the ``file'' at any time
323: * before the StringIO object's close() method is called.
324: * @return the contents of the StringIO.
325: */
326: public String getvalue() {
327: opencheck();
328: return new String(buf, 0, count);
329: }
330:
331: private final void opencheck() {
332: if (buf == null)
333: throw Py.ValueError("I/O operation on closed file");
334: }
335: }
336:
337: private static String[] strings = new String[256];
338:
339: static String getString(char ch) {
340: if ((int) ch > 255) {
341: return new String(new char[] { ch });
342: }
343:
344: String s = strings[(int) ch];
345:
346: if (s == null) {
347: s = new String(new char[] { ch });
348: strings[(int) ch] = s;
349: }
350: return s;
351: }
352: }
|