Subversion Repositories mkgmap

Rev

Rev 3408 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * 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;
        }
}