/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; /** * The list of available shared strings. This class contains * the labels used for the entire spreadsheet */ class SharedStrings { /** * All the strings in the spreadsheet, keyed on the string itself */ private HashMap strings; /** * Contains the same strings, held in a list */ private ArrayList stringList; /** * The total occurrence of strings in the workbook */ private int totalOccurrences; /** * Constructor */ public SharedStrings() { strings = new HashMap(100); stringList = new ArrayList(100); totalOccurrences = 0; } /** * Gets the index for the string passed in. If the string is already * present, then returns the index of that string, otherwise * creates a new key-index mapping * * @param s the string whose index we want * @return the index of the string */ public int getIndex(String s) { Integer i = (Integer) strings.get(s); if (i == null) { i = new Integer(strings.size()); strings.put(s, i); stringList.add(s); } totalOccurrences++; return i.intValue(); } /** * Gets the string at the specified index * * @param i the index of the string * @return the string at the specified index */ public String get(int i) { return (String) stringList.get(i); } /** * Writes out the shared string table * * @param outputFile the binary output file * @exception IOException */ public void write(File outputFile) throws IOException { // Thanks to Guenther for contributing the ExtSST implementation portion // of this method int charsLeft = 0; String curString = null; SSTRecord sst = new SSTRecord(totalOccurrences, stringList.size()); ExtendedSSTRecord extsst = new ExtendedSSTRecord(stringList.size()); int bucketSize = extsst.getNumberOfStringsPerBucket(); Iterator i = stringList.iterator(); int stringIndex = 0; while (i.hasNext() && charsLeft == 0) { curString = (String) i.next(); // offset + header bytes int relativePosition = sst.getOffset() + 4; charsLeft = sst.add(curString); if ((stringIndex % bucketSize) == 0) { extsst.addString(outputFile.getPos(), relativePosition); } stringIndex++; } outputFile.write(sst); if (charsLeft != 0 || i.hasNext()) { // Add the remainder of the string to the continue record SSTContinueRecord cont = createContinueRecord(curString, charsLeft, outputFile); // Carry on looping through the array until all the strings are done while (i.hasNext()) { curString = (String) i.next(); int relativePosition = cont.getOffset() + 4; charsLeft = cont.add(curString); if ((stringIndex % bucketSize) == 0) { extsst.addString(outputFile.getPos(), relativePosition); } stringIndex++; if (charsLeft != 0) { outputFile.write(cont); cont = createContinueRecord(curString, charsLeft, outputFile); } } outputFile.write(cont); } outputFile.write(extsst); } /** * Creates and returns a continue record using the left over bits and * pieces */ private SSTContinueRecord createContinueRecord (String curString, int charsLeft, File outputFile) throws IOException { // Set up the remainder of the string in the continue record SSTContinueRecord cont = null; while (charsLeft != 0) { cont = new SSTContinueRecord(); if (charsLeft == curString.length() || curString.length() == 0) { charsLeft = cont.setFirstString(curString, true); } else { charsLeft = cont.setFirstString (curString.substring(curString.length() - charsLeft), false); } if (charsLeft != 0) { outputFile.write(cont); cont = new SSTContinueRecord(); } } return cont; } }