poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject svn commit: r703620 - in /poi/trunk/src: documentation/content/xdocs/ java/org/apache/poi/hssf/record/ testcases/org/apache/poi/hssf/record/
Date Sat, 11 Oct 2008 01:11:06 GMT
Author: josh
Date: Fri Oct 10 18:11:05 2008
New Revision: 703620

URL: http://svn.apache.org/viewvc?rev=703620&view=rev
Log:
fix for bug 45866 - allowed for change of unicode compression across Continue records

Added:
    poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordInputStream.java
Modified:
    poi/trunk/src/documentation/content/xdocs/changes.xml
    poi/trunk/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/hssf/record/RecordInputStream.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/TestUnicodeString.java

Modified: poi/trunk/src/documentation/content/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/changes.xml?rev=703620&r1=703619&r2=703620&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/changes.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/changes.xml Fri Oct 10 18:11:05 2008
@@ -37,6 +37,7 @@
 
 		<!-- Don't forget to update status.xml too! -->
         <release version="3.2-alpha1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">45866 - allowed for change of unicode
compression across Continue records</action>
            <action dev="POI-DEVELOPERS" type="fix">45964 - support for link formulas
in Text Objects</action>
            <action dev="POI-DEVELOPERS" type="fix">43354 - support for evalating formulas
with missing args</action>
            <action dev="POI-DEVELOPERS" type="fix">45912 - fixed ArrayIndexOutOfBoundsException
in EmbeddedObjectRefSubRecord</action>

Modified: poi/trunk/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/status.xml?rev=703620&r1=703619&r2=703620&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/status.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/status.xml Fri Oct 10 18:11:05 2008
@@ -34,6 +34,7 @@
 	<!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.2-alpha1" date="2008-??-??">
+           <action dev="POI-DEVELOPERS" type="fix">45866 - allowed for change of unicode
compression across Continue records</action>
            <action dev="POI-DEVELOPERS" type="fix">45964 - support for link formulas
in Text Objects</action>
            <action dev="POI-DEVELOPERS" type="fix">43354 - support for evalating formulas
with missing args</action>
            <action dev="POI-DEVELOPERS" type="fix">45912 - fixed ArrayIndexOutOfBoundsException
in EmbeddedObjectRefSubRecord</action>

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/RecordInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/RecordInputStream.java?rev=703620&r1=703619&r2=703620&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/RecordInputStream.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/RecordInputStream.java Fri Oct 10 18:11:05
2008
@@ -218,54 +218,81 @@
 		return result;
 	}
 
-  /**
-   *  given a byte array of 16-bit unicode characters, compress to 8-bit and
-   *  return a string
-   *
-   * { 0x16, 0x00 } -0x16
-   *
-   * @param length the length of the final string
-   * @return                                     the converted string
-   * @exception  IllegalArgumentException        if len is too large (i.e.,
-   *      there is not enough data in string to create a String of that
-   *      length)
-   */
-  public String readUnicodeLEString(int length) {
-    if ((length < 0) || (((remaining() / 2) < length) && !isContinueNext()))
{
-            throw new IllegalArgumentException("Illegal length - asked for " + length + "
but only " + (remaining()/2) + " left!");
-    }
-
-    StringBuffer buf = new StringBuffer(length);
-    for (int i=0;i<length;i++) {
-      if ((remaining() == 0) && (isContinueNext())){
-        nextRecord();
-        int compressByte = readByte();
-        if(compressByte != 1) throw new IllegalArgumentException("compressByte in continue
records must be 1 while reading unicode LE string");
-      }
-      char ch = (char)readShort();
-      buf.append(ch);
-    }
-    return buf.toString();
-  }
+	public String readString() {
+		int requestedLength = readUShort();
+		byte compressFlag = readByte();
+		return readStringCommon(requestedLength, compressFlag == 0);
+	}
+	/**
+	 *  given a byte array of 16-bit unicode characters, compress to 8-bit and
+	 *  return a string
+	 *
+	 * { 0x16, 0x00 } -0x16
+	 *
+	 * @param requestedLength the length of the final string
+	 * @return                                     the converted string
+	 * @exception  IllegalArgumentException        if len is too large (i.e.,
+	 *      there is not enough data in string to create a String of that
+	 *      length)
+	 */
+	public String readUnicodeLEString(int requestedLength) {
+		return readStringCommon(requestedLength, false);
+	}
 
-  public String readCompressedUnicode(int length) {
-    if ((length < 0) || ((remaining() < length) && !isContinueNext())) {
-            throw new IllegalArgumentException("Illegal length " + length);
-    }
+	public String readCompressedUnicode(int requestedLength) {
+		return readStringCommon(requestedLength, true);
+	}
 
-    StringBuffer buf = new StringBuffer(length);
-    for (int i=0;i<length;i++) {
-      if ((remaining() == 0) && (isContinueNext())) {
-          nextRecord();
-          int compressByte = readByte();
-          if(compressByte != 0) throw new IllegalArgumentException("compressByte in continue
records must be 0 while reading compressed unicode");
-      }
-      byte b = readByte();
-      char ch = (char)(0x00FF & b); // avoid sex
-      buf.append(ch);
-    }
-    return buf.toString();
-  }
+	private String readStringCommon(int requestedLength, boolean pIsCompressedEncoding) {
+		// Sanity check to detect garbage string lengths
+		if (requestedLength < 0 || requestedLength > 0x100000) { // 16 million chars?
+			throw new IllegalArgumentException("Bad requested string length (" + requestedLength +
")");
+		}
+		char[] buf = new char[requestedLength];
+		boolean isCompressedEncoding = pIsCompressedEncoding;
+		int curLen = 0;
+		while(true) {
+			int availableChars =isCompressedEncoding ?  remaining() : remaining() / LittleEndian.SHORT_SIZE;
+			if (requestedLength - curLen <= availableChars) {
+				// enough space in current record, so just read it out
+				while(curLen < requestedLength) {
+					char ch;
+					if (isCompressedEncoding) {
+						ch = (char)readUByte();
+					} else {
+						ch = (char)readShort();
+					}
+					buf[curLen] = ch;
+					curLen++;
+				}
+				return new String(buf);
+			}
+			// else string has been spilled into next continue record
+			// so read what's left of the current record
+			while(availableChars > 0) {
+				char ch;
+				if (isCompressedEncoding) {
+					ch = (char)readUByte();
+				} else {
+					ch = (char)readShort();
+				}
+				buf[curLen] = ch;
+				curLen++;
+				availableChars--;
+			}
+			if (!isContinueNext()) {
+				throw new RecordFormatException("Expected to find a ContinueRecord in order to read remaining
" 
+						+ (requestedLength-curLen) + " of " + requestedLength + " chars");
+			}
+			if(remaining() != 0) {
+				throw new RecordFormatException("Odd number of bytes(" + remaining() + ") left behind");
+			}
+			nextRecord();
+			// note - the compressed flag may change on the fly
+			byte compressFlag = readByte();
+			isCompressedEncoding = (compressFlag == 0); 
+		}
+	}
 
   /** Returns an excel style unicode string from the bytes reminaing in the record.
    * <i>Note:</i> Unicode strings differ from <b>normal</b> strings
due to the addition of

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java?rev=703620&r1=703619&r2=703620&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java Fri Oct 10 18:11:05
2008
@@ -84,6 +84,7 @@
 		result.addTestSuite(TestPaneRecord.class);
 		result.addTestSuite(TestPlotAreaRecord.class);
 		result.addTestSuite(TestPlotGrowthRecord.class);
+		result.addTestSuite(TestRecordInputStream.class);
 		result.addTestSuite(TestRecordFactory.class);
 		result.addTestSuite(TestSCLRecord.class);
 		result.addTestSuite(TestSSTDeserializer.class);

Added: poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordInputStream.java?rev=703620&view=auto
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordInputStream.java (added)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordInputStream.java Fri Oct
10 18:11:05 2008
@@ -0,0 +1,97 @@
+/* ====================================================================
+   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.hssf.record;
+
+import org.apache.poi.util.HexRead;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link RecordInputStream}
+ *
+ * @author Josh Micich
+ */
+public final class TestRecordInputStream extends TestCase {
+
+	/**
+	 * Data inspired by attachment 22626 of bug 45866<br/>
+	 * A unicode string of 18 chars, with a continue record where the compression flag changes
+	 */
+	private static final String HED_DUMP1 = ""
+			+ "1A 59 00 8A 9E 8A " // 3 uncompressed unicode chars
+			+ "3C 00 " // Continue sid
+			+ "10 00 " // rec size 16 (1+15)
+			+ "00"	// next chunk is compressed
+			+ "20 2D 20 4D 75 6C 74 69 6C 69 6E 67 75 61 6C " // 15 chars
+	;
+	/**
+	 * same string re-arranged
+	 */
+	private static final String HED_DUMP2 = ""
+			// 15 chars at end of current record
+			+ "4D 75 6C 74 69 6C 69 6E 67 75 61 6C 20 2D 20"
+			+ "3C 00 " // Continue sid
+			+ "07 00 " // rec size 7 (1+6)
+			+ "01"	// this bit uncompressed
+			+ "1A 59 00 8A 9E 8A " // 3 uncompressed unicode chars
+	;
+	public void testChangeOfCompressionFlag_bug25866() {
+		byte[] changingFlagSimpleData = HexRead.readFromString(""
+				+ "AA AA "  // fake SID
+				+ "06 00 "  // first rec len 6
+				+ HED_DUMP1
+				);
+		RecordInputStream in = TestcaseRecordInputStream.create(changingFlagSimpleData);
+		String actual;
+		try {
+			actual = in.readUnicodeLEString(18);
+		} catch (IllegalArgumentException e) {
+			if ("compressByte in continue records must be 1 while reading unicode LE string".equals(e.getMessage()))
{
+				throw new AssertionFailedError("Identified bug 45866");
+			}
+				
+			throw e;
+		}
+		assertEquals("\u591A\u8A00\u8A9E - Multilingual", actual);
+	}
+
+	public void testChangeFromUnCompressedToCompressed() {
+		byte[] changingFlagSimpleData = HexRead.readFromString(""
+				+ "AA AA "  // fake SID
+				+ "0F 00 "  // first rec len 15
+				+ HED_DUMP2
+				);
+		RecordInputStream in = TestcaseRecordInputStream.create(changingFlagSimpleData);
+		String actual = in.readCompressedUnicode(18);
+		assertEquals("Multilingual - \u591A\u8A00\u8A9E", actual);
+	}
+	
+	public void testReadString() {
+		byte[] changingFlagFullData = HexRead.readFromString(""
+				+ "AA AA "  // fake SID
+				+ "12 00 "  // first rec len 18 (15 + next 3 bytes)
+				+ "12 00 "  // total chars 18
+				+ "00 "	 // this bit compressed
+				+ HED_DUMP2
+				);
+		RecordInputStream in = TestcaseRecordInputStream.create(changingFlagFullData);
+		String actual = in.readString();
+		assertEquals("Multilingual - \u591A\u8A00\u8A9E", actual);
+	}
+}

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/TestUnicodeString.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/TestUnicodeString.java?rev=703620&r1=703619&r2=703620&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/TestUnicodeString.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/TestUnicodeString.java Fri Oct 10 18:11:05
2008
@@ -1,4 +1,3 @@
-
 /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -19,6 +18,8 @@
 
 package org.apache.poi.hssf.record;
 
+import org.apache.poi.util.HexRead;
+
 import junit.framework.TestCase;
 
 /**
@@ -26,18 +27,10 @@
  *
  * @author Jason Height (jheight at apache.org)
  */
-public class TestUnicodeString
-        extends TestCase
-{
+public final class TestUnicodeString extends TestCase {
 
-    public TestUnicodeString( String s )
-    {
-        super( s );
-    }
 
-    public void testSmallStringSize()
-            throws Exception
-    {
+    public void testSmallStringSize() {
         //Test a basic string
         UnicodeString s = makeUnicodeString("Test");
         UnicodeString.UnicodeRecordStats stats = new UnicodeString.UnicodeRecordStats();
@@ -80,9 +73,7 @@
         assertEquals(30, stats.recordSize);
     }
 
-    public void testPerfectStringSize()
-            throws Exception
-    {
+    public void testPerfectStringSize() {
       //Test a basic string
       UnicodeString s = makeUnicodeString(SSTRecord.MAX_RECORD_SIZE-2-1);
       UnicodeString.UnicodeRecordStats stats = new UnicodeString.UnicodeRecordStats();
@@ -99,9 +90,7 @@
       assertEquals(SSTRecord.MAX_RECORD_SIZE-1, stats.recordSize);
     }
 
-    public void testPerfectRichStringSize()
-            throws Exception
-    {
+    public void testPerfectRichStringSize() {
       //Test a rich text string
       UnicodeString s = makeUnicodeString(SSTRecord.MAX_RECORD_SIZE-2-1-8-2);
       s.addFormatRun(new UnicodeString.FormatRun((short)1,(short)0));
@@ -123,7 +112,7 @@
       assertEquals(SSTRecord.MAX_RECORD_SIZE-1, stats.recordSize);
     }
 
-    public void testContinuedStringSize() throws Exception {
+    public void testContinuedStringSize() {
       //Test a basic string
       UnicodeString s = makeUnicodeString(SSTRecord.MAX_RECORD_SIZE-2-1+20);
       UnicodeString.UnicodeRecordStats stats = new UnicodeString.UnicodeRecordStats();
@@ -132,7 +121,7 @@
     }
 
     /** Tests that a string size calculation that fits neatly in two records, the second
being a continue*/
-    public void testPerfectContinuedStringSize() throws Exception {
+    public void testPerfectContinuedStringSize() {
       //Test a basic string
       int strSize = SSTRecord.MAX_RECORD_SIZE*2;
       //String overhead
@@ -150,19 +139,18 @@
 
 
 
-    private UnicodeString makeUnicodeString( String s )
+    private static UnicodeString makeUnicodeString( String s )
     {
       UnicodeString st = new UnicodeString(s);
       st.setOptionFlags((byte)0);
       return st;
     }
 
-    private UnicodeString makeUnicodeString( int numChars) {
+    private static UnicodeString makeUnicodeString( int numChars) {
       StringBuffer b = new StringBuffer(numChars);
       for (int i=0;i<numChars;i++) {
         b.append(i%10);
       }
       return makeUnicodeString(b.toString());
     }
-
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org


Mime
View raw message