/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 2000-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine is distributed in the hope that it will * * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.io; /** This class is used to handle record sizes of a PDBFile. * It is used in most cases with a DataStream. For example: <pre> PDBFile pdb = new PDBFile("Name.Crtr.Type",PDBFile.CREATE); ResizeRecord rs = new ResizeRecord(pdb,512); DataStream ds = new DataStream(rs); rs.startRecord(); ds.writeStringArray(aStringArray); rs.endRecord(); </pre> PS: if you dont call startRecord, writeBytes will simply call PDBFile.writeBytes and will not resize the record! @since SuperWaba 5.8 */ public class ResizeRecord extends Stream // guich@580_19 { /** the associated PDBFile */ private PDBFile cat; /** the intial size of the record */ private int initialSize; /** how many bytes were written */ private int written; /** current record size */ private int size; boolean dontFinalize; private boolean isRecordClosed = true; // flsobral@tc113_30: flag to avoid the execution of endRecord twice for the same record. private boolean isClosing; // flsobral@tc113_30 /** Constructs the resize stream. @param cat The PDBFile associated @param initialSize The initial size of the record. CANNOT BE 0! */ public ResizeRecord(PDBFile cat, int initialSize) { this.cat = cat; this.initialSize = initialSize; } /** * Inserts the record at the specified index in the PDBFile. * * @param pos * The position where to insert the record. If greater or equal to the record count, the record is * appended. * @throws IOException * @since SuperWaba 1.21. * * @see #startRecord() * @see #restartRecord(int) * @see #endRecord() */ public void startRecord(int pos) throws IOException // flsobral@tc100b5_49: returning boolean is no longer necessary. { if (pos >= cat.getRecordCount()) // append? cat.addRecord(initialSize); else cat.addRecord(initialSize, pos); written = 0; size = initialSize; isRecordClosed = false; } /** * Appends a new record to the PDBFile. * * @throws IOException * @see #restartRecord(int) * @see #startRecord(int) * @see #endRecord() */ public void startRecord() throws IOException { cat.addRecord(initialSize); // guich@200b4_96 written = 0; size = initialSize; isRecordClosed = false; } /** Restart writing to the given record pos, overwritting the current record. * @param pos The position to overwrite. If pos is lower than 0 or greater than the * number of records of the PDBFile, the record is appended. * @see #startRecord() * @see #startRecord(int) * @see #endRecord() */ public boolean restartRecord(int pos) throws IOException { if (pos < 0 || pos >= cat.getRecordCount()) // append? guich@310_4: check if < 0 startRecord(); else { written = 0; size = initialSize; cat.setRecordPos(pos); // guich@241_14 size = cat.getRecordSize(); // guich@300_35: initialize to the current record size } return true; } /** Must be called after the record is finished so it can be properly resized. * @see #startRecord() * @see #restartRecord(int) * @see #startRecord(int) */ public void endRecord() throws IOException { if (!isRecordClosed) { isRecordClosed = true; if (written > 0) // guich@400_22 { if (written != size) // guich@550_12: only call resizeRecord if there were a change cat.resizeRecord(written); } else cat.deleteRecord(); size = 0; } } public int readBytes(byte buf[], int start, int count) throws totalcross.io.IOException { return cat.readBytes(buf, start, count); } public int writeBytes(byte buf[], int start, int count) throws totalcross.io.IOException { if (size == 0) return cat.writeBytes(buf, start, count); if (count - start <= 0) return 0; int total = written + (count - start); while (total > size) // no more space? { if (size == 65520) return -1; // guich@550_14: avoid infinite recursion size += initialSize; if (size > 65520) size = 65520; // guich@500_7: avoid blowing up the buffer try { cat.resizeRecord(size); // expand } catch (IOException e) { return -1; } } int n = cat.writeBytes(buf, start, count); if (n >= 0) written += n; return n; } /** * closes the PDBFile * * @throws totalcross.io.IOException */ public void close() throws totalcross.io.IOException { if (isClosing) // flsobral@tc113_30 return; isClosing = true; //cat.close(); guich@tc122_45 dontFinalize = true; } /** Returns the stream attached to this stream (which is always a PDBFile). */ public Stream getStream() { return cat; } protected void finalize() { try { if (cat.mode != -1) endRecord(); close(); } catch (IOException ex) { } } }