]> source.dussan.org Git - poi.git/commitdiff
rewrite Sttb utils to handle complex cases
authorSergey Vladimirov <sergey@apache.org>
Fri, 30 Sep 2011 13:16:50 +0000 (13:16 +0000)
committerSergey Vladimirov <sergey@apache.org>
Fri, 30 Sep 2011 13:16:50 +0000 (13:16 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1177643 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hwpf/model/BookmarksTables.java
src/scratchpad/src/org/apache/poi/hwpf/model/RevisionMarkAuthorTable.java
src/scratchpad/src/org/apache/poi/hwpf/model/SavedByTable.java
src/scratchpad/src/org/apache/poi/hwpf/model/SttbUtils.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/model/SttbfUtils.java [deleted file]

index bc2d21f15cbedbb980a43b3cfeceecc01579c364..29910b0b91f1bcb6b05e523a6134f405dded13d2 100644 (file)
@@ -21,12 +21,10 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import org.apache.poi.util.POILogFactory;
-
-import org.apache.poi.util.POILogger;
-
 import org.apache.poi.hwpf.model.io.HWPFOutputStream;
 import org.apache.poi.util.Internal;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
 
 @Internal
 public class BookmarksTables
@@ -120,8 +118,8 @@ public class BookmarksTables
         int namesLength = fib.getLcbSttbfbkmk();
 
         if ( namesStart != 0 && namesLength != 0 )
-            this.names = new ArrayList<String>( Arrays.asList( SttbfUtils.read(
-                    tableStream, namesStart ) ) );
+            this.names = new ArrayList<String>( Arrays.asList( SttbUtils
+                    .readSttbfBkmk( tableStream, namesStart ) ) );
 
         int firstDescriptorsStart = fib.getFcPlcfbkf();
         int firstDescriptorsLength = fib.getLcbPlcfbkf();
@@ -196,8 +194,8 @@ public class BookmarksTables
         }
 
         int start = tableStream.getOffset();
-        SttbfUtils
-                .write( tableStream, names.toArray( new String[names.size()] ) );
+        SttbUtils.writeSttbfBkmk( names.toArray( new String[names.size()] ),
+                tableStream );
         int end = tableStream.getOffset();
 
         fib.setFcSttbfbkmk( start );
index 1f86dc64fbabc704dfb6c8aa5833ea6d1c3bf4e6..b1347d0e7663243e5489ec21e97478425707ce50 100644 (file)
@@ -24,8 +24,6 @@ import java.util.List;
 
 import org.apache.poi.hwpf.model.io.HWPFOutputStream;
 import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.StringUtil;
 
 /**
  * String table containing the names of authors of revision marks, e-mails and
@@ -35,21 +33,6 @@ import org.apache.poi.util.StringUtil;
  */
 @Internal
 public final class RevisionMarkAuthorTable {
-       /**
-        * must be 0xFFFF
-        */
-       private short fExtend = (short) 0xFFFF;
-       
-       /**
-        * the number of entries in the table
-        */
-       private short cData = 0;
-       
-       /**
-        * must be 0
-        */
-       private short cbExtra = 0;
-
        /**
         * Array of entries.
         */
@@ -62,36 +45,11 @@ public final class RevisionMarkAuthorTable {
         * @param offset the offset into the byte array.
         * @param size the size of the table in the byte array.
         */
-       public RevisionMarkAuthorTable(byte[] tableStream, int offset, int size) throws IOException {
-               // Read fExtend - it isn't used
-               fExtend = LittleEndian.getShort(tableStream, offset);
-               if(fExtend != 0xFFFF) {
-                       //TODO: throw an exception here?
-               }
-               offset += 2;
-
-               // Read the number of entries
-               cData = LittleEndian.getShort(tableStream, offset);
-               offset += 2;
-
-               // Read cbExtra - it isn't used
-               cbExtra = LittleEndian.getShort(tableStream, offset);
-               if(cbExtra != 0) {
-                       //TODO: throw an exception here?
-               }
-               offset += 2;
-               
-               entries = new String[cData];
-               for (int i = 0; i < cData; i++) {
-                       int len = LittleEndian.getShort(tableStream, offset);
-                       offset += 2;
-                       
-                       String name = StringUtil.getFromUnicodeLE(tableStream, offset, len);
-                       offset += len * 2;
-
-                       entries[i] = name;
-               }
-       }
+    public RevisionMarkAuthorTable( byte[] tableStream, int offset, int size )
+            throws IOException
+    {
+        entries = SttbUtils.readSttbfRMark( tableStream, offset );
+    }
 
        /**
         * Gets the entries. The returned list cannot be modified.
@@ -121,7 +79,7 @@ public final class RevisionMarkAuthorTable {
         * @return the number of entries.
         */
        public int getSize() {
-               return cData;
+               return entries.length;
        }
 
        /**
@@ -130,19 +88,9 @@ public final class RevisionMarkAuthorTable {
         * @param tableStream  the table stream to write to.
         * @throws IOException  if an error occurs while writing.
         */
-       public void writeTo(HWPFOutputStream tableStream) throws IOException {
-               byte[] header = new byte[6];
-               LittleEndian.putShort(header, 0, fExtend);
-               LittleEndian.putShort(header, 2, cData);
-               LittleEndian.putShort(header, 4, cbExtra);
-               tableStream.write(header);
-
-               for (String name : entries) {
-                       byte[] buf = new byte[name.length() * 2 + 2];
-                       LittleEndian.putShort(buf, 0, (short) name.length());
-                       StringUtil.putUnicodeLE(name, buf, 2);
-                       tableStream.write(buf);
-               }
-       }
+    public void writeTo( HWPFOutputStream tableStream ) throws IOException
+    {
+        SttbUtils.writeSttbfRMark( entries, tableStream );
+    }
 
 }
index 078acd109612ac6f0d5ac12c0843a8cd2936f5ea..87c7a8ef98293768876eb907f40cf86926aaa26d 100644 (file)
@@ -14,7 +14,6 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 ==================================================================== */
-
 package org.apache.poi.hwpf.model;
 
 import java.io.IOException;
@@ -26,55 +25,32 @@ import org.apache.poi.hwpf.model.io.HWPFOutputStream;
 import org.apache.poi.util.Internal;
 
 /**
- * String table containing the history of the last few revisions ("saves") of the document.
- * Read-only for the time being.
- *
+ * String table containing the history of the last few revisions ("saves") of
+ * the document. Read-only for the time being.
+ * 
  * @author Daniel Noll
  */
 @Internal
 public final class SavedByTable
 {
+    /**
+     * Array of entries.
+     */
+    private SavedByEntry[] entries;
 
-  /**
-   * Array of entries.
-   */
-  private SavedByEntry[] entries;
-
-  /**
-   * Constructor to read the table from the table stream.
-   *
-   * @param tableStream the table stream.
-   * @param offset the offset into the byte array.
-   * @param size the size of the table in the byte array.
-   */
-  public SavedByTable(byte[] tableStream, int offset, int size)
-  {      
-//    // Read the value that I don't know what it does. :-)
-//    unknownValue = LittleEndian.getShort(tableStream, offset);
-//    offset += 2;
-//
-//    // The stored int is the number of strings, and there are two strings per entry.
-//    int numEntries = LittleEndian.getInt(tableStream, offset) / 2;
-//    offset += 4;
-//
-//    entries = new SavedByEntry[numEntries];
-//    for (int i = 0; i < numEntries; i++)
-//    {
-//      int len = LittleEndian.getShort(tableStream, offset);
-//      offset += 2;
-//      String userName = StringUtil.getFromUnicodeLE(tableStream, offset, len);
-//      offset += len * 2;
-//      len = LittleEndian.getShort(tableStream, offset);
-//      offset += 2;
-//      String saveLocation = StringUtil.getFromUnicodeLE(tableStream, offset, len);
-//      offset += len * 2;
-//
-//      entries[i] = new SavedByEntry(userName, saveLocation);
-//    }
-
-        // first value is mark for extended STTBF ;) -- sergey
-        String[] strings = SttbfUtils.read( tableStream, offset );
-
+    /**
+     * Constructor to read the table from the table stream.
+     * 
+     * @param tableStream
+     *            the table stream.
+     * @param offset
+     *            the offset into the byte array.
+     * @param size
+     *            the size of the table in the byte array.
+     */
+    public SavedByTable( byte[] tableStream, int offset, int size )
+    {
+        String[] strings = SttbUtils.readSttbSavedBy( tableStream, offset );
         int numEntries = strings.length / 2;
         entries = new SavedByEntry[numEntries];
         for ( int i = 0; i < numEntries; i++ )
@@ -83,15 +59,15 @@ public final class SavedByTable
         }
     }
 
-  /**
-   * Gets the entries.  The returned list cannot be modified.
-   *
-   * @return the list of entries.
-   */
-  public List<SavedByEntry> getEntries()
-  {
-    return Collections.unmodifiableList(Arrays.asList(entries));
-  }
+    /**
+     * Gets the entries. The returned list cannot be modified.
+     * 
+     * @return the list of entries.
+     */
+    public List<SavedByEntry> getEntries()
+    {
+        return Collections.unmodifiableList( Arrays.asList( entries ) );
+    }
 
     /**
      * Writes this table to the table stream.
@@ -110,7 +86,7 @@ public final class SavedByTable
             toSave[counter++] = entry.getUserName();
             toSave[counter++] = entry.getSaveLocation();
         }
-        SttbfUtils.write( tableStream, toSave );
+        SttbUtils.writeSttbSavedBy( toSave, tableStream );
     }
 
 }
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/SttbUtils.java b/src/scratchpad/src/org/apache/poi/hwpf/model/SttbUtils.java
new file mode 100644 (file)
index 0000000..1cc11e0
--- /dev/null
@@ -0,0 +1,211 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+package org.apache.poi.hwpf.model;
+
+import java.io.IOException;
+
+import org.apache.poi.hwpf.model.io.HWPFOutputStream;
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.StringUtil;
+
+/**
+ * Utils class for storing and reading "STring TaBle stored in File"
+ * 
+ * @author Sergey Vladimirov (vlsergey {at} gmail {dot} com)
+ */
+@Internal
+class SttbUtils
+{
+
+    static class Sttb
+    {
+        public int cbExtra;
+
+        public int cDataLength;
+
+        public String[] data;
+
+        public byte[][] extraData;
+    }
+
+    private static final int CBEXTRA_STTB_SAVED_BY = 0; // bytes
+
+    private static final int CBEXTRA_STTBF_BKMK = 0; // bytes
+
+    private static final int CBEXTRA_STTBF_R_MARK = 0; // bytes
+
+    private static final int CDATA_SIZE_STTB_SAVED_BY = 2; // bytes
+
+    private static final int CDATA_SIZE_STTBF_BKMK = 2; // bytes
+
+    private static final int CDATA_SIZE_STTBF_R_MARK = 2; // bytes
+
+    static Sttb read( int cDataLength, byte[] buffer, int startOffset )
+    {
+        short ffff = LittleEndian.getShort( buffer, startOffset );
+        int offset = startOffset + 2;
+
+        if ( ffff != (short) 0xffff )
+        {
+            // Non-extended character Pascal strings
+            throw new UnsupportedOperationException(
+                    "Non-extended character Pascal strings are not supported right now. "
+                            + "Please, contact POI developers for update." );
+        }
+        // strings are extended character strings
+
+        int cData = cDataLength == 2 ? LittleEndian.getUShort( buffer, offset )
+                : LittleEndian.getInt( buffer, offset );
+        offset += cDataLength;
+
+        Sttb sttb = new Sttb();
+        sttb.cDataLength = cDataLength;
+        sttb.cbExtra = LittleEndian.getUShort( buffer, offset );
+        offset += 2;
+
+        sttb.data = new String[cData];
+        sttb.extraData = new byte[cData][];
+
+        for ( int i = 0; i < cData; i++ )
+        {
+            int cchData = LittleEndian.getShort( buffer, offset );
+            offset += 2;
+
+            if ( cchData < 0 )
+                continue;
+
+            sttb.data[i] = StringUtil
+                    .getFromUnicodeLE( buffer, offset, cchData );
+            offset += cchData * 2;
+
+            sttb.extraData[i] = LittleEndian.getByteArray( buffer, offset,
+                    sttb.cbExtra );
+            offset += sttb.cbExtra;
+        }
+
+        return sttb;
+    }
+
+    static String[] readSttbfBkmk( byte[] buffer, int startOffset )
+    {
+        return read( CDATA_SIZE_STTBF_BKMK, buffer, startOffset ).data;
+    }
+
+    static String[] readSttbfRMark( byte[] buffer, int startOffset )
+    {
+        return read( CDATA_SIZE_STTBF_R_MARK, buffer, startOffset ).data;
+    }
+
+    static String[] readSttbSavedBy( byte[] buffer, int startOffset )
+    {
+        return read( CDATA_SIZE_STTB_SAVED_BY, buffer, startOffset ).data;
+    }
+
+    static void write( Sttb sttb, HWPFOutputStream tableStream )
+            throws IOException
+    {
+        final int headerSize = sttb.cDataLength == 2 ? 6 : 8;
+
+        byte[] header = new byte[headerSize];
+        LittleEndian.putShort( header, 0, (short) 0xffff );
+
+        if ( sttb.data == null || sttb.data.length == 0 )
+        {
+            if ( sttb.cDataLength == 4 )
+            {
+                LittleEndian.putInt( header, 2, 0 );
+                LittleEndian.putUShort( header, 6, sttb.cbExtra );
+                tableStream.write( header );
+                return;
+            }
+
+            LittleEndian.putUShort( header, 2, 0 );
+            LittleEndian.putUShort( header, 4, sttb.cbExtra );
+            tableStream.write( header );
+            return;
+        }
+
+        if ( sttb.cDataLength == 4 )
+        {
+            LittleEndian.putInt( header, 2, sttb.data.length );
+            LittleEndian.putUShort( header, 6, sttb.cbExtra );
+            tableStream.write( header );
+        }
+        else
+        {
+            LittleEndian.putUShort( header, 2, sttb.data.length );
+            LittleEndian.putUShort( header, 4, sttb.cbExtra );
+            tableStream.write( header );
+        }
+
+        for ( int i = 0; i < sttb.data.length; i++ )
+        {
+            String entry = sttb.data[i];
+            if ( entry == null )
+            {
+                // is it correct?
+                tableStream.write( new byte[] { -1, 0 } );
+                continue;
+            }
+
+            byte[] buf = new byte[entry.length() * 2 + sttb.cbExtra + 2];
+
+            LittleEndian.putShort( buf, 0, (short) entry.length() );
+            StringUtil.putUnicodeLE( entry, buf, 2 );
+
+            if ( sttb.extraData != null && i < sttb.extraData.length
+                    && sttb.extraData[i] != null )
+                System.arraycopy( sttb.extraData[i], 0, buf,
+                        entry.length() * 2,
+                        Math.min( sttb.extraData[i].length, sttb.cbExtra ) );
+
+            tableStream.write( buf );
+        }
+    }
+
+    static void writeSttbfBkmk( String[] data, HWPFOutputStream tableStream )
+            throws IOException
+    {
+        Sttb sttb = new Sttb();
+        sttb.cDataLength = CDATA_SIZE_STTBF_BKMK;
+        sttb.data = data;
+        sttb.cbExtra = CBEXTRA_STTBF_BKMK;
+        write( sttb, tableStream );
+    }
+
+    static void writeSttbfRMark( String[] data, HWPFOutputStream tableStream )
+            throws IOException
+    {
+        Sttb sttb = new Sttb();
+        sttb.cDataLength = CDATA_SIZE_STTBF_R_MARK;
+        sttb.data = data;
+        sttb.cbExtra = CBEXTRA_STTBF_R_MARK;
+        write( sttb, tableStream );
+    }
+
+    static void writeSttbSavedBy( String[] data, HWPFOutputStream tableStream )
+            throws IOException
+    {
+        Sttb sttb = new Sttb();
+        sttb.cDataLength = CDATA_SIZE_STTB_SAVED_BY;
+        sttb.data = data;
+        sttb.cbExtra = CBEXTRA_STTB_SAVED_BY;
+        write( sttb, tableStream );
+    }
+
+}
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/SttbfUtils.java b/src/scratchpad/src/org/apache/poi/hwpf/model/SttbfUtils.java
deleted file mode 100644 (file)
index 8b5bd92..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-package org.apache.poi.hwpf.model;
-
-import java.io.IOException;
-
-import org.apache.poi.hwpf.model.io.HWPFOutputStream;
-import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.StringUtil;
-
-/**
- * Utils for storing and reading "STring TaBle stored in File"
- * 
- * @author Sergey Vladimirov (vlsergey {at} gmail {dot} com)
- */
-@Internal
-class SttbfUtils
-{
-    public static String[] read( byte[] data, int startOffset )
-    {
-        short ffff = LittleEndian.getShort( data, startOffset );
-
-        if ( ffff != (short) 0xffff )
-        {
-            // Non-extended character Pascal strings
-            throw new UnsupportedOperationException(
-                    "Non-extended character Pascal strings are not supported right now. "
-                            + "Please, contact POI developers for update." );
-        }
-
-        // strings are extended character strings
-        int offset = startOffset + 2;
-        int numEntries = LittleEndian.getInt( data, offset );
-        offset += 4;
-
-        String[] entries = new String[numEntries];
-        for ( int i = 0; i < numEntries; i++ )
-        {
-            int len = LittleEndian.getShort( data, offset );
-            offset += 2;
-            String value = StringUtil.getFromUnicodeLE( data, offset, len );
-            offset += len * 2;
-            entries[i] = value;
-        }
-        return entries;
-    }
-
-    public static int write( HWPFOutputStream tableStream, String[] entries )
-            throws IOException
-    {
-        byte[] header = new byte[6];
-        LittleEndian.putShort( header, 0, (short) 0xffff );
-
-        if ( entries == null || entries.length == 0 )
-        {
-            LittleEndian.putInt( header, 2, 0 );
-            tableStream.write( header );
-            return 6;
-        }
-
-        LittleEndian.putInt( header, 2, entries.length );
-        tableStream.write( header );
-        int size = 6;
-
-        for ( String entry : entries )
-        {
-            byte[] buf = new byte[entry.length() * 2 + 2];
-            LittleEndian.putShort( buf, 0, (short) entry.length() );
-            StringUtil.putUnicodeLE( entry, buf, 2 );
-            tableStream.write( buf );
-            size += buf.length;
-        }
-
-        return size;
-    }
-
-}