snichol 2002/10/03 19:06:17 Modified: java/test/encoding/soapenc PackageTests.java java/src/org/apache/soap/encoding/soapenc Base64.java Added: java/test/encoding/soapenc Base64Test.java Log: Submitted by: Pavel Ausianik <[EMAIL PROTECTED]> Reviewed by: Scott Nichol Base64 encoded parameters decoded too slow. See http://nagoya.apache.org/bugzilla/show_bug.cgi?id=12510 Revision Changes Path 1.3 +1 -0 xml-soap/java/test/encoding/soapenc/PackageTests.java Index: PackageTests.java =================================================================== RCS file: /home/cvs/xml-soap/java/test/encoding/soapenc/PackageTests.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- PackageTests.java 21 May 2001 01:22:33 -0000 1.2 +++ PackageTests.java 4 Oct 2002 02:06:17 -0000 1.3 @@ -24,6 +24,7 @@ suite.addTestSuite(FloatDeserializerTest.class); suite.addTestSuite(FloatObjectDeserializerTest.class); suite.addTestSuite(DecimalDeserializerTest.class); + suite.addTestSuite(Base64Test.class); return suite; } 1.1 xml-soap/java/test/encoding/soapenc/Base64Test.java Index: Base64Test.java =================================================================== package test.encoding.soapenc; import javax.xml.parsers.*; // JAXP interfaces import org.w3c.dom.*; import org.apache.soap.util.Bean; import org.apache.soap.util.xml.Deserializer; import java.io.ByteArrayInputStream; import org.apache.soap.encoding.soapenc.Base64; import java.math.BigDecimal; import junit.framework.TestCase; import junit.framework.Assert; /** * @author Pavel Ausianik <[EMAIL PROTECTED]> */ public class Base64Test extends TestCase { public static void assertEquals(String message, byte[] expected, byte[] actual) { if(expected == null && actual == null) return; if(expected == null || actual == null) fail(message); if(expected != null && expected == actual) return; if (expected.length != actual.length) fail(message); int len = expected.length; for (int i=0; i<len; i++) if (expected[i] != actual[i]) { fail(message); break; } } public Base64Test(String name) { super(name); } public void testArrays() throws Exception { for (int i=0; i<1000; i++) { byte testArray[] = new byte[i]; for (int j=0; j<i; j++) testArray[j] = (byte)j; String out = Base64.encode(testArray); byte resultArray[] = Base64.decode(out); assertEquals("testArray fails", testArray, resultArray); char charArray[] = out.toCharArray(); resultArray = Base64.decode(charArray, 0, charArray.length); assertEquals("testArray fails", testArray, resultArray); } } } 1.3 +60 -25 xml-soap/java/src/org/apache/soap/encoding/soapenc/Base64.java Index: Base64.java =================================================================== RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/encoding/soapenc/Base64.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- Base64.java 8 May 2002 14:43:08 -0000 1.2 +++ Base64.java 4 Oct 2002 02:06:17 -0000 1.3 @@ -23,15 +23,16 @@ /** * * @author TAMURA Kent <[EMAIL PROTECTED]> + * @author Pavel Ausianik <[EMAIL PROTECTED]> */ public class Base64 { private static final char[] S_BASE64CHAR = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; private static final char S_BASE64PAD = '='; @@ -99,27 +100,45 @@ return ret; } + public static final int BUF_SIZE = 256; /** * Decode the base64 data. * @param data The base64 encoded data to be decoded * @return The decoded data */ public static byte[] decode(String data) { - char[] ibuf = new char[4]; int ibufcount = 0; - byte[] obuf = new byte[data.length()/4*3+3]; + int slen = data.length(); + char[] ibuf = new char[slen < BUF_SIZE ? slen : BUF_SIZE]; + byte[] obuf = new byte[slen/4*3+3]; int obufcount = 0; - for (int i = 0; i < data.length(); i ++) { - char ch = data.charAt(i); - if (ch == S_BASE64PAD - || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { + int blen = 0; + + for (int i = 0; i < slen; i +=BUF_SIZE ) { + // buffer may contain unprocessed characters from previous step + if (i + BUF_SIZE <= slen) { + data.getChars(i, i+BUF_SIZE , ibuf, ibufcount); + blen = BUF_SIZE+ibufcount; + } else { + data.getChars(i, slen, ibuf, ibufcount); + blen = slen - i+ibufcount; + } + + for (int j=ibufcount; j<blen; j++) { + char ch = ibuf[j]; + if (ch == S_BASE64PAD + || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { ibuf[ibufcount++] = ch; - if (ibufcount == ibuf.length) { - ibufcount = 0; - obufcount += decode0(ibuf, obuf, obufcount); + + // as soon as we have 4 chars process them + if (ibufcount == 4) { + ibufcount = 0; + obufcount += decode0(ibuf, obuf, obufcount); } + } } } + if (obufcount == obuf.length) return obuf; byte[] ret = new byte[obufcount]; @@ -160,19 +179,35 @@ * written */ public static void decode(String data, OutputStream ostream) throws IOException { - char[] ibuf = new char[4]; - int ibufcount = 0; + char[] ibuf = new char[BUF_SIZE + 4]; byte[] obuf = new byte[3]; - for (int i = 0; i < data.length(); i ++) { - char ch = data.charAt(i); - if (ch == S_BASE64PAD - || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { + int slen = data.length(); + int blen = 0; + int ibufcount = 0; + + for (int i = 0; i < slen; i +=BUF_SIZE ) { + // buffer may contain unprocessed characters from previous step + if (i + BUF_SIZE <= slen) { + data.getChars(i, i+BUF_SIZE , ibuf, ibufcount); + blen = BUF_SIZE+ibufcount; + } else { + data.getChars(i, slen, ibuf, ibufcount); + blen = slen - i+ibufcount; + } + + for (int j=ibufcount; j<blen; j++) { + char ch = ibuf[j]; + if (ch == S_BASE64PAD + || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) { ibuf[ibufcount++] = ch; - if (ibufcount == ibuf.length) { - ibufcount = 0; - int obufcount = decode0(ibuf, obuf, 0); - ostream.write(obuf, 0, obufcount); + + // as sson as we have 4 chars process them + if (ibufcount == 4) { + ibufcount = 0; + int obufcount = decode0(ibuf, obuf, 0); + ostream.write(obuf, 0, obufcount); } + } } } }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>