/* * Copyright (C) 2009. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 or * version 2 as published by the Free Software Foundation. * * This program 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. See the GNU * General Public License for more details. */ package uk.me.parabola.imgfmt.app.mdr; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; import uk.me.parabola.imgfmt.ExitException; import uk.me.parabola.imgfmt.MapFailedException; import uk.me.parabola.imgfmt.Utils; import uk.me.parabola.imgfmt.app.ImgFileWriter; /** * The string table. This is not used by the device. * * There is a compressed and non-compressed version of this section. * We are starting with the regular string version. * * @author Steve Ratcliffe */ public class Mdr15 extends MdrSection { private final OutputStream stringFile; private int nextOffset; private Map<String, Integer> strings = new HashMap<String, Integer>(); private final Charset charset; private final File tempFile; public Mdr15(MdrConfig config) { setConfig(config); charset = config.getSort().getCharset(); try { tempFile = File.createTempFile("strings", null, config.getOutputDir()); tempFile.deleteOnExit(); stringFile = new BufferedOutputStream(new FileOutputStream(tempFile), 64 * 1024); // reserve the string at offset 0 to be the empty string. stringFile.write(0); nextOffset = 1; } catch (IOException e) { throw new ExitException("Could not create temporary file"); } } public int createString(String str) { Integer offset = strings.get(str); if (offset != null) return offset; int off; try { off = nextOffset; byte[] bytes = str.getBytes(charset); stringFile.write(bytes); stringFile.write(0); // Increase offset for the length of the string and the null byte nextOffset += bytes.length + 1; } catch (IOException e) { // Can't convert, return empty string instead. off = 0; } strings.put(str, off); return off; } /** * Tidy up after reading files. * Close the temporary file, and release the string table which is no longer * needed. */ public void releaseMemory() { strings = null; try { stringFile.close(); } catch (IOException e) { throw new MapFailedException("Could not close string temporary file"); } } public void writeSectData(ImgFileWriter writer) { FileInputStream stream = null; try { stream = new FileInputStream(tempFile); FileChannel channel = stream.getChannel(); ByteBuffer buf = ByteBuffer.allocate(32 * 1024); while (channel.read(buf) > 0) { buf.flip(); writer.put(buf); buf.compact(); } } catch (IOException e) { throw new ExitException("Could not write string section of index"); } finally { Utils.closeFile(stream); } } public int getItemSize() { // variable sized records. return 0; } /** * The meaning of number of items for this section is the largest string * offset possible. We are taking the total size of the string section * for this. */ public int getSizeForRecord() { return numberToPointerSize(nextOffset); } /** * There is no use for this as the records are not fixed length. * * @return Always zero, could return the number of strings. */ protected int numberOfItems() { return 0; } }