You are viewing a plain text version of this content. The canonical link for it is here.
Posted to rpc-dev@xml.apache.org by John Wilson <tu...@wilson.co.uk> on 2002/03/09 21:58:27 UTC
Bas64 encoding performance
I have been looking at the performance of the latest version of the Apache
XML-RPC system when transferring 1Mb byte arrays via base64 encoding. That
is to say I have been running the TestBase64 benchmark.
On my test system (Sun 1.3 JVM on Win2K) here the "old Helma" XML-RPC system
runs the TestBase64 benchmark (from the current CVS tree) in ~54 seconds.
The latest version from CVS runs the same benchmark in ~77 seconds. I have
replaced the Base64 implementation with a version of the Base64
encode/decoding from MinML-RPC and tidied up the interfacing of this to the
rest of the code (avoiding converting from StringBuffer to String, returning
a char array rather than a byte array and the consequential changes). This
now runs the benchmark in ~26 seconds.
Are you interested in having these patches?
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
Sorry, I intended to attach the patch to the last message - here it is.
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by Rick Blair <rb...@photoaccess.com>.
Hi all,
John has always been a great supporter and maintainer. He is also a great
resource. I say
+1
to be a committer.
Rick
At 10:15 AM 3/10/02 +0100, you wrote:
>Jason van Zyl wrote:
>
>>
>>Definitely. I know you've been on the helma mailing lists and have
>>always helped out, that you are very familiar with XmlRpc in general
>>(MinML-RPC) so I'd say you're more than capable of applying your patches
>>directly.
>>
>>I would like to nominate John for commit access.
>>
>>+1
>>
>>
>
>+1
>
>John has contributed lots of code and energy to the project already. In
>fact I asked him if he wanted to be committer when the project moved to
>Apache, was too busy with his other work at the time.
>
>Hannes
>
>
>
Re: Bas64 encoding performance
Posted by Jason van Zyl <jv...@zenplex.com>.
On Mon, 2002-03-11 at 11:51, Daniel Rall wrote:
> Jason van Zyl <jv...@zenplex.com> writes:
>
> > On Sat, 2002-03-09 at 15:58, John Wilson wrote:
> > > I have been looking at the performance of the latest version of the Apache
> >> XML-RPC system when transferring 1Mb byte arrays via base64 encoding. That
> >> is to say I have been running the TestBase64 benchmark.
> >>
> >> On my test system (Sun 1.3 JVM on Win2K) here the "old Helma" XML-RPC system
> >> runs the TestBase64 benchmark (from the current CVS tree) in ~54 seconds.
> >> The latest version from CVS runs the same benchmark in ~77 seconds. I have
> >> replaced the Base64 implementation with a version of the Base64
> >> encode/decoding from MinML-RPC and tidied up the interfacing of this to the
> >> rest of the code (avoiding converting from StringBuffer to String, returning
> >> a char array rather than a byte array and the consequential changes). This
> >> now runs the benchmark in ~26 seconds.
> >>
> >> Are you interested in having these patches?
> >
> > Definitely. I know you've been on the helma mailing lists and have
> > always helped out, that you are very familiar with XmlRpc in general
> > (MinML-RPC) so I'd say you're more than capable of applying your patches
> > directly.
> >
> > I would like to nominate John for commit access.
> >
> > +1
> >
> > Maybe we could combine the code bases somehow?
>
> +1, but please post diffs to the list the first few times so that Jon
> can tear them apart, uh, I mean, code review them. ;-)
>
> Jason, since you nominated, would you take care of the karma request
> and apache.org account (John doesn't appear to be an Apache commiter
> yet)?
Taken care of, thanks.
> - Dan
--
jvz.
Jason van Zyl
jvanzyl@apache.org
http://tambora.zenplex.org
Re: Bas64 encoding performance
Posted by Jason van Zyl <jv...@zenplex.com>.
On Mon, 2002-03-11 at 11:51, Daniel Rall wrote:
> Jason van Zyl <jv...@zenplex.com> writes:
>
> > On Sat, 2002-03-09 at 15:58, John Wilson wrote:
> > > I have been looking at the performance of the latest version of the Apache
> >> XML-RPC system when transferring 1Mb byte arrays via base64 encoding. That
> >> is to say I have been running the TestBase64 benchmark.
> >>
> >> On my test system (Sun 1.3 JVM on Win2K) here the "old Helma" XML-RPC system
> >> runs the TestBase64 benchmark (from the current CVS tree) in ~54 seconds.
> >> The latest version from CVS runs the same benchmark in ~77 seconds. I have
> >> replaced the Base64 implementation with a version of the Base64
> >> encode/decoding from MinML-RPC and tidied up the interfacing of this to the
> >> rest of the code (avoiding converting from StringBuffer to String, returning
> >> a char array rather than a byte array and the consequential changes). This
> >> now runs the benchmark in ~26 seconds.
> >>
> >> Are you interested in having these patches?
> >
> > Definitely. I know you've been on the helma mailing lists and have
> > always helped out, that you are very familiar with XmlRpc in general
> > (MinML-RPC) so I'd say you're more than capable of applying your patches
> > directly.
> >
> > I would like to nominate John for commit access.
> >
> > +1
> >
> > Maybe we could combine the code bases somehow?
>
> +1, but please post diffs to the list the first few times so that Jon
> can tear them apart, uh, I mean, code review them. ;-)
>
> Jason, since you nominated, would you take care of the karma request
> and apache.org account (John doesn't appear to be an Apache commiter
> yet)?
Taken care of, thanks.
> - Dan
--
jvz.
Jason van Zyl
jvanzyl@apache.org
http://tambora.zenplex.org
Re: Bas64 encoding performance
Posted by Daniel Rall <dl...@finemaltcoding.com>.
Jason van Zyl <jv...@zenplex.com> writes:
> On Sat, 2002-03-09 at 15:58, John Wilson wrote:
> > I have been looking at the performance of the latest version of the Apache
>> XML-RPC system when transferring 1Mb byte arrays via base64 encoding. That
>> is to say I have been running the TestBase64 benchmark.
>>
>> On my test system (Sun 1.3 JVM on Win2K) here the "old Helma" XML-RPC system
>> runs the TestBase64 benchmark (from the current CVS tree) in ~54 seconds.
>> The latest version from CVS runs the same benchmark in ~77 seconds. I have
>> replaced the Base64 implementation with a version of the Base64
>> encode/decoding from MinML-RPC and tidied up the interfacing of this to the
>> rest of the code (avoiding converting from StringBuffer to String, returning
>> a char array rather than a byte array and the consequential changes). This
>> now runs the benchmark in ~26 seconds.
>>
>> Are you interested in having these patches?
>
> Definitely. I know you've been on the helma mailing lists and have
> always helped out, that you are very familiar with XmlRpc in general
> (MinML-RPC) so I'd say you're more than capable of applying your patches
> directly.
>
> I would like to nominate John for commit access.
>
> +1
>
> Maybe we could combine the code bases somehow?
+1, but please post diffs to the list the first few times so that Jon
can tear them apart, uh, I mean, code review them. ;-)
Jason, since you nominated, would you take care of the karma request
and apache.org account (John doesn't appear to be an Apache commiter
yet)?
- Dan
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
----- Original Message -----
From: "Jason van Zyl" <jv...@zenplex.com>
To: <rp...@xml.apache.org>
Sent: Sunday, March 10, 2002 2:23 AM
Subject: Re: Bas64 encoding performance
[snip]
> Maybe we could combine the code bases somehow?
>
That would be a little difficult - MinML-RPC is intended for systems with
very limited resources (Cellphones and toasters!). These systems generally
support only JDK 1.1 or CLDC. Neither version of Java supports reflection or
the Java 2 Collection classes, for example. MinML-RPC is designed to
minimise the use of heap storage which is not really a concern on larger
systems. I think it would be useful for the code bases to cross fertilise
but MinML-RPC is very much a niche solution and I don't think the
conflicting requirements of mainstream and embedded Java could be happily
reconciled in one source tree (which is why I wrote MinML-RPC in the first
place).
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
----- Original Message -----
From: "Jason van Zyl" <jv...@zenplex.com>
To: <rp...@xml.apache.org>
Sent: Sunday, March 10, 2002 2:23 AM
Subject: Re: Bas64 encoding performance
[snip]
> Maybe we could combine the code bases somehow?
>
That would be a little difficult - MinML-RPC is intended for systems with
very limited resources (Cellphones and toasters!). These systems generally
support only JDK 1.1 or CLDC. Neither version of Java supports reflection or
the Java 2 Collection classes, for example. MinML-RPC is designed to
minimise the use of heap storage which is not really a concern on larger
systems. I think it would be useful for the code bases to cross fertilise
but MinML-RPC is very much a niche solution and I don't think the
conflicting requirements of mainstream and embedded Java could be happily
reconciled in one source tree (which is why I wrote MinML-RPC in the first
place).
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by Daniel Rall <dl...@finemaltcoding.com>.
Jason van Zyl <jv...@zenplex.com> writes:
> On Sat, 2002-03-09 at 15:58, John Wilson wrote:
> > I have been looking at the performance of the latest version of the Apache
>> XML-RPC system when transferring 1Mb byte arrays via base64 encoding. That
>> is to say I have been running the TestBase64 benchmark.
>>
>> On my test system (Sun 1.3 JVM on Win2K) here the "old Helma" XML-RPC system
>> runs the TestBase64 benchmark (from the current CVS tree) in ~54 seconds.
>> The latest version from CVS runs the same benchmark in ~77 seconds. I have
>> replaced the Base64 implementation with a version of the Base64
>> encode/decoding from MinML-RPC and tidied up the interfacing of this to the
>> rest of the code (avoiding converting from StringBuffer to String, returning
>> a char array rather than a byte array and the consequential changes). This
>> now runs the benchmark in ~26 seconds.
>>
>> Are you interested in having these patches?
>
> Definitely. I know you've been on the helma mailing lists and have
> always helped out, that you are very familiar with XmlRpc in general
> (MinML-RPC) so I'd say you're more than capable of applying your patches
> directly.
>
> I would like to nominate John for commit access.
>
> +1
>
> Maybe we could combine the code bases somehow?
+1, but please post diffs to the list the first few times so that Jon
can tear them apart, uh, I mean, code review them. ;-)
Jason, since you nominated, would you take care of the karma request
and apache.org account (John doesn't appear to be an Apache commiter
yet)?
- Dan
Re: Bas64 encoding performance
Posted by Rick Blair <rb...@photoaccess.com>.
Hi all,
John has always been a great supporter and maintainer. He is also a great
resource. I say
+1
to be a committer.
Rick
At 10:15 AM 3/10/02 +0100, you wrote:
>Jason van Zyl wrote:
>
>>
>>Definitely. I know you've been on the helma mailing lists and have
>>always helped out, that you are very familiar with XmlRpc in general
>>(MinML-RPC) so I'd say you're more than capable of applying your patches
>>directly.
>>
>>I would like to nominate John for commit access.
>>
>>+1
>>
>>
>
>+1
>
>John has contributed lots of code and energy to the project already. In
>fact I asked him if he wanted to be committer when the project moved to
>Apache, was too busy with his other work at the time.
>
>Hannes
>
>
>
Re: Bas64 encoding performance
Posted by Hannes Wallnoefer <ha...@helma.at>.
Jason van Zyl wrote:
>
>Definitely. I know you've been on the helma mailing lists and have
>always helped out, that you are very familiar with XmlRpc in general
>(MinML-RPC) so I'd say you're more than capable of applying your patches
>directly.
>
>I would like to nominate John for commit access.
>
>+1
>
>
+1
John has contributed lots of code and energy to the project already. In
fact I asked him if he wanted to be committer when the project moved to
Apache, was too busy with his other work at the time.
Hannes
Re: Bas64 encoding performance
Posted by Hannes Wallnoefer <ha...@helma.at>.
Jason van Zyl wrote:
>
>Definitely. I know you've been on the helma mailing lists and have
>always helped out, that you are very familiar with XmlRpc in general
>(MinML-RPC) so I'd say you're more than capable of applying your patches
>directly.
>
>I would like to nominate John for commit access.
>
>+1
>
>
+1
John has contributed lots of code and energy to the project already. In
fact I asked him if he wanted to be committer when the project moved to
Apache, was too busy with his other work at the time.
Hannes
Re: Bas64 encoding performance
Posted by Jon Scott Stevens <jo...@latchkey.com>.
on 3/9/02 6:23 PM, "Jason van Zyl" <jv...@zenplex.com> wrote:
> I would like to nominate John for commit access.
>
> +1
-0
I would like to see some patches first.
-jon
Re: Bas64 encoding performance
Posted by Jon Scott Stevens <jo...@latchkey.com>.
on 3/9/02 6:23 PM, "Jason van Zyl" <jv...@zenplex.com> wrote:
> I would like to nominate John for commit access.
>
> +1
-0
I would like to see some patches first.
-jon
Re: Bas64 encoding performance
Posted by Jason van Zyl <jv...@zenplex.com>.
On Sat, 2002-03-09 at 15:58, John Wilson wrote:
> I have been looking at the performance of the latest version of the Apache
> XML-RPC system when transferring 1Mb byte arrays via base64 encoding. That
> is to say I have been running the TestBase64 benchmark.
>
> On my test system (Sun 1.3 JVM on Win2K) here the "old Helma" XML-RPC system
> runs the TestBase64 benchmark (from the current CVS tree) in ~54 seconds.
> The latest version from CVS runs the same benchmark in ~77 seconds. I have
> replaced the Base64 implementation with a version of the Base64
> encode/decoding from MinML-RPC and tidied up the interfacing of this to the
> rest of the code (avoiding converting from StringBuffer to String, returning
> a char array rather than a byte array and the consequential changes). This
> now runs the benchmark in ~26 seconds.
>
> Are you interested in having these patches?
Definitely. I know you've been on the helma mailing lists and have
always helped out, that you are very familiar with XmlRpc in general
(MinML-RPC) so I'd say you're more than capable of applying your patches
directly.
I would like to nominate John for commit access.
+1
Maybe we could combine the code bases somehow?
> John Wilson
> The Wilson Partnership
> http://www.wilson.co.uk
--
jvz.
Jason van Zyl
jvanzyl@apache.org
http://tambora.zenplex.org
Re: Bas64 encoding performance
Posted by Jason van Zyl <jv...@zenplex.com>.
On Sat, 2002-03-09 at 15:58, John Wilson wrote:
> I have been looking at the performance of the latest version of the Apache
> XML-RPC system when transferring 1Mb byte arrays via base64 encoding. That
> is to say I have been running the TestBase64 benchmark.
>
> On my test system (Sun 1.3 JVM on Win2K) here the "old Helma" XML-RPC system
> runs the TestBase64 benchmark (from the current CVS tree) in ~54 seconds.
> The latest version from CVS runs the same benchmark in ~77 seconds. I have
> replaced the Base64 implementation with a version of the Base64
> encode/decoding from MinML-RPC and tidied up the interfacing of this to the
> rest of the code (avoiding converting from StringBuffer to String, returning
> a char array rather than a byte array and the consequential changes). This
> now runs the benchmark in ~26 seconds.
>
> Are you interested in having these patches?
Definitely. I know you've been on the helma mailing lists and have
always helped out, that you are very familiar with XmlRpc in general
(MinML-RPC) so I'd say you're more than capable of applying your patches
directly.
I would like to nominate John for commit access.
+1
Maybe we could combine the code bases somehow?
> John Wilson
> The Wilson Partnership
> http://www.wilson.co.uk
--
jvz.
Jason van Zyl
jvanzyl@apache.org
http://tambora.zenplex.org
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
Sorry, I intended to attach the patch to the last message - here it is.
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by Daniel Rall <dl...@finemaltcoding.com>.
FYI, your mail client line wrapped the patch, rendering it useless to
patch. Hopefully this is cleared up later in this thread, but I
don't see it checked in. You can create a Bugzilla attachment
<http://nagoya.apache.org/bugzilla/>.
- Dan
"John Wilson" <tu...@wilson.co.uk> writes:
> As the list seems to be eating attachments - here's the patch as a message:
>
>
>
> Index: src/java/org/apache/xmlrpc/Base64.java
> ===================================================================
> RCS file: /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v
> retrieving revision 1.2
> diff -u -r1.2 Base64.java
> --- src/java/org/apache/xmlrpc/Base64.java 19 Feb 2002 02:25:01 -0000 1.2
> +++ src/java/org/apache/xmlrpc/Base64.java 9 Mar 2002 21:57:12 -0000
> @@ -1,9 +1,9 @@
> package org.apache.xmlrpc;
>
> /*
> - * $Header:
> /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/Bas
> e64.java,v 1.4 2001/09/04 21:49:55 craigmcc Exp $
> - * $Revision: 1.4 $
> - * $Date: 2001/09/04 21:49:55 $
> + * $Header:
> /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v 1.2
> 2002/02/19 02:25:01 jon Exp $
> + * $Revision: 1.2 $
> + * $Date: 2002/02/19 02:25:01 $
> *
> * ====================================================================
> *
> @@ -70,253 +70,140 @@
> * Multipurpose Internet Mail Extensions (MIME) Part One: Format of
> * Internet Message Bodies. Reference 1996
> *
> - * @author Jeffrey Rodriguez
> - * @version $Id: Base64.java,v 1.4 2001/09/04 21:49:55 craigmcc Exp $
> + * @author John Wilson (tug@wilson.co.uk)
> + * @version $Id: Base64.java,v 1.2 2002/02/19 02:25:01 jon Exp $
> */
> -public final class Base64
> -{
> - static private final int BASELENGTH = 255;
> - static private final int LOOKUPLENGTH = 64;
> - static private final int TWENTYFOURBITGROUP = 24;
> - static private final int EIGHTBIT = 8;
> - static private final int SIXTEENBIT = 16;
> - static private final int SIXBIT = 6;
> - static private final int FOURBYTE = 4;
> - static private final int SIGN = -128;
> - static private final byte PAD = (byte) '=';
> - static private byte [] base64Alphabet = new byte[BASELENGTH];
> - static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
> - //static private final Log log =
> LogSource.getInstance("org.apache.commons.util.Base64");
> -
> - static
> - {
> - for (int i = 0; i < BASELENGTH; i++ )
> - {
> - base64Alphabet[i] = -1;
> - }
> - for (int i = 'Z'; i >= 'A'; i--)
> - {
> - base64Alphabet[i] = (byte) (i - 'A');
> - }
> - for (int i = 'z'; i>= 'a'; i--)
> - {
> - base64Alphabet[i] = (byte) (i - 'a' + 26);
> - }
> - for (int i = '9'; i >= '0'; i--)
> - {
> - base64Alphabet[i] = (byte) (i - '0' + 52);
> - }
> -
> - base64Alphabet['+'] = 62;
> - base64Alphabet['/'] = 63;
> -
> - for (int i = 0; i <= 25; i++ )
> - lookUpBase64Alphabet[i] = (byte) ('A' + i);
> -
> - for (int i = 26, j = 0; i <= 51; i++, j++ )
> - lookUpBase64Alphabet[i] = (byte) ('a'+ j);
> -
> - for (int i = 52, j = 0; i <= 61; i++, j++ )
> - lookUpBase64Alphabet[i] = (byte) ('0' + j);
> -
> - lookUpBase64Alphabet[62] = (byte) '+';
> - lookUpBase64Alphabet[63] = (byte) '/';
> - }
> -
> - public static boolean isBase64( String isValidString )
> - {
> - return isArrayByteBase64(isValidString.getBytes());
> - }
> -
> - public static boolean isBase64( byte octect )
> - {
> - //shall we ignore white space? JEFF??
> - return (octect == PAD || base64Alphabet[octect] != -1);
> - }
> -
> - public static boolean isArrayByteBase64( byte[] arrayOctect )
> - {
> - int length = arrayOctect.length;
> - if (length == 0)
> - {
> - // shouldn't a 0 length array be valid base64 data?
> - // return false;
> - return true;
> - }
> - for (int i=0; i < length; i++)
> - {
> - if ( !Base64.isBase64(arrayOctect[i]) )
> - return false;
> - }
> - return true;
> - }
> -
> - /**
> - * Encodes hex octects into Base64.
> - *
> - * @param binaryData Array containing binary data to encode.
> - * @return Base64-encoded data.
> - */
> - public static byte[] encode( byte[] binaryData )
> - {
> - int lengthDataBits = binaryData.length*EIGHTBIT;
> - int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP;
> - int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP;
> - byte encodedData[] = null;
> -
> -
> - if (fewerThan24bits != 0)
> - {
> - //data not divisible by 24 bit
> - encodedData = new byte[ (numberTriplets + 1 ) * 4 ];
> - }
> - else
> - {
> - // 16 or 8 bit
> - encodedData = new byte[ numberTriplets * 4 ];
> - }
> -
> - byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
> -
> - int encodedIndex = 0;
> - int dataIndex = 0;
> - int i = 0;
> - //log.debug("number of triplets = " + numberTriplets);
> - for ( i = 0; i<numberTriplets; i++ )
> - {
> - dataIndex = i*3;
> - b1 = binaryData[dataIndex];
> - b2 = binaryData[dataIndex + 1];
> - b3 = binaryData[dataIndex + 2];
> -
> - //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
> -
> - l = (byte)(b2 & 0x0f);
> - k = (byte)(b1 & 0x03);
> -
> - encodedIndex = i * 4;
> - byte val1 = ((b1 &
> SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
> - byte val2 = ((b2 &
> SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
> - byte val3 = ((b3 &
> SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc);
> -
> - encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
> - //log.debug( "val2 = " + val2 );
> - //log.debug( "k4 = " + (k<<4) );
> - //log.debug( "vak = " + (val2 | (k<<4)) );
> - encodedData[encodedIndex+1] =
> - lookUpBase64Alphabet[ val2 | ( k<<4 )];
> - encodedData[encodedIndex+2] =
> - lookUpBase64Alphabet[ (l <<2 ) | val3 ];
> - encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 &
> 0x3f ];
> - }
> -
> - // form integral number of 6-bit groups
> - dataIndex = i*3;
> - encodedIndex = i*4;
> - if (fewerThan24bits == EIGHTBIT )
> - {
> - b1 = binaryData[dataIndex];
> - k = (byte) ( b1 &0x03 );
> - //log.debug("b1=" + b1);
> - //log.debug("b1<<2 = " + (b1>>2) );
> - byte val1 = ((b1 &
> SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
> - encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
> - encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ];
> - encodedData[encodedIndex + 2] = PAD;
> - encodedData[encodedIndex + 3] = PAD;
> - }
> - else if (fewerThan24bits == SIXTEENBIT)
> - {
> -
> - b1 = binaryData[dataIndex];
> - b2 = binaryData[dataIndex +1 ];
> - l = (byte) (b2 & 0x0f);
> - k = (byte) (b1 & 0x03);
> -
> - byte val1 = ((b1 & SIGN) ==
> 0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
> - byte val2 = ((b2 & SIGN) ==
> 0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
> -
> - encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
> - encodedData[encodedIndex + 1] =
> - lookUpBase64Alphabet[ val2 | ( k<<4 )];
> - encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
> - encodedData[encodedIndex + 3] = PAD;
> - }
> -
> - return encodedData;
> - }
> -
> - /**
> - * Decodes Base64 data into octects
> - *
> - * @param binaryData Byte array containing Base64 data
> - * @return Array containing decoded data.
> - */
> - public static byte[] decode( byte[] base64Data )
> - {
> - // handle the edge case, so we don't have to worry about it later
> - if(base64Data.length == 0) { return new byte[0]; }
> -
> - int numberQuadruple = base64Data.length/FOURBYTE;
> - byte decodedData[] = null;
> - byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0;
> -
> - // Throw away anything not in base64Data
> -
> - int encodedIndex = 0;
> - int dataIndex = 0;
> - {
> - // this sizes the output array properly - rlw
> - int lastData = base64Data.length;
> - // ignore the '=' padding
> - while (base64Data[lastData-1] == PAD)
> - {
> - if (--lastData == 0)
> - {
> - return new byte[0];
> - }
> - }
> - decodedData = new byte[ lastData - numberQuadruple ];
> - }
> -
> - for (int i = 0; i < numberQuadruple; i++)
> - {
> - dataIndex = i * 4;
> - marker0 = base64Data[dataIndex + 2];
> - marker1 = base64Data[dataIndex + 3];
> -
> - b1 = base64Alphabet[base64Data[dataIndex]];
> - b2 = base64Alphabet[base64Data[dataIndex +1]];
> -
> - if (marker0 != PAD && marker1 != PAD)
> - {
> - //No PAD e.g 3cQl
> - b3 = base64Alphabet[ marker0 ];
> - b4 = base64Alphabet[ marker1 ];
> -
> - decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
> - decodedData[encodedIndex + 1] =
> - (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
> - decodedData[encodedIndex + 2] = (byte)( b3<<6 | b4 );
> - }
> - else if (marker0 == PAD)
> - {
> - //Two PAD e.g. 3c[Pad][Pad]
> - decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
> - }
> - else if (marker1 == PAD)
> - {
> - //One PAD e.g. 3cQ[Pad]
> - b3 = base64Alphabet[ marker0 ];
> -
> - decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 );
> - decodedData[encodedIndex + 1] =
> - (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
> - }
> - encodedIndex += 3;
> - }
> - return decodedData;
> - }
> -
> -
> +public final class Base64 {
> + private static final char[] tTable =
> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharAr
> ray();
> + private static final byte[] translateTable = (
> + //
> +
> "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
> + // \t \n
> \r
> + +
> "\u0042\u0042\u0041\u0041\u0042\u0042\u0041\u0042"
> + //
> + +
> "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
> + //
> + +
> "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
> + // sp ! " #
> $ % & '
> + +
> "\u0041\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
> + // ( ) * +
> , - . /
> + +
> "\u0042\u0042\u0042\u003E\u0042\u0042\u0042\u003F"
> + // 0 1 2 3
> 4 5 6 7
> + +
> "\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B"
> + // 8 9 : ;
> < = > ?
> + +
> "\u003C\u003D\u0042\u0042\u0042\u0040\u0042\u0042"
> + // @ A B C
> D E F G
> + +
> "\u0042\u0000\u0001\u0002\u0003\u0004\u0005\u0006"
> + // H I J K L M
> N O
> + +
> "\u0007\u0008\t\n\u000B\u000C\r\u000E"
> + // P Q R S
> T U V W
> + +
> "\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016"
> + // X Y Z
> [ \ ] ^ _
> + +
> "\u0017\u0018\u0019\u0042\u0042\u0042\u0042\u0042"
> + // ' a b c
> d e f g
> + +
> "\u0042\u001A\u001B\u001C\u001D\u001E\u001F\u0020"
> + // h i j k l
> m n o p
> + +
> "\u0021\"\u0023\u0024\u0025\u0026\u0027\u0028"
> + // p q r s
> t u v w
> + +
> "\u0029\u002A\u002B\u002C\u002D\u002E\u002F\u0030"
> + // x y z
> + +
> "\u0031\u0032\u0033").getBytes();
> +
> + /**
> + * Encodes hex octects into Base64.
> + *
> + * @param binaryData Array containing binary data to encode.
> + * @return Base64-encoded data.
> + */
> + public static char[] encode(final byte[] binaryData) {
> + final int numChars = ((binaryData.length + 2) / 3) * 4;
> + final int dLimit = (binaryData.length / 3) * 3;
> + final char[] buf = new char[numChars + 2 + (binaryData.length / 54)];
> + int bIndex = 1;
> + int byteCount = 0;
> +
> + buf[0] = '\n';
> +
> + for (int dIndex = 0; dIndex != dLimit; dIndex += 3) {
> + final int d = ((binaryData[dIndex] & 0XFF) << 16) |
> + ((binaryData[dIndex + 1] & 0XFF) << 8) |
> + (binaryData[dIndex + 2] & 0XFF);
> +
> + buf[bIndex++] = tTable[d >> 18];
> + buf[bIndex++] = tTable[(d >> 12) & 0X3F];
> + buf[bIndex++] = tTable[(d >> 6) & 0X3F];
> + buf[bIndex++] = tTable[d & 0X3F];
> +
> + if (++byteCount == 18) {
> + buf[bIndex++] = '\n';
> + byteCount = 0;
> + }
> + }
> +
> + if (dLimit != binaryData.length) {
> + int d = (binaryData[dLimit] & 0XFF) << 16;
> +
> + if (dLimit + 1 != binaryData.length) {
> + d |= (binaryData[dLimit + 1] & 0XFF) << 8;
> + }
> +
> + buf[bIndex++] = tTable[d >> 18];
> + buf[bIndex++] = tTable[(d >> 12) & 0X3F];
> + buf[bIndex++] = (dLimit + 1 < binaryData.length) ? tTable[(d >> 6) &
> 0X3F] : '=';
> + buf[bIndex++] = '=';
> + }
> +
> + buf[bIndex] = '\n';
> +
> + return buf;
> + }
> +
> + /**
> + * Decodes Base64 binaryData into octects
> + *
> + * @param binarybinaryData Byte array containing Base64 binaryData
> + * @return Array containing decoded binaryData.
> + */
> + public static byte[] decode(final StringBuffer base64Data) {
> + final byte[] bytes = new byte[((base64Data.length() + 3) / 4) * 3];
> + int bytesIndex = 0;
> + int byteShift = 4;
> + int tmp = 0;
> + int sixBit = 0;
> + boolean gotEquals = false;
> +
> + for (int i = 0; i != base64Data.length(); i++) {
> + final char c = base64Data.charAt(i);
> +
> + sixBit = (c < translateTable.length) ? translateTable[c] : 66;
> +
> + if (sixBit < 64) {
> + if (gotEquals) throw new Error("= character not at end of base64
> value");
> +
> + tmp = (tmp << 6) | sixBit;
> +
> + if (byteShift-- != 4)
> + bytes[bytesIndex++] = (byte)(tmp >> (byteShift * 2));
> +
> + } else if (sixBit == 64) {
> + byteShift--;
> + gotEquals = true;
> +
> + } else if (sixBit == 66) {
> + throw new Error("bad character \'" + c + "\' in base64 value");
> + }
> +
> + if (byteShift == 0) byteShift = 4;
> + }
> +
> + if (byteShift != 4) throw new Error("wrong number of = characters at
> end of base64 value");
> +
> + if (bytes.length == bytesIndex) return bytes;
> +
> + final byte[] t = new byte[bytesIndex];
> +
> + System.arraycopy(bytes, 0, t, 0, bytesIndex);
> +
> + return t;
> + }
> }
> Index: src/java/org/apache/xmlrpc/WebServer.java
> ===================================================================
> RCS file:
> /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/WebServer.java,v
> retrieving revision 1.9
> diff -u -r1.9 WebServer.java
> --- src/java/org/apache/xmlrpc/WebServer.java 6 Mar 2002 15:52:56 -0000 1.9
> +++ src/java/org/apache/xmlrpc/WebServer.java 9 Mar 2002 21:57:15 -0000
> @@ -640,7 +640,7 @@
> try
> {
> byte[] c =
> - Base64.decode (line.substring(21).getBytes());
> + Base64.decode(new
> StringBuffer(line.substring(21)));
> String str = new String (c);
> int col = str.indexOf (':');
> user = str.substring (0, col);
> Index: src/java/org/apache/xmlrpc/XmlRpc.java
> ===================================================================
> RCS file: /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/XmlRpc.java,v
> retrieving revision 1.21
> diff -u -r1.21 XmlRpc.java
> --- src/java/org/apache/xmlrpc/XmlRpc.java 8 Mar 2002 05:19:29 -0000 1.21
> +++ src/java/org/apache/xmlrpc/XmlRpc.java 9 Mar 2002 21:57:18 -0000
> @@ -389,7 +389,7 @@
> // finalize character data, if appropriate
> if (currentValue != null && readCdata)
> {
> - currentValue.characterData (cdata.toString ());
> + currentValue.characterData (cdata);
> cdata.setLength (0);
> readCdata = false;
> }
> @@ -587,39 +587,39 @@
> * Set the character data for the element and interpret it
> * according to the element type.
> */
> - public void characterData (String cdata)
> + public void characterData (StringBuffer cdata)
> {
> switch (type)
> {
> case INTEGER:
> - value = new Integer (cdata.trim ());
> + value = new Integer(cdata.toString().trim());
> break;
> case BOOLEAN:
> - value = ("1".equals (cdata.trim ()) ?
> + value = ("1".equals(cdata.toString().trim()) ?
> Boolean.TRUE : Boolean.FALSE);
> break;
> case DOUBLE:
> - value = new Double (cdata.trim ());
> + value = new Double(cdata.toString().trim());
> break;
> case DATE:
> try
> {
> - value = dateformat.parse (cdata.trim ());
> + value = dateformat.parse(cdata.toString().trim());
> }
> catch (ParseException p)
> {
> - throw new RuntimeException (p.getMessage ());
> + throw new RuntimeException(p.getMessage());
> }
> break;
> case BASE64:
> - value = Base64.decode (cdata.getBytes());
> + value = Base64.decode(cdata);
> break;
> case STRING:
> - value = cdata;
> + value = cdata.toString();
> break;
> case STRUCT:
> // this is the name to use for the next member of this
> struct
> - nextMemberName = cdata;
> + nextMemberName = cdata.toString();
> break;
> }
> }
> Index: src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java
> ===================================================================
> RCS file:
> /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient
> .java,v
> retrieving revision 1.3
> diff -u -r1.3 SimpleXmlRpcClient.java
> --- src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java 8 Mar 2002
> 04:41:53 -0000 1.3
> +++ src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java 9 Mar 2002
> 21:57:22 -0000
> @@ -330,7 +330,7 @@
> // finalize character data, if appropriate
> if (currentValue != null && readCdata)
> {
> - currentValue.characterData (cdata.toString ());
> + currentValue.characterData(cdata);
> cdata.setLength (0);
> readCdata = false;
> }
> @@ -518,39 +518,39 @@
> * Set the character data for the element and interpret it
> according to the
> * element type
> */
> - public void characterData (String cdata)
> + public void characterData (StringBuffer cdata)
> {
> switch (type)
> {
> case INTEGER:
> - value = new Integer (cdata.trim ());
> + value = new Integer (cdata.toString().trim());
> break;
> case BOOLEAN:
> - value = new Boolean ("1".equals (cdata.trim ()));
> + value = new Boolean ("1".equals
> (cdata.toString().trim()));
> break;
> case DOUBLE:
> - value = new Double (cdata.trim ());
> + value = new Double (cdata.toString().trim());
> break;
> case DATE:
> try
> {
> - value = format.parse (cdata.trim ());
> + value = format.parse (cdata.toString().trim());
> }
> catch (ParseException p)
> {
> // System.err.println ("Exception while parsing
> date: "+p);
> - throw new RuntimeException (p.getMessage ());
> + throw new RuntimeException (p.getMessage());
> }
> break;
> case BASE64:
> - value = Base64.decode(cdata.getBytes());
> + value = Base64.decode(cdata);
> break;
> case STRING:
> - value = cdata;
> + value = cdata.toString();
> break;
> case STRUCT:
> // this is the name to use for the next member of this
> struct
> - nextMemberName = cdata;
> + nextMemberName = cdata.toString();
> break;
> }
> }
Re: Bas64 encoding performance
Posted by Daniel Rall <dl...@finemaltcoding.com>.
FYI, your mail client line wrapped the patch, rendering it useless to
patch. Hopefully this is cleared up later in this thread, but I
don't see it checked in. You can create a Bugzilla attachment
<http://nagoya.apache.org/bugzilla/>.
- Dan
"John Wilson" <tu...@wilson.co.uk> writes:
> As the list seems to be eating attachments - here's the patch as a message:
>
>
>
> Index: src/java/org/apache/xmlrpc/Base64.java
> ===================================================================
> RCS file: /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v
> retrieving revision 1.2
> diff -u -r1.2 Base64.java
> --- src/java/org/apache/xmlrpc/Base64.java 19 Feb 2002 02:25:01 -0000 1.2
> +++ src/java/org/apache/xmlrpc/Base64.java 9 Mar 2002 21:57:12 -0000
> @@ -1,9 +1,9 @@
> package org.apache.xmlrpc;
>
> /*
> - * $Header:
> /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/Bas
> e64.java,v 1.4 2001/09/04 21:49:55 craigmcc Exp $
> - * $Revision: 1.4 $
> - * $Date: 2001/09/04 21:49:55 $
> + * $Header:
> /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v 1.2
> 2002/02/19 02:25:01 jon Exp $
> + * $Revision: 1.2 $
> + * $Date: 2002/02/19 02:25:01 $
> *
> * ====================================================================
> *
> @@ -70,253 +70,140 @@
> * Multipurpose Internet Mail Extensions (MIME) Part One: Format of
> * Internet Message Bodies. Reference 1996
> *
> - * @author Jeffrey Rodriguez
> - * @version $Id: Base64.java,v 1.4 2001/09/04 21:49:55 craigmcc Exp $
> + * @author John Wilson (tug@wilson.co.uk)
> + * @version $Id: Base64.java,v 1.2 2002/02/19 02:25:01 jon Exp $
> */
> -public final class Base64
> -{
> - static private final int BASELENGTH = 255;
> - static private final int LOOKUPLENGTH = 64;
> - static private final int TWENTYFOURBITGROUP = 24;
> - static private final int EIGHTBIT = 8;
> - static private final int SIXTEENBIT = 16;
> - static private final int SIXBIT = 6;
> - static private final int FOURBYTE = 4;
> - static private final int SIGN = -128;
> - static private final byte PAD = (byte) '=';
> - static private byte [] base64Alphabet = new byte[BASELENGTH];
> - static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
> - //static private final Log log =
> LogSource.getInstance("org.apache.commons.util.Base64");
> -
> - static
> - {
> - for (int i = 0; i < BASELENGTH; i++ )
> - {
> - base64Alphabet[i] = -1;
> - }
> - for (int i = 'Z'; i >= 'A'; i--)
> - {
> - base64Alphabet[i] = (byte) (i - 'A');
> - }
> - for (int i = 'z'; i>= 'a'; i--)
> - {
> - base64Alphabet[i] = (byte) (i - 'a' + 26);
> - }
> - for (int i = '9'; i >= '0'; i--)
> - {
> - base64Alphabet[i] = (byte) (i - '0' + 52);
> - }
> -
> - base64Alphabet['+'] = 62;
> - base64Alphabet['/'] = 63;
> -
> - for (int i = 0; i <= 25; i++ )
> - lookUpBase64Alphabet[i] = (byte) ('A' + i);
> -
> - for (int i = 26, j = 0; i <= 51; i++, j++ )
> - lookUpBase64Alphabet[i] = (byte) ('a'+ j);
> -
> - for (int i = 52, j = 0; i <= 61; i++, j++ )
> - lookUpBase64Alphabet[i] = (byte) ('0' + j);
> -
> - lookUpBase64Alphabet[62] = (byte) '+';
> - lookUpBase64Alphabet[63] = (byte) '/';
> - }
> -
> - public static boolean isBase64( String isValidString )
> - {
> - return isArrayByteBase64(isValidString.getBytes());
> - }
> -
> - public static boolean isBase64( byte octect )
> - {
> - //shall we ignore white space? JEFF??
> - return (octect == PAD || base64Alphabet[octect] != -1);
> - }
> -
> - public static boolean isArrayByteBase64( byte[] arrayOctect )
> - {
> - int length = arrayOctect.length;
> - if (length == 0)
> - {
> - // shouldn't a 0 length array be valid base64 data?
> - // return false;
> - return true;
> - }
> - for (int i=0; i < length; i++)
> - {
> - if ( !Base64.isBase64(arrayOctect[i]) )
> - return false;
> - }
> - return true;
> - }
> -
> - /**
> - * Encodes hex octects into Base64.
> - *
> - * @param binaryData Array containing binary data to encode.
> - * @return Base64-encoded data.
> - */
> - public static byte[] encode( byte[] binaryData )
> - {
> - int lengthDataBits = binaryData.length*EIGHTBIT;
> - int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP;
> - int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP;
> - byte encodedData[] = null;
> -
> -
> - if (fewerThan24bits != 0)
> - {
> - //data not divisible by 24 bit
> - encodedData = new byte[ (numberTriplets + 1 ) * 4 ];
> - }
> - else
> - {
> - // 16 or 8 bit
> - encodedData = new byte[ numberTriplets * 4 ];
> - }
> -
> - byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
> -
> - int encodedIndex = 0;
> - int dataIndex = 0;
> - int i = 0;
> - //log.debug("number of triplets = " + numberTriplets);
> - for ( i = 0; i<numberTriplets; i++ )
> - {
> - dataIndex = i*3;
> - b1 = binaryData[dataIndex];
> - b2 = binaryData[dataIndex + 1];
> - b3 = binaryData[dataIndex + 2];
> -
> - //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
> -
> - l = (byte)(b2 & 0x0f);
> - k = (byte)(b1 & 0x03);
> -
> - encodedIndex = i * 4;
> - byte val1 = ((b1 &
> SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
> - byte val2 = ((b2 &
> SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
> - byte val3 = ((b3 &
> SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc);
> -
> - encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
> - //log.debug( "val2 = " + val2 );
> - //log.debug( "k4 = " + (k<<4) );
> - //log.debug( "vak = " + (val2 | (k<<4)) );
> - encodedData[encodedIndex+1] =
> - lookUpBase64Alphabet[ val2 | ( k<<4 )];
> - encodedData[encodedIndex+2] =
> - lookUpBase64Alphabet[ (l <<2 ) | val3 ];
> - encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 &
> 0x3f ];
> - }
> -
> - // form integral number of 6-bit groups
> - dataIndex = i*3;
> - encodedIndex = i*4;
> - if (fewerThan24bits == EIGHTBIT )
> - {
> - b1 = binaryData[dataIndex];
> - k = (byte) ( b1 &0x03 );
> - //log.debug("b1=" + b1);
> - //log.debug("b1<<2 = " + (b1>>2) );
> - byte val1 = ((b1 &
> SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
> - encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
> - encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ];
> - encodedData[encodedIndex + 2] = PAD;
> - encodedData[encodedIndex + 3] = PAD;
> - }
> - else if (fewerThan24bits == SIXTEENBIT)
> - {
> -
> - b1 = binaryData[dataIndex];
> - b2 = binaryData[dataIndex +1 ];
> - l = (byte) (b2 & 0x0f);
> - k = (byte) (b1 & 0x03);
> -
> - byte val1 = ((b1 & SIGN) ==
> 0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
> - byte val2 = ((b2 & SIGN) ==
> 0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
> -
> - encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
> - encodedData[encodedIndex + 1] =
> - lookUpBase64Alphabet[ val2 | ( k<<4 )];
> - encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
> - encodedData[encodedIndex + 3] = PAD;
> - }
> -
> - return encodedData;
> - }
> -
> - /**
> - * Decodes Base64 data into octects
> - *
> - * @param binaryData Byte array containing Base64 data
> - * @return Array containing decoded data.
> - */
> - public static byte[] decode( byte[] base64Data )
> - {
> - // handle the edge case, so we don't have to worry about it later
> - if(base64Data.length == 0) { return new byte[0]; }
> -
> - int numberQuadruple = base64Data.length/FOURBYTE;
> - byte decodedData[] = null;
> - byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0;
> -
> - // Throw away anything not in base64Data
> -
> - int encodedIndex = 0;
> - int dataIndex = 0;
> - {
> - // this sizes the output array properly - rlw
> - int lastData = base64Data.length;
> - // ignore the '=' padding
> - while (base64Data[lastData-1] == PAD)
> - {
> - if (--lastData == 0)
> - {
> - return new byte[0];
> - }
> - }
> - decodedData = new byte[ lastData - numberQuadruple ];
> - }
> -
> - for (int i = 0; i < numberQuadruple; i++)
> - {
> - dataIndex = i * 4;
> - marker0 = base64Data[dataIndex + 2];
> - marker1 = base64Data[dataIndex + 3];
> -
> - b1 = base64Alphabet[base64Data[dataIndex]];
> - b2 = base64Alphabet[base64Data[dataIndex +1]];
> -
> - if (marker0 != PAD && marker1 != PAD)
> - {
> - //No PAD e.g 3cQl
> - b3 = base64Alphabet[ marker0 ];
> - b4 = base64Alphabet[ marker1 ];
> -
> - decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
> - decodedData[encodedIndex + 1] =
> - (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
> - decodedData[encodedIndex + 2] = (byte)( b3<<6 | b4 );
> - }
> - else if (marker0 == PAD)
> - {
> - //Two PAD e.g. 3c[Pad][Pad]
> - decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
> - }
> - else if (marker1 == PAD)
> - {
> - //One PAD e.g. 3cQ[Pad]
> - b3 = base64Alphabet[ marker0 ];
> -
> - decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 );
> - decodedData[encodedIndex + 1] =
> - (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
> - }
> - encodedIndex += 3;
> - }
> - return decodedData;
> - }
> -
> -
> +public final class Base64 {
> + private static final char[] tTable =
> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharAr
> ray();
> + private static final byte[] translateTable = (
> + //
> +
> "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
> + // \t \n
> \r
> + +
> "\u0042\u0042\u0041\u0041\u0042\u0042\u0041\u0042"
> + //
> + +
> "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
> + //
> + +
> "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
> + // sp ! " #
> $ % & '
> + +
> "\u0041\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
> + // ( ) * +
> , - . /
> + +
> "\u0042\u0042\u0042\u003E\u0042\u0042\u0042\u003F"
> + // 0 1 2 3
> 4 5 6 7
> + +
> "\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B"
> + // 8 9 : ;
> < = > ?
> + +
> "\u003C\u003D\u0042\u0042\u0042\u0040\u0042\u0042"
> + // @ A B C
> D E F G
> + +
> "\u0042\u0000\u0001\u0002\u0003\u0004\u0005\u0006"
> + // H I J K L M
> N O
> + +
> "\u0007\u0008\t\n\u000B\u000C\r\u000E"
> + // P Q R S
> T U V W
> + +
> "\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016"
> + // X Y Z
> [ \ ] ^ _
> + +
> "\u0017\u0018\u0019\u0042\u0042\u0042\u0042\u0042"
> + // ' a b c
> d e f g
> + +
> "\u0042\u001A\u001B\u001C\u001D\u001E\u001F\u0020"
> + // h i j k l
> m n o p
> + +
> "\u0021\"\u0023\u0024\u0025\u0026\u0027\u0028"
> + // p q r s
> t u v w
> + +
> "\u0029\u002A\u002B\u002C\u002D\u002E\u002F\u0030"
> + // x y z
> + +
> "\u0031\u0032\u0033").getBytes();
> +
> + /**
> + * Encodes hex octects into Base64.
> + *
> + * @param binaryData Array containing binary data to encode.
> + * @return Base64-encoded data.
> + */
> + public static char[] encode(final byte[] binaryData) {
> + final int numChars = ((binaryData.length + 2) / 3) * 4;
> + final int dLimit = (binaryData.length / 3) * 3;
> + final char[] buf = new char[numChars + 2 + (binaryData.length / 54)];
> + int bIndex = 1;
> + int byteCount = 0;
> +
> + buf[0] = '\n';
> +
> + for (int dIndex = 0; dIndex != dLimit; dIndex += 3) {
> + final int d = ((binaryData[dIndex] & 0XFF) << 16) |
> + ((binaryData[dIndex + 1] & 0XFF) << 8) |
> + (binaryData[dIndex + 2] & 0XFF);
> +
> + buf[bIndex++] = tTable[d >> 18];
> + buf[bIndex++] = tTable[(d >> 12) & 0X3F];
> + buf[bIndex++] = tTable[(d >> 6) & 0X3F];
> + buf[bIndex++] = tTable[d & 0X3F];
> +
> + if (++byteCount == 18) {
> + buf[bIndex++] = '\n';
> + byteCount = 0;
> + }
> + }
> +
> + if (dLimit != binaryData.length) {
> + int d = (binaryData[dLimit] & 0XFF) << 16;
> +
> + if (dLimit + 1 != binaryData.length) {
> + d |= (binaryData[dLimit + 1] & 0XFF) << 8;
> + }
> +
> + buf[bIndex++] = tTable[d >> 18];
> + buf[bIndex++] = tTable[(d >> 12) & 0X3F];
> + buf[bIndex++] = (dLimit + 1 < binaryData.length) ? tTable[(d >> 6) &
> 0X3F] : '=';
> + buf[bIndex++] = '=';
> + }
> +
> + buf[bIndex] = '\n';
> +
> + return buf;
> + }
> +
> + /**
> + * Decodes Base64 binaryData into octects
> + *
> + * @param binarybinaryData Byte array containing Base64 binaryData
> + * @return Array containing decoded binaryData.
> + */
> + public static byte[] decode(final StringBuffer base64Data) {
> + final byte[] bytes = new byte[((base64Data.length() + 3) / 4) * 3];
> + int bytesIndex = 0;
> + int byteShift = 4;
> + int tmp = 0;
> + int sixBit = 0;
> + boolean gotEquals = false;
> +
> + for (int i = 0; i != base64Data.length(); i++) {
> + final char c = base64Data.charAt(i);
> +
> + sixBit = (c < translateTable.length) ? translateTable[c] : 66;
> +
> + if (sixBit < 64) {
> + if (gotEquals) throw new Error("= character not at end of base64
> value");
> +
> + tmp = (tmp << 6) | sixBit;
> +
> + if (byteShift-- != 4)
> + bytes[bytesIndex++] = (byte)(tmp >> (byteShift * 2));
> +
> + } else if (sixBit == 64) {
> + byteShift--;
> + gotEquals = true;
> +
> + } else if (sixBit == 66) {
> + throw new Error("bad character \'" + c + "\' in base64 value");
> + }
> +
> + if (byteShift == 0) byteShift = 4;
> + }
> +
> + if (byteShift != 4) throw new Error("wrong number of = characters at
> end of base64 value");
> +
> + if (bytes.length == bytesIndex) return bytes;
> +
> + final byte[] t = new byte[bytesIndex];
> +
> + System.arraycopy(bytes, 0, t, 0, bytesIndex);
> +
> + return t;
> + }
> }
> Index: src/java/org/apache/xmlrpc/WebServer.java
> ===================================================================
> RCS file:
> /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/WebServer.java,v
> retrieving revision 1.9
> diff -u -r1.9 WebServer.java
> --- src/java/org/apache/xmlrpc/WebServer.java 6 Mar 2002 15:52:56 -0000 1.9
> +++ src/java/org/apache/xmlrpc/WebServer.java 9 Mar 2002 21:57:15 -0000
> @@ -640,7 +640,7 @@
> try
> {
> byte[] c =
> - Base64.decode (line.substring(21).getBytes());
> + Base64.decode(new
> StringBuffer(line.substring(21)));
> String str = new String (c);
> int col = str.indexOf (':');
> user = str.substring (0, col);
> Index: src/java/org/apache/xmlrpc/XmlRpc.java
> ===================================================================
> RCS file: /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/XmlRpc.java,v
> retrieving revision 1.21
> diff -u -r1.21 XmlRpc.java
> --- src/java/org/apache/xmlrpc/XmlRpc.java 8 Mar 2002 05:19:29 -0000 1.21
> +++ src/java/org/apache/xmlrpc/XmlRpc.java 9 Mar 2002 21:57:18 -0000
> @@ -389,7 +389,7 @@
> // finalize character data, if appropriate
> if (currentValue != null && readCdata)
> {
> - currentValue.characterData (cdata.toString ());
> + currentValue.characterData (cdata);
> cdata.setLength (0);
> readCdata = false;
> }
> @@ -587,39 +587,39 @@
> * Set the character data for the element and interpret it
> * according to the element type.
> */
> - public void characterData (String cdata)
> + public void characterData (StringBuffer cdata)
> {
> switch (type)
> {
> case INTEGER:
> - value = new Integer (cdata.trim ());
> + value = new Integer(cdata.toString().trim());
> break;
> case BOOLEAN:
> - value = ("1".equals (cdata.trim ()) ?
> + value = ("1".equals(cdata.toString().trim()) ?
> Boolean.TRUE : Boolean.FALSE);
> break;
> case DOUBLE:
> - value = new Double (cdata.trim ());
> + value = new Double(cdata.toString().trim());
> break;
> case DATE:
> try
> {
> - value = dateformat.parse (cdata.trim ());
> + value = dateformat.parse(cdata.toString().trim());
> }
> catch (ParseException p)
> {
> - throw new RuntimeException (p.getMessage ());
> + throw new RuntimeException(p.getMessage());
> }
> break;
> case BASE64:
> - value = Base64.decode (cdata.getBytes());
> + value = Base64.decode(cdata);
> break;
> case STRING:
> - value = cdata;
> + value = cdata.toString();
> break;
> case STRUCT:
> // this is the name to use for the next member of this
> struct
> - nextMemberName = cdata;
> + nextMemberName = cdata.toString();
> break;
> }
> }
> Index: src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java
> ===================================================================
> RCS file:
> /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient
> .java,v
> retrieving revision 1.3
> diff -u -r1.3 SimpleXmlRpcClient.java
> --- src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java 8 Mar 2002
> 04:41:53 -0000 1.3
> +++ src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java 9 Mar 2002
> 21:57:22 -0000
> @@ -330,7 +330,7 @@
> // finalize character data, if appropriate
> if (currentValue != null && readCdata)
> {
> - currentValue.characterData (cdata.toString ());
> + currentValue.characterData(cdata);
> cdata.setLength (0);
> readCdata = false;
> }
> @@ -518,39 +518,39 @@
> * Set the character data for the element and interpret it
> according to the
> * element type
> */
> - public void characterData (String cdata)
> + public void characterData (StringBuffer cdata)
> {
> switch (type)
> {
> case INTEGER:
> - value = new Integer (cdata.trim ());
> + value = new Integer (cdata.toString().trim());
> break;
> case BOOLEAN:
> - value = new Boolean ("1".equals (cdata.trim ()));
> + value = new Boolean ("1".equals
> (cdata.toString().trim()));
> break;
> case DOUBLE:
> - value = new Double (cdata.trim ());
> + value = new Double (cdata.toString().trim());
> break;
> case DATE:
> try
> {
> - value = format.parse (cdata.trim ());
> + value = format.parse (cdata.toString().trim());
> }
> catch (ParseException p)
> {
> // System.err.println ("Exception while parsing
> date: "+p);
> - throw new RuntimeException (p.getMessage ());
> + throw new RuntimeException (p.getMessage());
> }
> break;
> case BASE64:
> - value = Base64.decode(cdata.getBytes());
> + value = Base64.decode(cdata);
> break;
> case STRING:
> - value = cdata;
> + value = cdata.toString();
> break;
> case STRUCT:
> // this is the name to use for the next member of this
> struct
> - nextMemberName = cdata;
> + nextMemberName = cdata.toString();
> break;
> }
> }
Re: Proxy Authentication
Posted by Daniel Rall <dl...@finemaltcoding.com>.
"Paul" <po...@umich.edu> writes:
> Hi all. I need the ability to use Proxy-Authentication with XmlRpcClient,
> and I'm pretty sure this isn't possible without adding a
> setProxyAuthentication( String username, String password)
> like we already have for Basic-Authentication. It is a real simple change,
> and I'd be happy to provide a patch, if someone would kindly let me know how
> to make a patch.
http://jakarta.apache.org/site/source.html
Re: Proxy Authentication
Posted by Daniel Rall <dl...@finemaltcoding.com>.
"Paul" <po...@umich.edu> writes:
> Hi all. I need the ability to use Proxy-Authentication with XmlRpcClient,
> and I'm pretty sure this isn't possible without adding a
> setProxyAuthentication( String username, String password)
> like we already have for Basic-Authentication. It is a real simple change,
> and I'd be happy to provide a patch, if someone would kindly let me know how
> to make a patch.
http://jakarta.apache.org/site/source.html
Proxy Authentication
Posted by Paul <po...@umich.edu>.
Hi all. I need the ability to use Proxy-Authentication with XmlRpcClient,
and I'm pretty sure this isn't possible without adding a
setProxyAuthentication( String username, String password)
like we already have for Basic-Authentication. It is a real simple change,
and I'd be happy to provide a patch, if someone would kindly let me know how
to make a patch.
If I'm mistaken, and this functionality already exists, please let me know!
Thanks,
Paul Oehler
Proxy Authentication
Posted by Paul <po...@umich.edu>.
Hi all. I need the ability to use Proxy-Authentication with XmlRpcClient,
and I'm pretty sure this isn't possible without adding a
setProxyAuthentication( String username, String password)
like we already have for Basic-Authentication. It is a real simple change,
and I'd be happy to provide a patch, if someone would kindly let me know how
to make a patch.
If I'm mistaken, and this functionality already exists, please let me know!
Thanks,
Paul Oehler
Examples of XM-RPC servlets
Posted by Christer Nordvik <ch...@trafsys.no>.
Hi.
I am new to XML-RPC and I wonder if there exists some more documentation
on it. I want the following scenario:
1. User calls RPC server from JavaScript and asks if there has been a
change in status.
2. The server checks if the status(which is stored in a database) has
changed. If it hasn't changed then it waits for i.ex. 30 seconds before
it returns the answer to the client.
Can I wait 30 seconds using asynchronous callback? Really would
appreciate some examples here. And some recommendations on a good
javascript XML-RPC client.
Best regards,
Christer
Examples of XM-RPC servlets
Posted by Christer Nordvik <ch...@trafsys.no>.
Hi.
I am new to XML-RPC and I wonder if there exists some more documentation
on it. I want the following scenario:
1. User calls RPC server from JavaScript and asks if there has been a
change in status.
2. The server checks if the status(which is stored in a database) has
changed. If it hasn't changed then it waits for i.ex. 30 seconds before
it returns the answer to the client.
Can I wait 30 seconds using asynchronous callback? Really would
appreciate some examples here. And some recommendations on a good
javascript XML-RPC client.
Best regards,
Christer
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
----- Original Message -----
From: "Paul Brown" <pr...@fivesight.com>
To: <rp...@xml.apache.org>
Sent: Monday, March 11, 2002 2:00 AM
Subject: RE: Bas64 encoding performance
[snip]
> But I also I grabbed the wrong snippet of code; this was the one that I
> wanted:
>
> + } else if (sixBit == 66) {
> + throw new Error("bad character \'" + c + "\' in base64 value");
>
> This one should let the character go (p. 25):
>
> if (sixBit == 66) byteShift--;
Paul,
a better way to allow any character is just to remove the state 66. That
is to say change all the translateTable entries from \u0042 to \u0041 and to
change:
sixBit = (c < translateTable.length) ? translateTable[c] : 66;
to
sixBit = (c < translateTable.length) ? translateTable[c] : 65;
then the } else... can be removed.
However, I do not favour this change. I believe that the RFC allows a Base64
processor to reject messages containing non Table 1 characters and
whitespace. I believe that an XML-RPC Base64 processor should reject such
messages.
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
----- Original Message -----
From: "Paul Brown" <pr...@fivesight.com>
To: <rp...@xml.apache.org>
Sent: Monday, March 11, 2002 2:00 AM
Subject: RE: Bas64 encoding performance
[snip]
> But I also I grabbed the wrong snippet of code; this was the one that I
> wanted:
>
> + } else if (sixBit == 66) {
> + throw new Error("bad character \'" + c + "\' in base64 value");
>
> This one should let the character go (p. 25):
>
> if (sixBit == 66) byteShift--;
Paul,
a better way to allow any character is just to remove the state 66. That
is to say change all the translateTable entries from \u0042 to \u0041 and to
change:
sixBit = (c < translateTable.length) ? translateTable[c] : 66;
to
sixBit = (c < translateTable.length) ? translateTable[c] : 65;
then the } else... can be removed.
However, I do not favour this change. I believe that the RFC allows a Base64
processor to reject messages containing non Table 1 characters and
whitespace. I believe that an XML-RPC Base64 processor should reject such
messages.
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
RE: Bas64 encoding performance
Posted by Paul Brown <pr...@fivesight.com>.
> From: John Wilson [mailto:tug@wilson.co.uk]
> the code ignores whitespace.
> Which I take to mean that "=" or "==" should not be followed by non
> whitespace characters. So I think I'm justified in flagging this as an
> error.
John --
You're right... :) I missed the bytes at the head of your translation
table.
But I also I grabbed the wrong snippet of code; this was the one that I
wanted:
+ } else if (sixBit == 66) {
+ throw new Error("bad character \'" + c + "\' in base64 value");
This one should let the character go (p. 25):
if (sixBit == 66) byteShift--;
Cheers,
Paul
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
Here you go
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
----- Original Message -----
From: "Jon Scott Stevens" <jo...@latchkey.com>
To: <rp...@xml.apache.org>
Sent: Monday, March 11, 2002 1:06 AM
Subject: Re: Bas64 encoding performance
> on 3/10/02 2:48 PM, "John Wilson" <tu...@wilson.co.uk> wrote:
>
> >
> > Paul,
> >
> > the code ignores whitespace.
>
> John, please re-submit your files to the list, your email client line
> wrapped them. I have gotten the problem with attachments fixed. Or, you
> could put them on your/a website so that we can download them.
>
> Thanks,
>
> -jon
>
>
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
Here you go
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
----- Original Message -----
From: "Jon Scott Stevens" <jo...@latchkey.com>
To: <rp...@xml.apache.org>
Sent: Monday, March 11, 2002 1:06 AM
Subject: Re: Bas64 encoding performance
> on 3/10/02 2:48 PM, "John Wilson" <tu...@wilson.co.uk> wrote:
>
> >
> > Paul,
> >
> > the code ignores whitespace.
>
> John, please re-submit your files to the list, your email client line
> wrapped them. I have gotten the problem with attachments fixed. Or, you
> could put them on your/a website so that we can download them.
>
> Thanks,
>
> -jon
>
>
Re: Bas64 encoding performance
Posted by Jon Scott Stevens <jo...@latchkey.com>.
on 3/10/02 2:48 PM, "John Wilson" <tu...@wilson.co.uk> wrote:
>
> Paul,
>
> the code ignores whitespace.
John, please re-submit your files to the list, your email client line
wrapped them. I have gotten the problem with attachments fixed. Or, you
could put them on your/a website so that we can download them.
Thanks,
-jon
Re: Bas64 encoding performance
Posted by Jon Scott Stevens <jo...@latchkey.com>.
on 3/10/02 2:48 PM, "John Wilson" <tu...@wilson.co.uk> wrote:
>
> Paul,
>
> the code ignores whitespace.
John, please re-submit your files to the list, your email client line
wrapped them. I have gotten the problem with attachments fixed. Or, you
could put them on your/a website so that we can download them.
Thanks,
-jon
RE: Bas64 encoding performance
Posted by Paul Brown <pr...@fivesight.com>.
> From: John Wilson [mailto:tug@wilson.co.uk]
> the code ignores whitespace.
> Which I take to mean that "=" or "==" should not be followed by non
> whitespace characters. So I think I'm justified in flagging this as an
> error.
John --
You're right... :) I missed the bytes at the head of your translation
table.
But I also I grabbed the wrong snippet of code; this was the one that I
wanted:
+ } else if (sixBit == 66) {
+ throw new Error("bad character \'" + c + "\' in base64 value");
This one should let the character go (p. 25):
if (sixBit == 66) byteShift--;
Cheers,
Paul
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
----- Original Message -----
From: "Paul Brown" <pr...@fivesight.com>
To: <rp...@xml.apache.org>
Sent: Sunday, March 10, 2002 10:00 PM
Subject: RE: Bas64 encoding performance
>
> > From: John Wilson [mailto:tug@wilson.co.uk]
> > Subject: Re: Bas64 encoding performance
> > + if (sixBit < 64) {
> > + if (gotEquals) throw new Error("= character not at end of
base64
> > value");
>
> Technically, if you look at the RFC (which is probably the correct
yardstick
> for a cross-system base64 implementation), you'll see that this isn't
quite
> the correct behavior. Among other things, whitespace and illegal
characters
> are to be ignored.
>
> RFC 2045, S6.8:
> http://www.ietf.org/rfc/rfc2045.txt
Paul,
the code ignores whitespace.
RFC2045 says (page 24) :
"In base64 data, characters other than those in Table 1, line breaks, and
other
white space probably indicate a transmission error, about which a
warning message or even a message rejection might be appropriate
under some circumstances."
Which, in my view, allows decoding software to reject a message containing
odd characters (as mine does).
The RFC also says (page 24):
"Because it is used only for padding at the end of the data, the
occurrence of any "=" characters may be taken as evidence that the
end of the data has been reached (without truncation in transit). "
Which I take to mean that "=" or "==" should not be followed by non
whitespace characters. So I think I'm justified in flagging this as an
error.
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
----- Original Message -----
From: "Paul Brown" <pr...@fivesight.com>
To: <rp...@xml.apache.org>
Sent: Sunday, March 10, 2002 10:00 PM
Subject: RE: Bas64 encoding performance
>
> > From: John Wilson [mailto:tug@wilson.co.uk]
> > Subject: Re: Bas64 encoding performance
> > + if (sixBit < 64) {
> > + if (gotEquals) throw new Error("= character not at end of
base64
> > value");
>
> Technically, if you look at the RFC (which is probably the correct
yardstick
> for a cross-system base64 implementation), you'll see that this isn't
quite
> the correct behavior. Among other things, whitespace and illegal
characters
> are to be ignored.
>
> RFC 2045, S6.8:
> http://www.ietf.org/rfc/rfc2045.txt
Paul,
the code ignores whitespace.
RFC2045 says (page 24) :
"In base64 data, characters other than those in Table 1, line breaks, and
other
white space probably indicate a transmission error, about which a
warning message or even a message rejection might be appropriate
under some circumstances."
Which, in my view, allows decoding software to reject a message containing
odd characters (as mine does).
The RFC also says (page 24):
"Because it is used only for padding at the end of the data, the
occurrence of any "=" characters may be taken as evidence that the
end of the data has been reached (without truncation in transit). "
Which I take to mean that "=" or "==" should not be followed by non
whitespace characters. So I think I'm justified in flagging this as an
error.
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
RE: Bas64 encoding performance
Posted by Paul Brown <pr...@fivesight.com>.
> From: John Wilson [mailto:tug@wilson.co.uk]
> Subject: Re: Bas64 encoding performance
> + if (sixBit < 64) {
> + if (gotEquals) throw new Error("= character not at end of base64
> value");
Technically, if you look at the RFC (which is probably the correct yardstick
for a cross-system base64 implementation), you'll see that this isn't quite
the correct behavior. Among other things, whitespace and illegal characters
are to be ignored.
RFC 2045, S6.8:
http://www.ietf.org/rfc/rfc2045.txt
-- Paul
RE: Bas64 encoding performance
Posted by Paul Brown <pr...@fivesight.com>.
> From: John Wilson [mailto:tug@wilson.co.uk]
> Subject: Re: Bas64 encoding performance
> + if (sixBit < 64) {
> + if (gotEquals) throw new Error("= character not at end of base64
> value");
Technically, if you look at the RFC (which is probably the correct yardstick
for a cross-system base64 implementation), you'll see that this isn't quite
the correct behavior. Among other things, whitespace and illegal characters
are to be ignored.
RFC 2045, S6.8:
http://www.ietf.org/rfc/rfc2045.txt
-- Paul
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
As the list seems to be eating attachments - here's the patch as a message:
Index: src/java/org/apache/xmlrpc/Base64.java
===================================================================
RCS file: /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v
retrieving revision 1.2
diff -u -r1.2 Base64.java
--- src/java/org/apache/xmlrpc/Base64.java 19 Feb 2002 02:25:01 -0000 1.2
+++ src/java/org/apache/xmlrpc/Base64.java 9 Mar 2002 21:57:12 -0000
@@ -1,9 +1,9 @@
package org.apache.xmlrpc;
/*
- * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/Bas
e64.java,v 1.4 2001/09/04 21:49:55 craigmcc Exp $
- * $Revision: 1.4 $
- * $Date: 2001/09/04 21:49:55 $
+ * $Header:
/home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v 1.2
2002/02/19 02:25:01 jon Exp $
+ * $Revision: 1.2 $
+ * $Date: 2002/02/19 02:25:01 $
*
* ====================================================================
*
@@ -70,253 +70,140 @@
* Multipurpose Internet Mail Extensions (MIME) Part One: Format of
* Internet Message Bodies. Reference 1996
*
- * @author Jeffrey Rodriguez
- * @version $Id: Base64.java,v 1.4 2001/09/04 21:49:55 craigmcc Exp $
+ * @author John Wilson (tug@wilson.co.uk)
+ * @version $Id: Base64.java,v 1.2 2002/02/19 02:25:01 jon Exp $
*/
-public final class Base64
-{
- static private final int BASELENGTH = 255;
- static private final int LOOKUPLENGTH = 64;
- static private final int TWENTYFOURBITGROUP = 24;
- static private final int EIGHTBIT = 8;
- static private final int SIXTEENBIT = 16;
- static private final int SIXBIT = 6;
- static private final int FOURBYTE = 4;
- static private final int SIGN = -128;
- static private final byte PAD = (byte) '=';
- static private byte [] base64Alphabet = new byte[BASELENGTH];
- static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
- //static private final Log log =
LogSource.getInstance("org.apache.commons.util.Base64");
-
- static
- {
- for (int i = 0; i < BASELENGTH; i++ )
- {
- base64Alphabet[i] = -1;
- }
- for (int i = 'Z'; i >= 'A'; i--)
- {
- base64Alphabet[i] = (byte) (i - 'A');
- }
- for (int i = 'z'; i>= 'a'; i--)
- {
- base64Alphabet[i] = (byte) (i - 'a' + 26);
- }
- for (int i = '9'; i >= '0'; i--)
- {
- base64Alphabet[i] = (byte) (i - '0' + 52);
- }
-
- base64Alphabet['+'] = 62;
- base64Alphabet['/'] = 63;
-
- for (int i = 0; i <= 25; i++ )
- lookUpBase64Alphabet[i] = (byte) ('A' + i);
-
- for (int i = 26, j = 0; i <= 51; i++, j++ )
- lookUpBase64Alphabet[i] = (byte) ('a'+ j);
-
- for (int i = 52, j = 0; i <= 61; i++, j++ )
- lookUpBase64Alphabet[i] = (byte) ('0' + j);
-
- lookUpBase64Alphabet[62] = (byte) '+';
- lookUpBase64Alphabet[63] = (byte) '/';
- }
-
- public static boolean isBase64( String isValidString )
- {
- return isArrayByteBase64(isValidString.getBytes());
- }
-
- public static boolean isBase64( byte octect )
- {
- //shall we ignore white space? JEFF??
- return (octect == PAD || base64Alphabet[octect] != -1);
- }
-
- public static boolean isArrayByteBase64( byte[] arrayOctect )
- {
- int length = arrayOctect.length;
- if (length == 0)
- {
- // shouldn't a 0 length array be valid base64 data?
- // return false;
- return true;
- }
- for (int i=0; i < length; i++)
- {
- if ( !Base64.isBase64(arrayOctect[i]) )
- return false;
- }
- return true;
- }
-
- /**
- * Encodes hex octects into Base64.
- *
- * @param binaryData Array containing binary data to encode.
- * @return Base64-encoded data.
- */
- public static byte[] encode( byte[] binaryData )
- {
- int lengthDataBits = binaryData.length*EIGHTBIT;
- int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP;
- int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP;
- byte encodedData[] = null;
-
-
- if (fewerThan24bits != 0)
- {
- //data not divisible by 24 bit
- encodedData = new byte[ (numberTriplets + 1 ) * 4 ];
- }
- else
- {
- // 16 or 8 bit
- encodedData = new byte[ numberTriplets * 4 ];
- }
-
- byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
-
- int encodedIndex = 0;
- int dataIndex = 0;
- int i = 0;
- //log.debug("number of triplets = " + numberTriplets);
- for ( i = 0; i<numberTriplets; i++ )
- {
- dataIndex = i*3;
- b1 = binaryData[dataIndex];
- b2 = binaryData[dataIndex + 1];
- b3 = binaryData[dataIndex + 2];
-
- //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
-
- l = (byte)(b2 & 0x0f);
- k = (byte)(b1 & 0x03);
-
- encodedIndex = i * 4;
- byte val1 = ((b1 &
SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
- byte val2 = ((b2 &
SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
- byte val3 = ((b3 &
SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc);
-
- encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
- //log.debug( "val2 = " + val2 );
- //log.debug( "k4 = " + (k<<4) );
- //log.debug( "vak = " + (val2 | (k<<4)) );
- encodedData[encodedIndex+1] =
- lookUpBase64Alphabet[ val2 | ( k<<4 )];
- encodedData[encodedIndex+2] =
- lookUpBase64Alphabet[ (l <<2 ) | val3 ];
- encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 &
0x3f ];
- }
-
- // form integral number of 6-bit groups
- dataIndex = i*3;
- encodedIndex = i*4;
- if (fewerThan24bits == EIGHTBIT )
- {
- b1 = binaryData[dataIndex];
- k = (byte) ( b1 &0x03 );
- //log.debug("b1=" + b1);
- //log.debug("b1<<2 = " + (b1>>2) );
- byte val1 = ((b1 &
SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
- encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
- encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ];
- encodedData[encodedIndex + 2] = PAD;
- encodedData[encodedIndex + 3] = PAD;
- }
- else if (fewerThan24bits == SIXTEENBIT)
- {
-
- b1 = binaryData[dataIndex];
- b2 = binaryData[dataIndex +1 ];
- l = (byte) (b2 & 0x0f);
- k = (byte) (b1 & 0x03);
-
- byte val1 = ((b1 & SIGN) ==
0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
- byte val2 = ((b2 & SIGN) ==
0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
-
- encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
- encodedData[encodedIndex + 1] =
- lookUpBase64Alphabet[ val2 | ( k<<4 )];
- encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
- encodedData[encodedIndex + 3] = PAD;
- }
-
- return encodedData;
- }
-
- /**
- * Decodes Base64 data into octects
- *
- * @param binaryData Byte array containing Base64 data
- * @return Array containing decoded data.
- */
- public static byte[] decode( byte[] base64Data )
- {
- // handle the edge case, so we don't have to worry about it later
- if(base64Data.length == 0) { return new byte[0]; }
-
- int numberQuadruple = base64Data.length/FOURBYTE;
- byte decodedData[] = null;
- byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0;
-
- // Throw away anything not in base64Data
-
- int encodedIndex = 0;
- int dataIndex = 0;
- {
- // this sizes the output array properly - rlw
- int lastData = base64Data.length;
- // ignore the '=' padding
- while (base64Data[lastData-1] == PAD)
- {
- if (--lastData == 0)
- {
- return new byte[0];
- }
- }
- decodedData = new byte[ lastData - numberQuadruple ];
- }
-
- for (int i = 0; i < numberQuadruple; i++)
- {
- dataIndex = i * 4;
- marker0 = base64Data[dataIndex + 2];
- marker1 = base64Data[dataIndex + 3];
-
- b1 = base64Alphabet[base64Data[dataIndex]];
- b2 = base64Alphabet[base64Data[dataIndex +1]];
-
- if (marker0 != PAD && marker1 != PAD)
- {
- //No PAD e.g 3cQl
- b3 = base64Alphabet[ marker0 ];
- b4 = base64Alphabet[ marker1 ];
-
- decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
- decodedData[encodedIndex + 1] =
- (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
- decodedData[encodedIndex + 2] = (byte)( b3<<6 | b4 );
- }
- else if (marker0 == PAD)
- {
- //Two PAD e.g. 3c[Pad][Pad]
- decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
- }
- else if (marker1 == PAD)
- {
- //One PAD e.g. 3cQ[Pad]
- b3 = base64Alphabet[ marker0 ];
-
- decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 );
- decodedData[encodedIndex + 1] =
- (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
- }
- encodedIndex += 3;
- }
- return decodedData;
- }
-
-
+public final class Base64 {
+ private static final char[] tTable =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharAr
ray();
+ private static final byte[] translateTable = (
+ //
+
"\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
+ // \t \n
\r
+ +
"\u0042\u0042\u0041\u0041\u0042\u0042\u0041\u0042"
+ //
+ +
"\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
+ //
+ +
"\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
+ // sp ! " #
$ % & '
+ +
"\u0041\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
+ // ( ) * +
, - . /
+ +
"\u0042\u0042\u0042\u003E\u0042\u0042\u0042\u003F"
+ // 0 1 2 3
4 5 6 7
+ +
"\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B"
+ // 8 9 : ;
< = > ?
+ +
"\u003C\u003D\u0042\u0042\u0042\u0040\u0042\u0042"
+ // @ A B C
D E F G
+ +
"\u0042\u0000\u0001\u0002\u0003\u0004\u0005\u0006"
+ // H I J K L M
N O
+ +
"\u0007\u0008\t\n\u000B\u000C\r\u000E"
+ // P Q R S
T U V W
+ +
"\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016"
+ // X Y Z
[ \ ] ^ _
+ +
"\u0017\u0018\u0019\u0042\u0042\u0042\u0042\u0042"
+ // ' a b c
d e f g
+ +
"\u0042\u001A\u001B\u001C\u001D\u001E\u001F\u0020"
+ // h i j k l
m n o p
+ +
"\u0021\"\u0023\u0024\u0025\u0026\u0027\u0028"
+ // p q r s
t u v w
+ +
"\u0029\u002A\u002B\u002C\u002D\u002E\u002F\u0030"
+ // x y z
+ +
"\u0031\u0032\u0033").getBytes();
+
+ /**
+ * Encodes hex octects into Base64.
+ *
+ * @param binaryData Array containing binary data to encode.
+ * @return Base64-encoded data.
+ */
+ public static char[] encode(final byte[] binaryData) {
+ final int numChars = ((binaryData.length + 2) / 3) * 4;
+ final int dLimit = (binaryData.length / 3) * 3;
+ final char[] buf = new char[numChars + 2 + (binaryData.length / 54)];
+ int bIndex = 1;
+ int byteCount = 0;
+
+ buf[0] = '\n';
+
+ for (int dIndex = 0; dIndex != dLimit; dIndex += 3) {
+ final int d = ((binaryData[dIndex] & 0XFF) << 16) |
+ ((binaryData[dIndex + 1] & 0XFF) << 8) |
+ (binaryData[dIndex + 2] & 0XFF);
+
+ buf[bIndex++] = tTable[d >> 18];
+ buf[bIndex++] = tTable[(d >> 12) & 0X3F];
+ buf[bIndex++] = tTable[(d >> 6) & 0X3F];
+ buf[bIndex++] = tTable[d & 0X3F];
+
+ if (++byteCount == 18) {
+ buf[bIndex++] = '\n';
+ byteCount = 0;
+ }
+ }
+
+ if (dLimit != binaryData.length) {
+ int d = (binaryData[dLimit] & 0XFF) << 16;
+
+ if (dLimit + 1 != binaryData.length) {
+ d |= (binaryData[dLimit + 1] & 0XFF) << 8;
+ }
+
+ buf[bIndex++] = tTable[d >> 18];
+ buf[bIndex++] = tTable[(d >> 12) & 0X3F];
+ buf[bIndex++] = (dLimit + 1 < binaryData.length) ? tTable[(d >> 6) &
0X3F] : '=';
+ buf[bIndex++] = '=';
+ }
+
+ buf[bIndex] = '\n';
+
+ return buf;
+ }
+
+ /**
+ * Decodes Base64 binaryData into octects
+ *
+ * @param binarybinaryData Byte array containing Base64 binaryData
+ * @return Array containing decoded binaryData.
+ */
+ public static byte[] decode(final StringBuffer base64Data) {
+ final byte[] bytes = new byte[((base64Data.length() + 3) / 4) * 3];
+ int bytesIndex = 0;
+ int byteShift = 4;
+ int tmp = 0;
+ int sixBit = 0;
+ boolean gotEquals = false;
+
+ for (int i = 0; i != base64Data.length(); i++) {
+ final char c = base64Data.charAt(i);
+
+ sixBit = (c < translateTable.length) ? translateTable[c] : 66;
+
+ if (sixBit < 64) {
+ if (gotEquals) throw new Error("= character not at end of base64
value");
+
+ tmp = (tmp << 6) | sixBit;
+
+ if (byteShift-- != 4)
+ bytes[bytesIndex++] = (byte)(tmp >> (byteShift * 2));
+
+ } else if (sixBit == 64) {
+ byteShift--;
+ gotEquals = true;
+
+ } else if (sixBit == 66) {
+ throw new Error("bad character \'" + c + "\' in base64 value");
+ }
+
+ if (byteShift == 0) byteShift = 4;
+ }
+
+ if (byteShift != 4) throw new Error("wrong number of = characters at
end of base64 value");
+
+ if (bytes.length == bytesIndex) return bytes;
+
+ final byte[] t = new byte[bytesIndex];
+
+ System.arraycopy(bytes, 0, t, 0, bytesIndex);
+
+ return t;
+ }
}
Index: src/java/org/apache/xmlrpc/WebServer.java
===================================================================
RCS file:
/home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/WebServer.java,v
retrieving revision 1.9
diff -u -r1.9 WebServer.java
--- src/java/org/apache/xmlrpc/WebServer.java 6 Mar 2002 15:52:56 -0000 1.9
+++ src/java/org/apache/xmlrpc/WebServer.java 9 Mar 2002 21:57:15 -0000
@@ -640,7 +640,7 @@
try
{
byte[] c =
- Base64.decode (line.substring(21).getBytes());
+ Base64.decode(new
StringBuffer(line.substring(21)));
String str = new String (c);
int col = str.indexOf (':');
user = str.substring (0, col);
Index: src/java/org/apache/xmlrpc/XmlRpc.java
===================================================================
RCS file: /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/XmlRpc.java,v
retrieving revision 1.21
diff -u -r1.21 XmlRpc.java
--- src/java/org/apache/xmlrpc/XmlRpc.java 8 Mar 2002 05:19:29 -0000 1.21
+++ src/java/org/apache/xmlrpc/XmlRpc.java 9 Mar 2002 21:57:18 -0000
@@ -389,7 +389,7 @@
// finalize character data, if appropriate
if (currentValue != null && readCdata)
{
- currentValue.characterData (cdata.toString ());
+ currentValue.characterData (cdata);
cdata.setLength (0);
readCdata = false;
}
@@ -587,39 +587,39 @@
* Set the character data for the element and interpret it
* according to the element type.
*/
- public void characterData (String cdata)
+ public void characterData (StringBuffer cdata)
{
switch (type)
{
case INTEGER:
- value = new Integer (cdata.trim ());
+ value = new Integer(cdata.toString().trim());
break;
case BOOLEAN:
- value = ("1".equals (cdata.trim ()) ?
+ value = ("1".equals(cdata.toString().trim()) ?
Boolean.TRUE : Boolean.FALSE);
break;
case DOUBLE:
- value = new Double (cdata.trim ());
+ value = new Double(cdata.toString().trim());
break;
case DATE:
try
{
- value = dateformat.parse (cdata.trim ());
+ value = dateformat.parse(cdata.toString().trim());
}
catch (ParseException p)
{
- throw new RuntimeException (p.getMessage ());
+ throw new RuntimeException(p.getMessage());
}
break;
case BASE64:
- value = Base64.decode (cdata.getBytes());
+ value = Base64.decode(cdata);
break;
case STRING:
- value = cdata;
+ value = cdata.toString();
break;
case STRUCT:
// this is the name to use for the next member of this
struct
- nextMemberName = cdata;
+ nextMemberName = cdata.toString();
break;
}
}
Index: src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java
===================================================================
RCS file:
/home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient
.java,v
retrieving revision 1.3
diff -u -r1.3 SimpleXmlRpcClient.java
--- src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java 8 Mar 2002
04:41:53 -0000 1.3
+++ src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java 9 Mar 2002
21:57:22 -0000
@@ -330,7 +330,7 @@
// finalize character data, if appropriate
if (currentValue != null && readCdata)
{
- currentValue.characterData (cdata.toString ());
+ currentValue.characterData(cdata);
cdata.setLength (0);
readCdata = false;
}
@@ -518,39 +518,39 @@
* Set the character data for the element and interpret it
according to the
* element type
*/
- public void characterData (String cdata)
+ public void characterData (StringBuffer cdata)
{
switch (type)
{
case INTEGER:
- value = new Integer (cdata.trim ());
+ value = new Integer (cdata.toString().trim());
break;
case BOOLEAN:
- value = new Boolean ("1".equals (cdata.trim ()));
+ value = new Boolean ("1".equals
(cdata.toString().trim()));
break;
case DOUBLE:
- value = new Double (cdata.trim ());
+ value = new Double (cdata.toString().trim());
break;
case DATE:
try
{
- value = format.parse (cdata.trim ());
+ value = format.parse (cdata.toString().trim());
}
catch (ParseException p)
{
// System.err.println ("Exception while parsing
date: "+p);
- throw new RuntimeException (p.getMessage ());
+ throw new RuntimeException (p.getMessage());
}
break;
case BASE64:
- value = Base64.decode(cdata.getBytes());
+ value = Base64.decode(cdata);
break;
case STRING:
- value = cdata;
+ value = cdata.toString();
break;
case STRUCT:
// this is the name to use for the next member of this
struct
- nextMemberName = cdata;
+ nextMemberName = cdata.toString();
break;
}
}
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
As the list seems to be eating attachments - here's the patch as a message:
Index: src/java/org/apache/xmlrpc/Base64.java
===================================================================
RCS file: /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v
retrieving revision 1.2
diff -u -r1.2 Base64.java
--- src/java/org/apache/xmlrpc/Base64.java 19 Feb 2002 02:25:01 -0000 1.2
+++ src/java/org/apache/xmlrpc/Base64.java 9 Mar 2002 21:57:12 -0000
@@ -1,9 +1,9 @@
package org.apache.xmlrpc;
/*
- * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/Bas
e64.java,v 1.4 2001/09/04 21:49:55 craigmcc Exp $
- * $Revision: 1.4 $
- * $Date: 2001/09/04 21:49:55 $
+ * $Header:
/home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v 1.2
2002/02/19 02:25:01 jon Exp $
+ * $Revision: 1.2 $
+ * $Date: 2002/02/19 02:25:01 $
*
* ====================================================================
*
@@ -70,253 +70,140 @@
* Multipurpose Internet Mail Extensions (MIME) Part One: Format of
* Internet Message Bodies. Reference 1996
*
- * @author Jeffrey Rodriguez
- * @version $Id: Base64.java,v 1.4 2001/09/04 21:49:55 craigmcc Exp $
+ * @author John Wilson (tug@wilson.co.uk)
+ * @version $Id: Base64.java,v 1.2 2002/02/19 02:25:01 jon Exp $
*/
-public final class Base64
-{
- static private final int BASELENGTH = 255;
- static private final int LOOKUPLENGTH = 64;
- static private final int TWENTYFOURBITGROUP = 24;
- static private final int EIGHTBIT = 8;
- static private final int SIXTEENBIT = 16;
- static private final int SIXBIT = 6;
- static private final int FOURBYTE = 4;
- static private final int SIGN = -128;
- static private final byte PAD = (byte) '=';
- static private byte [] base64Alphabet = new byte[BASELENGTH];
- static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
- //static private final Log log =
LogSource.getInstance("org.apache.commons.util.Base64");
-
- static
- {
- for (int i = 0; i < BASELENGTH; i++ )
- {
- base64Alphabet[i] = -1;
- }
- for (int i = 'Z'; i >= 'A'; i--)
- {
- base64Alphabet[i] = (byte) (i - 'A');
- }
- for (int i = 'z'; i>= 'a'; i--)
- {
- base64Alphabet[i] = (byte) (i - 'a' + 26);
- }
- for (int i = '9'; i >= '0'; i--)
- {
- base64Alphabet[i] = (byte) (i - '0' + 52);
- }
-
- base64Alphabet['+'] = 62;
- base64Alphabet['/'] = 63;
-
- for (int i = 0; i <= 25; i++ )
- lookUpBase64Alphabet[i] = (byte) ('A' + i);
-
- for (int i = 26, j = 0; i <= 51; i++, j++ )
- lookUpBase64Alphabet[i] = (byte) ('a'+ j);
-
- for (int i = 52, j = 0; i <= 61; i++, j++ )
- lookUpBase64Alphabet[i] = (byte) ('0' + j);
-
- lookUpBase64Alphabet[62] = (byte) '+';
- lookUpBase64Alphabet[63] = (byte) '/';
- }
-
- public static boolean isBase64( String isValidString )
- {
- return isArrayByteBase64(isValidString.getBytes());
- }
-
- public static boolean isBase64( byte octect )
- {
- //shall we ignore white space? JEFF??
- return (octect == PAD || base64Alphabet[octect] != -1);
- }
-
- public static boolean isArrayByteBase64( byte[] arrayOctect )
- {
- int length = arrayOctect.length;
- if (length == 0)
- {
- // shouldn't a 0 length array be valid base64 data?
- // return false;
- return true;
- }
- for (int i=0; i < length; i++)
- {
- if ( !Base64.isBase64(arrayOctect[i]) )
- return false;
- }
- return true;
- }
-
- /**
- * Encodes hex octects into Base64.
- *
- * @param binaryData Array containing binary data to encode.
- * @return Base64-encoded data.
- */
- public static byte[] encode( byte[] binaryData )
- {
- int lengthDataBits = binaryData.length*EIGHTBIT;
- int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP;
- int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP;
- byte encodedData[] = null;
-
-
- if (fewerThan24bits != 0)
- {
- //data not divisible by 24 bit
- encodedData = new byte[ (numberTriplets + 1 ) * 4 ];
- }
- else
- {
- // 16 or 8 bit
- encodedData = new byte[ numberTriplets * 4 ];
- }
-
- byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
-
- int encodedIndex = 0;
- int dataIndex = 0;
- int i = 0;
- //log.debug("number of triplets = " + numberTriplets);
- for ( i = 0; i<numberTriplets; i++ )
- {
- dataIndex = i*3;
- b1 = binaryData[dataIndex];
- b2 = binaryData[dataIndex + 1];
- b3 = binaryData[dataIndex + 2];
-
- //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
-
- l = (byte)(b2 & 0x0f);
- k = (byte)(b1 & 0x03);
-
- encodedIndex = i * 4;
- byte val1 = ((b1 &
SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
- byte val2 = ((b2 &
SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
- byte val3 = ((b3 &
SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc);
-
- encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
- //log.debug( "val2 = " + val2 );
- //log.debug( "k4 = " + (k<<4) );
- //log.debug( "vak = " + (val2 | (k<<4)) );
- encodedData[encodedIndex+1] =
- lookUpBase64Alphabet[ val2 | ( k<<4 )];
- encodedData[encodedIndex+2] =
- lookUpBase64Alphabet[ (l <<2 ) | val3 ];
- encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 &
0x3f ];
- }
-
- // form integral number of 6-bit groups
- dataIndex = i*3;
- encodedIndex = i*4;
- if (fewerThan24bits == EIGHTBIT )
- {
- b1 = binaryData[dataIndex];
- k = (byte) ( b1 &0x03 );
- //log.debug("b1=" + b1);
- //log.debug("b1<<2 = " + (b1>>2) );
- byte val1 = ((b1 &
SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
- encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
- encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ];
- encodedData[encodedIndex + 2] = PAD;
- encodedData[encodedIndex + 3] = PAD;
- }
- else if (fewerThan24bits == SIXTEENBIT)
- {
-
- b1 = binaryData[dataIndex];
- b2 = binaryData[dataIndex +1 ];
- l = (byte) (b2 & 0x0f);
- k = (byte) (b1 & 0x03);
-
- byte val1 = ((b1 & SIGN) ==
0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
- byte val2 = ((b2 & SIGN) ==
0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
-
- encodedData[encodedIndex] = lookUpBase64Alphabet[ val1 ];
- encodedData[encodedIndex + 1] =
- lookUpBase64Alphabet[ val2 | ( k<<4 )];
- encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
- encodedData[encodedIndex + 3] = PAD;
- }
-
- return encodedData;
- }
-
- /**
- * Decodes Base64 data into octects
- *
- * @param binaryData Byte array containing Base64 data
- * @return Array containing decoded data.
- */
- public static byte[] decode( byte[] base64Data )
- {
- // handle the edge case, so we don't have to worry about it later
- if(base64Data.length == 0) { return new byte[0]; }
-
- int numberQuadruple = base64Data.length/FOURBYTE;
- byte decodedData[] = null;
- byte b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0;
-
- // Throw away anything not in base64Data
-
- int encodedIndex = 0;
- int dataIndex = 0;
- {
- // this sizes the output array properly - rlw
- int lastData = base64Data.length;
- // ignore the '=' padding
- while (base64Data[lastData-1] == PAD)
- {
- if (--lastData == 0)
- {
- return new byte[0];
- }
- }
- decodedData = new byte[ lastData - numberQuadruple ];
- }
-
- for (int i = 0; i < numberQuadruple; i++)
- {
- dataIndex = i * 4;
- marker0 = base64Data[dataIndex + 2];
- marker1 = base64Data[dataIndex + 3];
-
- b1 = base64Alphabet[base64Data[dataIndex]];
- b2 = base64Alphabet[base64Data[dataIndex +1]];
-
- if (marker0 != PAD && marker1 != PAD)
- {
- //No PAD e.g 3cQl
- b3 = base64Alphabet[ marker0 ];
- b4 = base64Alphabet[ marker1 ];
-
- decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
- decodedData[encodedIndex + 1] =
- (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
- decodedData[encodedIndex + 2] = (byte)( b3<<6 | b4 );
- }
- else if (marker0 == PAD)
- {
- //Two PAD e.g. 3c[Pad][Pad]
- decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ;
- }
- else if (marker1 == PAD)
- {
- //One PAD e.g. 3cQ[Pad]
- b3 = base64Alphabet[ marker0 ];
-
- decodedData[encodedIndex] = (byte)( b1 <<2 | b2>>4 );
- decodedData[encodedIndex + 1] =
- (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
- }
- encodedIndex += 3;
- }
- return decodedData;
- }
-
-
+public final class Base64 {
+ private static final char[] tTable =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharAr
ray();
+ private static final byte[] translateTable = (
+ //
+
"\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
+ // \t \n
\r
+ +
"\u0042\u0042\u0041\u0041\u0042\u0042\u0041\u0042"
+ //
+ +
"\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
+ //
+ +
"\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
+ // sp ! " #
$ % & '
+ +
"\u0041\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
+ // ( ) * +
, - . /
+ +
"\u0042\u0042\u0042\u003E\u0042\u0042\u0042\u003F"
+ // 0 1 2 3
4 5 6 7
+ +
"\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B"
+ // 8 9 : ;
< = > ?
+ +
"\u003C\u003D\u0042\u0042\u0042\u0040\u0042\u0042"
+ // @ A B C
D E F G
+ +
"\u0042\u0000\u0001\u0002\u0003\u0004\u0005\u0006"
+ // H I J K L M
N O
+ +
"\u0007\u0008\t\n\u000B\u000C\r\u000E"
+ // P Q R S
T U V W
+ +
"\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016"
+ // X Y Z
[ \ ] ^ _
+ +
"\u0017\u0018\u0019\u0042\u0042\u0042\u0042\u0042"
+ // ' a b c
d e f g
+ +
"\u0042\u001A\u001B\u001C\u001D\u001E\u001F\u0020"
+ // h i j k l
m n o p
+ +
"\u0021\"\u0023\u0024\u0025\u0026\u0027\u0028"
+ // p q r s
t u v w
+ +
"\u0029\u002A\u002B\u002C\u002D\u002E\u002F\u0030"
+ // x y z
+ +
"\u0031\u0032\u0033").getBytes();
+
+ /**
+ * Encodes hex octects into Base64.
+ *
+ * @param binaryData Array containing binary data to encode.
+ * @return Base64-encoded data.
+ */
+ public static char[] encode(final byte[] binaryData) {
+ final int numChars = ((binaryData.length + 2) / 3) * 4;
+ final int dLimit = (binaryData.length / 3) * 3;
+ final char[] buf = new char[numChars + 2 + (binaryData.length / 54)];
+ int bIndex = 1;
+ int byteCount = 0;
+
+ buf[0] = '\n';
+
+ for (int dIndex = 0; dIndex != dLimit; dIndex += 3) {
+ final int d = ((binaryData[dIndex] & 0XFF) << 16) |
+ ((binaryData[dIndex + 1] & 0XFF) << 8) |
+ (binaryData[dIndex + 2] & 0XFF);
+
+ buf[bIndex++] = tTable[d >> 18];
+ buf[bIndex++] = tTable[(d >> 12) & 0X3F];
+ buf[bIndex++] = tTable[(d >> 6) & 0X3F];
+ buf[bIndex++] = tTable[d & 0X3F];
+
+ if (++byteCount == 18) {
+ buf[bIndex++] = '\n';
+ byteCount = 0;
+ }
+ }
+
+ if (dLimit != binaryData.length) {
+ int d = (binaryData[dLimit] & 0XFF) << 16;
+
+ if (dLimit + 1 != binaryData.length) {
+ d |= (binaryData[dLimit + 1] & 0XFF) << 8;
+ }
+
+ buf[bIndex++] = tTable[d >> 18];
+ buf[bIndex++] = tTable[(d >> 12) & 0X3F];
+ buf[bIndex++] = (dLimit + 1 < binaryData.length) ? tTable[(d >> 6) &
0X3F] : '=';
+ buf[bIndex++] = '=';
+ }
+
+ buf[bIndex] = '\n';
+
+ return buf;
+ }
+
+ /**
+ * Decodes Base64 binaryData into octects
+ *
+ * @param binarybinaryData Byte array containing Base64 binaryData
+ * @return Array containing decoded binaryData.
+ */
+ public static byte[] decode(final StringBuffer base64Data) {
+ final byte[] bytes = new byte[((base64Data.length() + 3) / 4) * 3];
+ int bytesIndex = 0;
+ int byteShift = 4;
+ int tmp = 0;
+ int sixBit = 0;
+ boolean gotEquals = false;
+
+ for (int i = 0; i != base64Data.length(); i++) {
+ final char c = base64Data.charAt(i);
+
+ sixBit = (c < translateTable.length) ? translateTable[c] : 66;
+
+ if (sixBit < 64) {
+ if (gotEquals) throw new Error("= character not at end of base64
value");
+
+ tmp = (tmp << 6) | sixBit;
+
+ if (byteShift-- != 4)
+ bytes[bytesIndex++] = (byte)(tmp >> (byteShift * 2));
+
+ } else if (sixBit == 64) {
+ byteShift--;
+ gotEquals = true;
+
+ } else if (sixBit == 66) {
+ throw new Error("bad character \'" + c + "\' in base64 value");
+ }
+
+ if (byteShift == 0) byteShift = 4;
+ }
+
+ if (byteShift != 4) throw new Error("wrong number of = characters at
end of base64 value");
+
+ if (bytes.length == bytesIndex) return bytes;
+
+ final byte[] t = new byte[bytesIndex];
+
+ System.arraycopy(bytes, 0, t, 0, bytesIndex);
+
+ return t;
+ }
}
Index: src/java/org/apache/xmlrpc/WebServer.java
===================================================================
RCS file:
/home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/WebServer.java,v
retrieving revision 1.9
diff -u -r1.9 WebServer.java
--- src/java/org/apache/xmlrpc/WebServer.java 6 Mar 2002 15:52:56 -0000 1.9
+++ src/java/org/apache/xmlrpc/WebServer.java 9 Mar 2002 21:57:15 -0000
@@ -640,7 +640,7 @@
try
{
byte[] c =
- Base64.decode (line.substring(21).getBytes());
+ Base64.decode(new
StringBuffer(line.substring(21)));
String str = new String (c);
int col = str.indexOf (':');
user = str.substring (0, col);
Index: src/java/org/apache/xmlrpc/XmlRpc.java
===================================================================
RCS file: /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/XmlRpc.java,v
retrieving revision 1.21
diff -u -r1.21 XmlRpc.java
--- src/java/org/apache/xmlrpc/XmlRpc.java 8 Mar 2002 05:19:29 -0000 1.21
+++ src/java/org/apache/xmlrpc/XmlRpc.java 9 Mar 2002 21:57:18 -0000
@@ -389,7 +389,7 @@
// finalize character data, if appropriate
if (currentValue != null && readCdata)
{
- currentValue.characterData (cdata.toString ());
+ currentValue.characterData (cdata);
cdata.setLength (0);
readCdata = false;
}
@@ -587,39 +587,39 @@
* Set the character data for the element and interpret it
* according to the element type.
*/
- public void characterData (String cdata)
+ public void characterData (StringBuffer cdata)
{
switch (type)
{
case INTEGER:
- value = new Integer (cdata.trim ());
+ value = new Integer(cdata.toString().trim());
break;
case BOOLEAN:
- value = ("1".equals (cdata.trim ()) ?
+ value = ("1".equals(cdata.toString().trim()) ?
Boolean.TRUE : Boolean.FALSE);
break;
case DOUBLE:
- value = new Double (cdata.trim ());
+ value = new Double(cdata.toString().trim());
break;
case DATE:
try
{
- value = dateformat.parse (cdata.trim ());
+ value = dateformat.parse(cdata.toString().trim());
}
catch (ParseException p)
{
- throw new RuntimeException (p.getMessage ());
+ throw new RuntimeException(p.getMessage());
}
break;
case BASE64:
- value = Base64.decode (cdata.getBytes());
+ value = Base64.decode(cdata);
break;
case STRING:
- value = cdata;
+ value = cdata.toString();
break;
case STRUCT:
// this is the name to use for the next member of this
struct
- nextMemberName = cdata;
+ nextMemberName = cdata.toString();
break;
}
}
Index: src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java
===================================================================
RCS file:
/home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient
.java,v
retrieving revision 1.3
diff -u -r1.3 SimpleXmlRpcClient.java
--- src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java 8 Mar 2002
04:41:53 -0000 1.3
+++ src/java/org/apache/xmlrpc/applet/SimpleXmlRpcClient.java 9 Mar 2002
21:57:22 -0000
@@ -330,7 +330,7 @@
// finalize character data, if appropriate
if (currentValue != null && readCdata)
{
- currentValue.characterData (cdata.toString ());
+ currentValue.characterData(cdata);
cdata.setLength (0);
readCdata = false;
}
@@ -518,39 +518,39 @@
* Set the character data for the element and interpret it
according to the
* element type
*/
- public void characterData (String cdata)
+ public void characterData (StringBuffer cdata)
{
switch (type)
{
case INTEGER:
- value = new Integer (cdata.trim ());
+ value = new Integer (cdata.toString().trim());
break;
case BOOLEAN:
- value = new Boolean ("1".equals (cdata.trim ()));
+ value = new Boolean ("1".equals
(cdata.toString().trim()));
break;
case DOUBLE:
- value = new Double (cdata.trim ());
+ value = new Double (cdata.toString().trim());
break;
case DATE:
try
{
- value = format.parse (cdata.trim ());
+ value = format.parse (cdata.toString().trim());
}
catch (ParseException p)
{
// System.err.println ("Exception while parsing
date: "+p);
- throw new RuntimeException (p.getMessage ());
+ throw new RuntimeException (p.getMessage());
}
break;
case BASE64:
- value = Base64.decode(cdata.getBytes());
+ value = Base64.decode(cdata);
break;
case STRING:
- value = cdata;
+ value = cdata.toString();
break;
case STRUCT:
// this is the name to use for the next member of this
struct
- nextMemberName = cdata;
+ nextMemberName = cdata.toString();
break;
}
}
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
One last go - see if the file extension of the attachment is significant.
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
One last go - see if the file extension of the attachment is significant.
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
----- Original Message -----
From: "John Wilson" <tu...@wilson.co.uk>
To: <rp...@xml.apache.org>
Cc: <rb...@photoaccess.com>
Sent: Sunday, March 10, 2002 8:21 AM
Subject: Re: Bas64 encoding performance
[snip]
> I sent an email with the patches as an attachment to the list a couple
> of minutes after the first message. I don't know that happened to the
> message. I'll try again with this one.
This is weird - is the list stripping attachments?
I CCd the message to you, Rick. Did you get the attachment?
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
----- Original Message -----
From: "John Wilson" <tu...@wilson.co.uk>
To: <rp...@xml.apache.org>
Cc: <rb...@photoaccess.com>
Sent: Sunday, March 10, 2002 8:21 AM
Subject: Re: Bas64 encoding performance
[snip]
> I sent an email with the patches as an attachment to the list a couple
> of minutes after the first message. I don't know that happened to the
> message. I'll try again with this one.
This is weird - is the list stripping attachments?
I CCd the message to you, Rick. Did you get the attachment?
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
----- Original Message -----
From: "Rick Blair" <rb...@photoaccess.com>
To: <rp...@xml.apache.org>
Sent: Sunday, March 10, 2002 1:03 AM
Subject: Re: Bas64 encoding performance
> John,
>
> Looks good. I would like to have them, Any change getting it
> patched in the apache surce tree. If so then +1.
Rick,
I sent an email with the patches as an attachment to the list a couple
of minutes after the first message. I don't know that happened to the
message. I'll try again with this one.
Note the code is a first cut. The Base64 methods throw Error when they find
a problem with the Base64 format (the previous code seems to ignore
formatting errors). This obviously needs to be changed to a checked
exception and the calling code needs to deal with the error. Also the static
tables are set up in a bizarre way in order to reduce the size of the class
file. This is an issue in the systems which run MinML-RPC but not in the
ones which run the Apache XML-RPC system.
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by John Wilson <tu...@wilson.co.uk>.
----- Original Message -----
From: "Rick Blair" <rb...@photoaccess.com>
To: <rp...@xml.apache.org>
Sent: Sunday, March 10, 2002 1:03 AM
Subject: Re: Bas64 encoding performance
> John,
>
> Looks good. I would like to have them, Any change getting it
> patched in the apache surce tree. If so then +1.
Rick,
I sent an email with the patches as an attachment to the list a couple
of minutes after the first message. I don't know that happened to the
message. I'll try again with this one.
Note the code is a first cut. The Base64 methods throw Error when they find
a problem with the Base64 format (the previous code seems to ignore
formatting errors). This obviously needs to be changed to a checked
exception and the calling code needs to deal with the error. Also the static
tables are set up in a bizarre way in order to reduce the size of the class
file. This is an issue in the systems which run MinML-RPC but not in the
ones which run the Apache XML-RPC system.
John Wilson
The Wilson Partnership
http://www.wilson.co.uk
Re: Bas64 encoding performance
Posted by Rick Blair <rb...@photoaccess.com>.
John,
Looks good. I would like to have them, Any change getting it
patched in the apache surce tree. If so then +1.
Rick
At 08:58 PM 3/9/02 -0000, you wrote:
>I have been looking at the performance of the latest version of the Apache
>XML-RPC system when transferring 1Mb byte arrays via base64 encoding. That
>is to say I have been running the TestBase64 benchmark.
>
>On my test system (Sun 1.3 JVM on Win2K) here the "old Helma" XML-RPC system
>runs the TestBase64 benchmark (from the current CVS tree) in ~54 seconds.
>The latest version from CVS runs the same benchmark in ~77 seconds. I have
>replaced the Base64 implementation with a version of the Base64
>encode/decoding from MinML-RPC and tidied up the interfacing of this to the
>rest of the code (avoiding converting from StringBuffer to String, returning
>a char array rather than a byte array and the consequential changes). This
>now runs the benchmark in ~26 seconds.
>
>Are you interested in having these patches?
>
>John Wilson
>The Wilson Partnership
>http://www.wilson.co.uk
>
Re: Bas64 encoding performance
Posted by Rick Blair <rb...@photoaccess.com>.
John,
Looks good. I would like to have them, Any change getting it
patched in the apache surce tree. If so then +1.
Rick
At 08:58 PM 3/9/02 -0000, you wrote:
>I have been looking at the performance of the latest version of the Apache
>XML-RPC system when transferring 1Mb byte arrays via base64 encoding. That
>is to say I have been running the TestBase64 benchmark.
>
>On my test system (Sun 1.3 JVM on Win2K) here the "old Helma" XML-RPC system
>runs the TestBase64 benchmark (from the current CVS tree) in ~54 seconds.
>The latest version from CVS runs the same benchmark in ~77 seconds. I have
>replaced the Base64 implementation with a version of the Base64
>encode/decoding from MinML-RPC and tidied up the interfacing of this to the
>rest of the code (avoiding converting from StringBuffer to String, returning
>a char array rather than a byte array and the consequential changes). This
>now runs the benchmark in ~26 seconds.
>
>Are you interested in having these patches?
>
>John Wilson
>The Wilson Partnership
>http://www.wilson.co.uk
>
Re: Bas64 encoding performance
Posted by Jon Scott Stevens <jo...@latchkey.com>.
> Are you interested in having these patches?
Twist my arm.
-jon
Re: Bas64 encoding performance
Posted by Jon Scott Stevens <jo...@latchkey.com>.
> Are you interested in having these patches?
Twist my arm.
-jon