/* * Copyright 1998 Finn Bock. * * This program contains material copyrighted by: * Copyright (c) 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, * The Netherlands. */ package org.python.modules; import org.python.core.Py; import org.python.core.PyCallIter; import org.python.core.PyList; import org.python.core.PyObject; import org.python.core.PyString; /** * This module implements a file-like class, StringIO, that reads and * writes a string buffer (also known as memory files). * See the description on file objects for operations. * @author Finn Bock, bckfnn@pipmail.dknet.dk * @version cStringIO.java,v 1.10 1999/05/20 18:03:20 fb Exp */ public class cStringIO { /** * Create an empty StringIO object * @return a new StringIO object. */ public static StringIO StringIO() { return new StringIO(); } /** * Create a StringIO object, initialized by the value. * @param buf The initial value. * @return a new StringIO object. */ public static StringIO StringIO(String buf) { return new StringIO(buf); } /** * The StringIO object * @see cStringIO#StringIO() * @see cStringIO#StringIO(String) */ public static class StringIO extends PyObject { transient public boolean softspace = false; //transient public String name = "<cStringIO>"; //transient public String mode = "w"; transient public boolean closed = false; transient private char[] buf; transient private int count; transient private int pos; StringIO() { this.buf = new char[16]; } StringIO(String buf) { this.buf = new char[buf.length() + 16]; write(buf); seek(0); } public void __setattr__(String name, PyObject value) { if (name == "softspace") { softspace = value.__nonzero__(); return; } super.__setattr__(name, value); } public PyObject __iter__() { return new PyCallIter(__getattr__("readline"), Py.newString("")); } /** * Free the memory buffer. */ public void close() { buf = null; closed = true; } /** * Return false. * @return false. */ public boolean isatty() { return false; } /** * Position the file pointer to the absolute position. * @param pos the position in the file. */ public void seek(long pos) { seek(pos, 0); } /** * Position the file pointer to the position in the . * @param pos the position in the file. * @param mode; 0=from the start, 1=relative, 2=from the end. */ public void seek(long pos, int mode) { if (mode == 1) this.pos = (int) pos + this.pos; else if (mode == 2) this.pos = (int) pos + count; else this.pos = Math.max(0, (int) pos); } /** * Reset the file position to the beginning of the file. */ public void reset() { pos = 0; } /** * Return the file position. * @returns the position in the file. */ public long tell() { return pos; } /** * Read all data until EOF is reached. * An empty string is returned when EOF is encountered immediately. * @returns A string containing the data. */ public String read() { return read(-1); } /** * Read at most size bytes from the file (less if the read hits EOF). * If the size argument is negative, read all data until EOF is * reached. An empty string is returned when EOF is encountered * immediately. * @param size the number of characters to read. * @returns A string containing the data read. */ public String read(int size) { opencheck(); int newpos = (size < 0) ? count : Math.min(pos + size, count); String r = null; if (size == 1 && newpos > pos) { r = cStringIO.getString(buf[pos]); } else { r = new String(buf, pos, newpos - pos); } pos = newpos; return r; } private int indexOf(char ch, int pos) { for (int i = pos; i < count; i++) { if (buf[i] == ch) return i; } return -1; } /** * Read one entire line from the file. A trailing newline character * is kept in the string (but may be absent when a file ends with * an incomplete line). * An empty string is returned when EOF is hit immediately. * @returns data from the file up to and including the newline. */ public String readline() { return readline(-1); } /** * Read one entire line from the file. A trailing newline character * is kept in the string (but may be absent when a file ends with an * incomplete line). * If the size argument is non-negative, it is a maximum byte count * (including the trailing newline) and an incomplete line may be * returned. * @returns data from the file up to and including the newline. */ public String readline(int length) { opencheck(); int i = indexOf('\n', pos); int newpos = (i < 0) ? count : i + 1; if (length != -1 && pos + length < newpos) newpos = pos + length; String r = new String(buf, pos, newpos - pos); pos = newpos; return r; } /** * Read and return a line without the trailing newling. * Usind by cPickle as an optimization. */ public String readlineNoNl() { int i = indexOf('\n', pos); int newpos = (i < 0) ? count : i; String r = new String(buf, pos, newpos - pos); pos = newpos; if (pos < count) // Skip the newline pos++; return r; } /** * Read until EOF using readline() and return a list containing * the lines thus read. * @return a list of the lines. */ public PyObject readlines() { return readlines(0); } /** * Read until EOF using readline() and return a list containing * the lines thus read. * @return a list of the lines. */ public PyObject readlines(int sizehint) { opencheck(); int total = 0; PyList lines = new PyList(); String line = readline(); while (line.length() > 0) { lines.append(new PyString(line)); total += line.length(); if (0 < sizehint && sizehint <= total) break; line = readline(); } return lines; } /** * truncate the file at the current position. */ public void truncate() { truncate(-1); } /** * truncate the file at the position pos. */ public void truncate(int pos) { opencheck(); if (pos < 0) pos = this.pos; if (count > pos) count = pos; } private void expandCapacity(int newLength) { int newCapacity = (buf.length + 1) * 2; if (newLength > newCapacity) { newCapacity = newLength; } char newBuf[] = new char[newCapacity]; System.arraycopy(buf, 0, newBuf, 0, count); buf = newBuf; //System.out.println("newleng:" + newCapacity); } /** * Write a string to the file. * @param s The data to write. */ public void write(String s) { opencheck(); int newpos = pos + s.length(); if (newpos >= buf.length) expandCapacity(newpos); if (newpos > count) count = newpos; s.getChars(0, s.length(), buf, pos); pos = newpos; } /** * Write a char to the file. Used by cPickle as an optimization. * @param ch The data to write. */ public void writeChar(char ch) { if (pos + 1 >= buf.length) expandCapacity(pos + 1); buf[pos++] = ch; if (pos > count) count = pos; } /** * Write a list of strings to the file. */ public void writelines(String[] lines) { for (int i = 0; i < lines.length; i++) { write(lines[i]); } } /** * Flush the internal buffer. Does nothing. */ public void flush() { opencheck(); } /** * Retrieve the entire contents of the ``file'' at any time * before the StringIO object's close() method is called. * @return the contents of the StringIO. */ public String getvalue() { opencheck(); return new String(buf, 0, count); } private final void opencheck() { if (buf == null) throw Py.ValueError("I/O operation on closed file"); } } private static String[] strings = new String[256]; static String getString(char ch) { if ((int) ch > 255) { return new String(new char[] { ch }); } String s = strings[(int) ch]; if (s == null) { s = new String(new char[] { ch }); strings[(int) ch] = s; } return s; } }