Return-Path: Delivered-To: apmail-activemq-commits-archive@www.apache.org Received: (qmail 44114 invoked from network); 14 Apr 2009 14:05:35 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 14 Apr 2009 14:05:35 -0000 Received: (qmail 21576 invoked by uid 500); 14 Apr 2009 14:05:34 -0000 Delivered-To: apmail-activemq-commits-archive@activemq.apache.org Received: (qmail 21522 invoked by uid 500); 14 Apr 2009 14:05:34 -0000 Mailing-List: contact commits-help@activemq.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@activemq.apache.org Delivered-To: mailing list commits@activemq.apache.org Received: (qmail 21513 invoked by uid 99); 14 Apr 2009 14:05:34 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 14 Apr 2009 14:05:34 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 14 Apr 2009 14:05:26 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id D8003238898F; Tue, 14 Apr 2009 14:05:05 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r764780 - in /activemq/activemq-cpp/trunk/activemq-cpp/src: main/ main/activemq/commands/ main/activemq/wireformat/openwire/marshal/ main/activemq/wireformat/openwire/utils/ main/decaf/io/ test/activemq/wireformat/openwire/utils/ test/decaf... Date: Tue, 14 Apr 2009 14:05:05 -0000 To: commits@activemq.apache.org From: tabish@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090414140505.D8003238898F@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: tabish Date: Tue Apr 14 14:05:04 2009 New Revision: 764780 URL: http://svn.apache.org/viewvc?rev=764780&view=rev Log: http://issues.apache.org/activemq/browse/AMQCPP-235 Fixed the DataInputStream, DataOutputStream and OpenwireStringSupport classes to all read and write correct modified UTF-8 strings for all ascii values 0-255. OpenwireStringSupport now correctly write the data with an int size prefix to support larger strings enabling primitive maps to store strings larger than 65535 characters. Added: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h (with props) Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/Makefile.am activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/commands/ActiveMQTextMessage.cpp activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/marshal/PrimitiveMapMarshaller.cpp activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/utils/OpenwireStringSupport.cpp activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.cpp activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.h activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.cpp activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.h activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.cpp activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.h activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.cpp activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.h activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.cpp activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.h Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/Makefile.am URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/Makefile.am?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/main/Makefile.am (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/Makefile.am Tue Apr 14 14:05:04 2009 @@ -573,6 +573,7 @@ decaf/io/BufferedOutputStream.h \ decaf/io/ByteArrayInputStream.h \ decaf/io/OutputStream.h \ + decaf/io/UTFDataFormatException.h \ decaf/io/BufferedInputStream.h \ decaf/io/DataInputStream.h \ decaf/io/IOException.h \ Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/commands/ActiveMQTextMessage.cpp URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/commands/ActiveMQTextMessage.cpp?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/commands/ActiveMQTextMessage.cpp (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/commands/ActiveMQTextMessage.cpp Tue Apr 14 14:05:04 2009 @@ -18,11 +18,15 @@ #include #include +#include using namespace std; using namespace activemq; using namespace activemq::exceptions; using namespace activemq::commands; +using namespace activemq::wireformat; +using namespace activemq::wireformat::openwire; +using namespace activemq::wireformat::openwire::utils; using namespace decaf::lang; //////////////////////////////////////////////////////////////////////////////// @@ -67,10 +71,9 @@ std::vector& content = getContent(); content.clear(); decaf::io::ByteArrayOutputStream bos( content ); - decaf::io::DataOutputStream dos( &bos ); + decaf::io::DataOutputStream dataOut( &bos ); - dos.writeInt( (int)msg.length() ); - dos.write( (const unsigned char*)msg.c_str(), 0, msg.length() ); + OpenwireStringSupport::writeString( dataOut, &msg ); } AMQ_CATCH_ALL_THROW_CMSEXCEPTION() } Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/marshal/PrimitiveMapMarshaller.cpp URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/marshal/PrimitiveMapMarshaller.cpp?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/marshal/PrimitiveMapMarshaller.cpp (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/marshal/PrimitiveMapMarshaller.cpp Tue Apr 14 14:05:04 2009 @@ -23,6 +23,7 @@ #include #include #include +#include using namespace activemq; using namespace activemq::util; @@ -72,7 +73,7 @@ PrimitiveMap* map = new PrimitiveMap; for( int i=0; i < size; i++ ) { - std::string key = OpenwireStringSupport::readString( dataIn ); + std::string key = dataIn.readUTF(); map->put( key, unmarshalPrimitive( dataIn ) ); } @@ -124,7 +125,7 @@ for(; iter != keys.end(); ++iter ) { - OpenwireStringSupport::writeString( dataOut, &(*iter) ); + dataOut.writeUTF( *iter ); PrimitiveValueNode value = map.get( *iter ); marshalPrimitive( dataOut, value ); } @@ -213,14 +214,14 @@ std::string data = value.getString(); // is the string big?? - if( data.size() > 8191 ) { + if( data.size() > Short::MAX_VALUE / 4 ) { dataOut.writeByte( PrimitiveValueNode::BIG_STRING_TYPE ); + OpenwireStringSupport::writeString( dataOut, &data ); } else { dataOut.writeByte( PrimitiveValueNode::STRING_TYPE ); + dataOut.writeUTF( data ); } - OpenwireStringSupport::writeString( dataOut, &data ); - } else if( value.getValueType() == PrimitiveValueNode::LIST_TYPE ) { dataOut.writeByte( PrimitiveValueNode::LIST_TYPE ); @@ -254,7 +255,7 @@ if( size > 0 ) { for( int i=0; i < size; i++ ) { - std::string key = OpenwireStringSupport::readString( dataIn ); + std::string key = dataIn.readUTF(); map.put( key, unmarshalPrimitive( dataIn ) ); } } @@ -331,6 +332,8 @@ break; } case PrimitiveValueNode::STRING_TYPE: + value.setString( dataIn.readUTF() ); + break; case PrimitiveValueNode::BIG_STRING_TYPE: value.setString( OpenwireStringSupport::readString( dataIn ) ); break; Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/utils/OpenwireStringSupport.cpp URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/utils/OpenwireStringSupport.cpp?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/utils/OpenwireStringSupport.cpp (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/utils/OpenwireStringSupport.cpp Tue Apr 14 14:05:04 2009 @@ -34,71 +34,86 @@ try { - short utflen = dataIn.readShort(); + int utfLength = dataIn.readInt(); - if( utflen > -1 ) - { - // Let the stream get us all that data. - std::vector value; - value.resize( utflen ); - dataIn.readFully( value ); - - unsigned char c = 0; - int count = 0; - - // x counts the number of 2-byte UTF8 sequences decoded - int x = 0; - - while( count+x < utflen ) - { - c = value[count+x]; - switch( c >> 4 ) - { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - // 1-byte UTF8 encoding: 0xxxxxxx - value[count] = c; - count++; - break; - case 12: - case 13: - // 2-byte UTF8 encoding: 110X XXxx 10xx xxxx - // Bits set at 'X' means we have encountered a UTF8 encoded value - // greater than 255, which is not supported. - if( c & 0x1C ) { - throw IOException( - __FILE__, - __LINE__, - "OpenwireStringSupport::readString - Encoding not supported" ); - } - // Place the decoded UTF8 character back into the value array - value[count] = ((c & 0x1F) << 6) | (value[count+x+1] & 0x3F); - count++; - x++; - break; - case 14: - default: - { - // 3-byte UTF8 encoding: 1110 xxxx 10xx xxxx 10xx xxxx - throw IOException( - __FILE__, - __LINE__, - "OpenwireStringSupport::readString - Encoding not supported" ); - } + if( utfLength == -1 ) { + return ""; + } + + std::vector buffer( utfLength ); + std::string result( utfLength, char() ); + + dataIn.readFully( &buffer[0], 0, utfLength ); + + int count = 0; + int index = 0; + unsigned char a = 0; + + while( count < utfLength ) { + if( (unsigned char)( result[index] = (char)buffer[count++] ) < 0x80 ) { + index++; + } else if( ( ( a = result[index++] ) & 0xE0 ) == 0xC0 ) { + if( count >= utfLength ) { + throw UTFDataFormatException( + __FILE__, __LINE__, + "Invalid UTF-8 encoding found, start of two byte char found at end."); + } + + unsigned char b = buffer[count++]; + if( ( b & 0xC0 ) != 0x80 ) { + throw UTFDataFormatException( + __FILE__, __LINE__, + "Invalid UTF-8 encoding found, byte two does not start with 0x80." ); } - } - // Let the Compiler give us a string. - return std::string(reinterpret_cast(&value[0]), count); + // 2-byte UTF8 encoding: 110X XXxx 10xx xxxx + // Bits set at 'X' means we have encountered a UTF8 encoded value + // greater than 255, which is not supported. + if( a & 0x1C ) { + throw UTFDataFormatException( + __FILE__, __LINE__, + "Invalid 2 byte UTF-8 encoding found, " + "This method only supports encoded ASCII values of (0-255)." ); + } + + result[index++] = (char)( ( ( a & 0x1F ) << 6 ) | ( b & 0x3F ) ); + + } else if( ( a & 0xF0 ) == 0xE0 ) { + + if( count + 1 >= utfLength ) { + throw UTFDataFormatException( + __FILE__, __LINE__, + "Invalid UTF-8 encoding found, start of three byte char found at end."); + } else { + throw UTFDataFormatException( + __FILE__, __LINE__, + "Invalid 3 byte UTF-8 encoding found, " + "This method only supports encoded ASCII values of (0-255)." ); + } + + // If we were to support multibyte strings in the future this would be + // the remainder of this method decoding logic. + // + //int b = buffer[count++]; + //int c = buffer[count++]; + //if( ( ( b & 0xC0 ) != 0x80 ) || ( ( c & 0xC0 ) != 0x80 ) ) { + // throw UTFDataFormatException( + // __FILE__, __LINE__, + // "Invalid UTF-8 encoding found, byte two does not start with 0x80." ); + //} + // + //result[inde++] = (char)( ( ( a & 0x0F ) << 12 ) | + // ( ( b & 0x3F ) << 6 ) | ( c & 0x3F ) ); + + } else { + throw UTFDataFormatException( + __FILE__, __LINE__, "Invalid UTF-8 encoding found, aborting."); + } } - return ""; + result.resize( index ); + + return result; } AMQ_CATCH_RETHROW( decaf::io::IOException ) AMQ_CATCH_EXCEPTION_CONVERT( Exception, decaf::io::IOException ) @@ -114,50 +129,60 @@ if( str != NULL ) { - if( str->size() > 65536 ) { + int utfLength = 0; + std::size_t length = str->length(); - throw IOException( - __FILE__, - __LINE__, - ( std::string( "OpenwireStringSupport::writeString - Cannot marshall " ) + - "string longer than: 65536 characters, supplied string was: " + - Integer::toString( (int)str->size() ) + " characters long." ).c_str() ); - } + for( std::size_t i = 0; i < length; ++i ) { + + unsigned int charValue = (unsigned char)str->at( i ); - unsigned short utflen = 0; - int count = 0; - unsigned char c; - - std::string::const_iterator iter = str->begin(); - - for(; iter != str->end(); ++iter ) { - c = *iter; - if( c < 0x80 ) { - utflen++; + // Written to allow for expansion to wide character strings at some + // point, as it stands now the value can never be > 255 since the + // string class returns a single byte char. + if( charValue > 0 && charValue <= 127 ) { + utfLength++; + } else if( charValue <= 2047 ) { + utfLength += 2; } else { - utflen += 2; + utfLength += 3; } } - dataOut.writeUnsignedShort( utflen ); - std::vector byteArr; - byteArr.resize( utflen ); - - for( iter = str->begin(); iter != str->end(); ++iter ) { - - c = *iter; - if( c < 0x80 ) { - byteArr[count++] = (unsigned char)c; + if( utfLength > Integer::MAX_VALUE ) { + throw UTFDataFormatException( + __FILE__, __LINE__, + ( std::string( "OpenwireStringSupport::writeString - Cannot marshall " ) + + "string utf8 encoding longer than: 2^31 bytes, supplied string utf8 encoding was: " + + Integer::toString( (int)utfLength ) + " bytes long." ).c_str() ); + } + + std::vector utfBytes( (std::size_t)utfLength ); + unsigned int utfIndex = 0; + + for( std::size_t i = 0; i < length; i++ ) { + + unsigned int charValue = (unsigned char)str->at( i ); + + // Written to allow for expansion to wide character strings at some + // point, as it stands now the value can never be > 255 since the + // string class returns a single byte char. + if( charValue > 0 && charValue <= 127 ) { + utfBytes[utfIndex++] = (unsigned char)charValue; + } else if( charValue <= 2047 ) { + utfBytes[utfIndex++] = (unsigned char)(0xc0 | (0x1f & (charValue >> 6))); + utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & charValue)); } else { - byteArr[count++] = (unsigned char)( 0xC0 | ( (c >> 6) & 0x1F) ); - byteArr[count++] = (unsigned char)( 0x80 | ( (c >> 0) & 0x3F) ); + utfBytes[utfIndex++] = (unsigned char)(0xe0 | (0x0f & (charValue >> 12))); + utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & (charValue >> 6))); + utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & charValue)); } } - dataOut.write( byteArr ); + dataOut.writeInt( utfLength ); + dataOut.write( &utfBytes[0], 0, utfLength ); } else { - dataOut.writeShort( (short)-1 ); + dataOut.writeInt( -1 ); } } AMQ_CATCH_RETHROW( decaf::io::IOException ) Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.cpp URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.cpp?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.cpp (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.cpp Tue Apr 14 14:05:04 2009 @@ -32,8 +32,7 @@ DataInputStream::~DataInputStream() {} //////////////////////////////////////////////////////////////////////////////// -int DataInputStream::read( std::vector& buffer ) - throw ( io::IOException ) { +int DataInputStream::read( std::vector& buffer ) throw ( io::IOException ) { try { return this->read( &buffer[0], 0, buffer.size() ); @@ -75,13 +74,11 @@ } //////////////////////////////////////////////////////////////////////////////// -bool DataInputStream::readBoolean() - throw( IOException, EOFException ) { +bool DataInputStream::readBoolean() throw( IOException, EOFException ) { try { - unsigned char value = 0; - readAllData( &value, sizeof(value) ); - return (bool)( value != 0 ); + readAllData( buffer, sizeof(char) ); + return (bool)( buffer[0] != 0 ); } DECAF_CATCH_RETHROW( EOFException ) DECAF_CATCH_RETHROW( IOException ) @@ -89,13 +86,11 @@ } //////////////////////////////////////////////////////////////////////////////// -char DataInputStream::readByte() - throw ( IOException, EOFException ) { +char DataInputStream::readByte() throw ( IOException, EOFException ) { try { - unsigned char value = 0; - readAllData( &value, sizeof(value) ); - return (char)( value ); + readAllData( buffer, sizeof(unsigned char) ); + return (char)( buffer[0] ); } DECAF_CATCH_RETHROW( EOFException ) DECAF_CATCH_RETHROW( IOException ) @@ -103,13 +98,11 @@ } //////////////////////////////////////////////////////////////////////////////// -unsigned char DataInputStream::readUnsignedByte() - throw ( IOException, EOFException ) { +unsigned char DataInputStream::readUnsignedByte() throw ( IOException, EOFException ) { try { - unsigned char value = 0; - readAllData( &value, sizeof(value) ); - return value; + readAllData( buffer, sizeof(unsigned char) ); + return buffer[0]; } DECAF_CATCH_RETHROW( EOFException ) DECAF_CATCH_RETHROW( IOException ) @@ -118,10 +111,10 @@ //////////////////////////////////////////////////////////////////////////////// char DataInputStream::readChar() throw ( IOException, EOFException ) { + try { - unsigned char value = 0; - readAllData( &value, sizeof(value) ); - return (char)( value ); + readAllData( buffer, sizeof(unsigned char) ); + return (char)( buffer[0] ); } DECAF_CATCH_RETHROW( EOFException ) DECAF_CATCH_RETHROW( IOException ) @@ -130,10 +123,10 @@ //////////////////////////////////////////////////////////////////////////////// short DataInputStream::readShort() throw ( io::IOException, io::EOFException ) { + try { short value = 0; - unsigned char buffer[sizeof(value)] = {0}; - readAllData( buffer, sizeof(value) ); + readAllData( buffer, sizeof(short) ); value |= (buffer[0] << 8 | buffer[1] << 0); return value; } @@ -143,12 +136,11 @@ } //////////////////////////////////////////////////////////////////////////////// -unsigned short DataInputStream::readUnsignedShort() - throw ( io::IOException, io::EOFException ) { +unsigned short DataInputStream::readUnsignedShort() throw ( io::IOException, io::EOFException ) { + try { unsigned short value = 0; - unsigned char buffer[sizeof(value)] = {0}; - readAllData( buffer, sizeof(value) ); + readAllData( buffer, sizeof(unsigned short) ); value |= (buffer[0] << 8 | buffer[1] << 0); return value; } @@ -159,10 +151,10 @@ //////////////////////////////////////////////////////////////////////////////// int DataInputStream::readInt() throw ( io::IOException, io::EOFException ) { + try { unsigned int value = 0; - unsigned char buffer[sizeof(value)] = {0}; - readAllData( buffer, sizeof(value) ); + readAllData( buffer, sizeof(int) ); value |= (buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3] << 0); return value; @@ -174,6 +166,7 @@ //////////////////////////////////////////////////////////////////////////////// double DataInputStream::readDouble() throw ( io::IOException, io::EOFException ) { + try { unsigned long long lvalue = this->readLong(); double value = 0.0; @@ -187,6 +180,7 @@ //////////////////////////////////////////////////////////////////////////////// float DataInputStream::readFloat() throw ( io::IOException, io::EOFException ) { + try { unsigned int lvalue = this->readInt(); float value = 0.0f; @@ -201,10 +195,10 @@ //////////////////////////////////////////////////////////////////////////////// long long DataInputStream::readLong() throw ( io::IOException, io::EOFException ) { + try { unsigned long long value = 0; - unsigned char buffer[sizeof(value)] = {0}; - readAllData( buffer, sizeof(value) ); + readAllData( buffer, sizeof(long long) ); // Have to do it this way because on Solaris and Cygwin we get all // kinds of warnings when shifting a byte up into a long long. @@ -228,8 +222,8 @@ } //////////////////////////////////////////////////////////////////////////////// -std::string DataInputStream::readString() - throw ( io::IOException, io::EOFException ) { +std::string DataInputStream::readString() throw ( io::IOException, io::EOFException ) { + try { if( inputStream == NULL ) { @@ -271,7 +265,8 @@ //////////////////////////////////////////////////////////////////////////////// std::string DataInputStream::readUTF() - throw ( io::IOException, io::EOFException ) { + throw ( io::IOException, io::EOFException, io::UTFDataFormatException ) { + try { if( inputStream == NULL ) { @@ -280,23 +275,83 @@ "DataInputStream::readFully - Base input stream is null" ); } - std::vector buffer; - unsigned short length = readUnsignedShort(); - buffer.resize(length + 1); // Add one for a null charactor. - - std::size_t n = 0; - while( n < length ) { - int count = inputStream->read( &buffer[n], 0, (length - n) ); - if( count == -1 ) { - throw EOFException( - __FILE__, __LINE__, - "DataInputStream::readUTF - Reached EOF" ); + unsigned short utfLength = readUnsignedShort(); + std::vector buffer( utfLength ); + std::string result( utfLength, char() ); + + this->readFully( &buffer[0], 0, utfLength ); + + std::size_t count = 0; + std::size_t index = 0; + unsigned char a = 0; + + while( count < utfLength ) { + if( (unsigned char)( result[index] = (char)buffer[count++] ) < 0x80 ) { + index++; + } else if( ( ( a = result[index++] ) & 0xE0 ) == 0xC0 ) { + if( count >= utfLength ) { + throw UTFDataFormatException( + __FILE__, __LINE__, + "Invalid UTF-8 encoding found, start of two byte char found at end."); + } + + unsigned char b = buffer[count++]; + if( ( b & 0xC0 ) != 0x80 ) { + throw UTFDataFormatException( + __FILE__, __LINE__, + "Invalid UTF-8 encoding found, byte two does not start with 0x80." ); + } + + // 2-byte UTF8 encoding: 110X XXxx 10xx xxxx + // Bits set at 'X' means we have encountered a UTF8 encoded value + // greater than 255, which is not supported. + if( a & 0x1C ) { + throw UTFDataFormatException( + __FILE__, __LINE__, + "Invalid 2 byte UTF-8 encoding found, " + "This method only supports encoded ASCII values of (0-255)." ); + } + + result[index++] = (char)( ( ( a & 0x1F ) << 6 ) | ( b & 0x3F ) ); + + } else if( ( a & 0xF0 ) == 0xE0 ) { + + if( count + 1 >= utfLength ) { + throw UTFDataFormatException( + __FILE__, __LINE__, + "Invalid UTF-8 encoding found, start of three byte char found at end."); + } else { + throw UTFDataFormatException( + __FILE__, __LINE__, + "Invalid 3 byte UTF-8 encoding found, " + "This method only supports encoded ASCII values of (0-255)." ); + } + + // If we were to support multibyte strings in the future this would be + // the remainder of this method decoding logic. + // + //int b = buffer[count++]; + //int c = buffer[count++]; + //if( ( ( b & 0xC0 ) != 0x80 ) || ( ( c & 0xC0 ) != 0x80 ) ) { + // throw UTFDataFormatException( + // __FILE__, __LINE__, + // "Invalid UTF-8 encoding found, byte two does not start with 0x80." ); + //} + // + //result[inde++] = (char)( ( ( a & 0x0F ) << 12 ) | + // ( ( b & 0x3F ) << 6 ) | ( c & 0x3F ) ); + + } else { + throw UTFDataFormatException( + __FILE__, __LINE__, "Invalid UTF-8 encoding found, aborting."); } - n += count; } - return (char*)&buffer[0]; + result.resize( index ); + + return result; } + DECAF_CATCH_RETHROW( UTFDataFormatException ) DECAF_CATCH_RETHROW( EOFException ) DECAF_CATCH_RETHROW( IOException ) DECAF_CATCHALL_THROW( IOException ) @@ -305,6 +360,7 @@ //////////////////////////////////////////////////////////////////////////////// void DataInputStream::readFully( std::vector< unsigned char >& buffer ) throw ( io::IOException, io::EOFException ) { + try { if( buffer.empty() ) { return; @@ -362,6 +418,7 @@ //////////////////////////////////////////////////////////////////////////////// std::size_t DataInputStream::skip( std::size_t num ) throw( io::IOException, lang::exceptions::UnsupportedOperationException ) { + try { if( inputStream == NULL ) { Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.h URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.h?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.h (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.h Tue Apr 14 14:05:04 2009 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -39,9 +40,16 @@ * creation of the underlying stream can occur in a Java like way. Ex: * * DataInputStream os = new DataInputStream( new InputStream(), true ) + * + * @since 1.0 */ - class DECAF_API DataInputStream : public FilterInputStream - { + class DECAF_API DataInputStream : public FilterInputStream { + private: + + // Buffer used to store bytes read from the stream while reconstructed into + // higher order C++ primitives. + unsigned char buffer[8]; + public: /** @@ -266,15 +274,22 @@ throw ( io::IOException, io::EOFException ); /** - * Reads a UTF8 encoded string in ASCII format and returns it, this is - * only useful if you know for sure that the string that is to be read - * was a string that contained all ascii values, and not uncide chars. - * @returns string read from stream. + * Reads a modified UTF-8 encoded string in ASCII format and returns it, + * this is only useful if you know for sure that the string that is to be read + * was a string that contained all ASCII values (0-255), if so this method will + * throw a UTFFormatException. This method reads String value written from a + * Java DataOutputStream and assumes that the length prefix the precedes the + * encoded UTF-8 bytes is an unsigned short, which implies that the String will + * be no longer than 65535 characters. + * + * @returns The decoded string read from stream. + * * @throws IOException * @throws EOFException + * @throws UTFDataFormatException */ virtual std::string readUTF() - throw ( io::IOException, io::EOFException ); + throw ( io::IOException, io::EOFException, io::UTFDataFormatException ); /** * Reads some bytes from an input stream and stores them into the Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.cpp URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.cpp?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.cpp (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.cpp Tue Apr 14 14:05:04 2009 @@ -16,6 +16,7 @@ */ #include +#include #include #include #include @@ -113,8 +114,8 @@ //////////////////////////////////////////////////////////////////////////////// void DataOutputStream::writeBoolean( bool value ) throw ( IOException ) { try { - unsigned char ivalue = 0; - value == true ? ivalue = 1 : ivalue = 0; + + value == true ? buffer[0] = 1 : buffer[0] = 0; if( outputStream == NULL ) { throw IOException( @@ -122,7 +123,7 @@ "DataOutputStream::write - Base stream is Null"); } - outputStream->write( ivalue ); + outputStream->write( buffer[0] ); written++; } DECAF_CATCH_RETHROW( IOException ) @@ -173,8 +174,6 @@ "DataOutputStream::write - Base stream is Null"); } - unsigned char buffer[sizeof(value)]; - buffer[0] = (value & 0xFF00) >> 8; buffer[1] = (value & 0x00FF) >> 0; @@ -197,8 +196,6 @@ "DataOutputStream::write - Base stream is Null"); } - unsigned char buffer[sizeof(value)]; - buffer[0] = (value & 0xFF00) >> 8; buffer[1] = (value & 0x00FF) >> 0; @@ -219,8 +216,6 @@ "DataOutputStream::write - Base stream is Null"); } - unsigned char buffer[sizeof(value)]; - buffer[0] = (value & 0xFF000000) >> 24; buffer[1] = (value & 0x00FF0000) >> 16; buffer[2] = (value & 0x0000FF00) >> 8; @@ -243,8 +238,6 @@ "DataOutputStream::write - Base stream is Null"); } - unsigned char buffer[sizeof(value)]; - buffer[0] = (unsigned char)((value & 0xFF00000000000000ULL) >> 56); buffer[1] = (unsigned char)((value & 0x00FF000000000000ULL) >> 48); buffer[2] = (unsigned char)((value & 0x0000FF0000000000ULL) >> 40); @@ -314,16 +307,72 @@ } //////////////////////////////////////////////////////////////////////////////// -void DataOutputStream::writeUTF( const std::string& value ) throw ( IOException ) { +void DataOutputStream::writeUTF( const std::string& value ) + throw ( IOException, UTFDataFormatException ) { + try { - if( value.length() == 0 ) { - return; + unsigned int utfLength = this->countUTFLength( value ); + + if( utfLength > 65535 ) { + throw UTFDataFormatException( + __FILE__, __LINE__, + "Attempted to write a string as UTF-8 whose length is longer " + "than the supported 65535 bytes" ); } - this->writeUnsignedShort( (unsigned short)value.length() ); - this->write( (const unsigned char*)value.c_str(), 0, value.length() ); + std::size_t length = value.length(); + std::vector utfBytes( (std::size_t)utfLength ); + unsigned int utfIndex = 0; + + for( std::size_t i = 0; i < length; i++ ) { + + unsigned int charValue = (unsigned char)value.at( i ); + + // Written to allow for expansion to wide character strings at some + // point, as it stands now the value can never be > 255 since the + // string class returns a single byte char. + if( charValue > 0 && charValue <= 127 ) { + utfBytes[utfIndex++] = (unsigned char)charValue; + } else if( charValue <= 2047 ) { + utfBytes[utfIndex++] = (unsigned char)(0xc0 | (0x1f & (charValue >> 6))); + utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & charValue)); + } else { + utfBytes[utfIndex++] = (unsigned char)(0xe0 | (0x0f & (charValue >> 12))); + utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & (charValue >> 6))); + utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & charValue)); + } + } + + this->writeUnsignedShort( (unsigned short)utfLength ); + this->write( &utfBytes[0], 0, utfIndex ); } + DECAF_CATCH_RETHROW( UTFDataFormatException ) DECAF_CATCH_RETHROW( IOException ) DECAF_CATCHALL_THROW( IOException ) } + +//////////////////////////////////////////////////////////////////////////////// +unsigned int DataOutputStream::countUTFLength( const std::string& value ) { + + unsigned int utfCount = 0; + std::size_t length = value.length(); + + for( std::size_t i = 0; i < length; ++i ) { + + unsigned int charValue = (unsigned char)value.at( i ); + + // Written to allow for expansion to wide character strings at some + // point, as it stands now the value can never be > 255 since the + // string class returns a single byte char. + if( charValue > 0 && charValue <= 127 ) { + utfCount++; + } else if( charValue <= 2047 ) { + utfCount += 2; + } else { + utfCount += 3; + } + } + + return utfCount; +} Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.h URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.h?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.h (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.h Tue Apr 14 14:05:04 2009 @@ -19,6 +19,9 @@ #define _DECAF_IO_DATAOUTPUTSTREAM_H_ #include +#include +#include +#include namespace decaf{ namespace io{ @@ -28,13 +31,15 @@ * types to an output stream in a portable way. An application can then * use a data input stream to read the data back in. */ - class DECAF_API DataOutputStream : public FilterOutputStream - { + class DECAF_API DataOutputStream : public FilterOutputStream { protected: // The number of bytes written to the data output stream so far. std::size_t written; + // Buffer used for storing byte values to write to the stream + unsigned char buffer[8]; + public: /** @@ -190,20 +195,33 @@ * characters. Each character is written to the data output stream * as if by the writeChar method. If no exception is thrown, the * counter written is incremented by the length of value. The trailing - * NULL charactor is written by this method. + * NULL character is written by this method. * @param value the value to write. * @throws IOException */ virtual void writeChars( const std::string& value ) throw ( IOException ); /** - * Writes out the string to the underlying output stream as a - * unsigned short indicating its length followed by the rest of - * the string. - * @param value the value to write. - * @throws IOException + * Writes out the string to the underlying output stream as a modeified UTF-8 + * encoded sequence of bytes. The first two bytes written are indicate its + * encoded length followed by the rest of the string's characters encoded as + * modified UTF-8. The length represent the encoded length of the data not the + * actual length of the string. + * + * @param value + * the value to write. + * + * @throws IOException - on a write error + * @throws UTFDataFormatException - if encoded size if greater than 65535 */ - virtual void writeUTF( const std::string& value ) throw ( IOException ); + virtual void writeUTF( const std::string& value ) + throw ( IOException, UTFDataFormatException ); + + private: + + // Determine the encoded length of a string when written as modified UTF-8 + unsigned int countUTFLength( const std::string& value ); + }; }} Added: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h?rev=764780&view=auto ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h (added) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h Tue Apr 14 14:05:04 2009 @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DECAF_IO_UTFDATAFORMATEXCEPTION_H_ +#define _DECAF_IO_UTFDATAFORMATEXCEPTION_H_ + +#include + +namespace decaf { +namespace io { + + /** + * Thrown from classes that attempt to read or write a UTF-8 encoded string + * and an encoding error is encountered. + * + * @since 1.0 + */ + class DECAF_API UTFDataFormatException : public decaf::io::IOException { + public: + + /** + * Default Constructor + */ + UTFDataFormatException() throw() {} + + /** + * Copy Constructor + * @param ex the exception to copy + */ + UTFDataFormatException( const lang::Exception& ex ) throw() + : IOException() + { + *(lang::Exception*)this = ex; + } + + /** + * Copy Constructor + * @param ex the exception to copy, which is an instance of this type + */ + UTFDataFormatException( const UTFDataFormatException& ex ) throw() + : IOException() + { + *(lang::Exception*)this = ex; + } + + /** + * Constructor - Initializes the file name and line number where + * this message occurred. Sets the message to report, using an + * optional list of arguments to parse into the message + * @param file name where exception occurs + * @param line number where the exception occurred. + * @param cause The exception that was the cause for this one to be thrown. + * @param message to report + * @param list of primitives that are formatted into the message + */ + UTFDataFormatException( const char* file, const int lineNumber, + const std::exception* cause, + const char* msg, ... ) throw() : IOException( cause ) + { + va_list vargs; + va_start( vargs, msg ); + buildMessage( msg, vargs ); + + // Set the first mark for this exception. + setMark( file, lineNumber ); + } + + /** + * Constructor + * @param cause Pointer to the exception that caused this one to + * be thrown, the object is cloned caller retains ownership. + */ + UTFDataFormatException( const std::exception* cause ) throw() : IOException( cause ) {} + + /** + * Constructor + * @param file name of the file were the exception occurred. + * @param lineNumber line where the exception occurred + * @param msg the message that was generated + */ + UTFDataFormatException( const char* file, const int lineNumber, + const char* msg, ... ) throw() + : IOException() + { + va_list vargs; + va_start( vargs, msg ); + buildMessage( msg, vargs ); + + // Set the first mark for this exception. + setMark( file, lineNumber ); + } + + /** + * Clones this exception. This is useful for cases where you need + * to preserve the type of the original exception as well as the message. + * All subclasses should override. + */ + virtual UTFDataFormatException* clone() const{ + return new UTFDataFormatException( *this ); + } + + virtual ~UTFDataFormatException() throw() {} + + }; + +}} + +#endif /* _DECAF_IO_UTFDATAFORMATEXCEPTION_H_ */ Propchange: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h ------------------------------------------------------------------------------ svn:eol-style = native Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.cpp URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.cpp?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.cpp (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.cpp Tue Apr 14 14:05:04 2009 @@ -23,6 +23,7 @@ #include #include #include +#include using namespace std; using namespace decaf; @@ -33,102 +34,195 @@ using namespace activemq::wireformat::openwire; using namespace activemq::wireformat::openwire::utils; - //////////////////////////////////////////////////////////////////////////////// -void OpenwireStringSupportTest::testHelper( unsigned char* input, int inputLength, - unsigned char* output, int outputLength, - bool negative ) { - try { - - ByteArrayInputStream bytesIn; - ByteArrayOutputStream bytesOut; - - DataInputStream dataIn( &bytesIn ); - DataOutputStream dataOut( &bytesOut ); - - bytesIn.setByteArray( input, inputLength ); - - string resultStr = OpenwireStringSupport::readString( dataIn ); - if( !negative ) { - CPPUNIT_ASSERT( resultStr == std::string( (char*)output, outputLength ) ); - - OpenwireStringSupport::writeString( dataOut, &resultStr ); - CPPUNIT_ASSERT( bytesOut.toString() == std::string( (char*)input, inputLength ) ); - } else { - CPPUNIT_ASSERT( 0 ); - } +void OpenwireStringSupportTest::writeTestHelper( unsigned char* input, int inputLength, + unsigned char* expect, int expectLength ) { + + ByteArrayOutputStream baos; + DataOutputStream writer( &baos ); + + std::string testStr( (char*)input, inputLength ); + OpenwireStringSupport::writeString( writer, &testStr ); + + const unsigned char* result = baos.toByteArray(); + + CPPUNIT_ASSERT( result[0] == 0x00 ); + CPPUNIT_ASSERT( result[1] == 0x00 ); + CPPUNIT_ASSERT( result[2] == 0x00 ); + CPPUNIT_ASSERT( result[3] == (unsigned char)( expectLength ) ); - } catch( Exception& e ) { - CPPUNIT_ASSERT( negative ); + for( std::size_t i = 4; i < baos.size(); ++i ) { + CPPUNIT_ASSERT( result[i] == expect[i-4] ); } } //////////////////////////////////////////////////////////////////////////////// -void OpenwireStringSupportTest::test() -{ - ByteArrayInputStream bytesIn; - ByteArrayOutputStream bytesOut; +void OpenwireStringSupportTest::testWriteString() { - DataInputStream dataIn( &bytesIn ); - DataOutputStream dataOut( &bytesOut ); + // Test data with 1-byte UTF8 encoding. + { + unsigned char input[] = {0x00, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64}; + unsigned char expect[] = {0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64}; - string testStr = "This is a test string for Openwire"; + writeTestHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); + } - OpenwireStringSupport::writeString( dataOut, &testStr ); + // Test data with 2-byte UT8 encoding. + { + unsigned char input[] = {0x00, 0xC2, 0xA9, 0xC3, 0xA6 }; + unsigned char expect[] = {0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 }; + writeTestHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); + } - // Move the output back to the input. - bytesIn.setByteArray( bytesOut.toByteArray(), bytesOut.size() ); + // Test data with 1-byte and 2-byte encoding with embedded NULL's. + { + unsigned char input[] = {0x00, 0x04, 0xC2, 0xA9, 0xC3, 0x00, 0xA6 }; + unsigned char expect[] = {0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 }; - string resultStr = OpenwireStringSupport::readString( dataIn ); + writeTestHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); + } - CPPUNIT_ASSERT( testStr == resultStr ); + // Test data with 1-byte and 2-byte encoding with embedded NULL's. + { + ByteArrayOutputStream baos; + ByteArrayInputStream bais; + DataOutputStream writer( &baos ); + DataInputStream dataIn( &bais ); + + OpenwireStringSupport::writeString( writer, NULL ); + + bais.setByteArray( baos.toByteArray(), baos.size() ); + + CPPUNIT_ASSERT( dataIn.readInt() == -1 ); + } +} + +//////////////////////////////////////////////////////////////////////////////// +void OpenwireStringSupportTest::readTestHelper( unsigned char* input, int inputLength, + unsigned char* expect, int expectLength ) { + + ByteArrayInputStream myStream( input, inputLength ); + DataInputStream reader( &myStream ); + + std::string result = reader.readUTF(); + + for( std::size_t i; i < result.length(); ++i ) { + CPPUNIT_ASSERT( (unsigned char)result[i] == expect[i] ); + } +} + +//////////////////////////////////////////////////////////////////////////////// +void OpenwireStringSupportTest::testReadString() { // Test data with 1-byte UTF8 encoding. { - unsigned char input[] = {0x00, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64}; - unsigned char output[] = {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64}; + unsigned char expect[] = {0x00, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64}; + unsigned char input[] = { 0x00, 0x00, 0x00, 0x0E ,0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64}; - testHelper( input, sizeof(input)/sizeof(unsigned char), - output, sizeof(output)/sizeof(unsigned char), false ); + readTestHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); } // Test data with 2-byte UT8 encoding. { - unsigned char input[] = {0x00, 0x04, 0xC2, 0xA9, 0xC3, 0xA6}; - unsigned char output[] = {0xA9, 0xE6}; - testHelper( input, sizeof(input)/sizeof(unsigned char), - output, sizeof(output)/sizeof(unsigned char), false ); + unsigned char expect[] = {0x00, 0xC2, 0xA9, 0xC3, 0xA6 }; + unsigned char input[] = { 0x00, 0x00, 0x00, 0x0A, 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 }; + readTestHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); } - // Test data with value greater than 255 in 2-byte encoding. - // Expect : IO Exception + // Test data with 1-byte and 2-byte encoding with embedded NULL's. { - unsigned char input[] = {0x00, 0x04, 0xC8, 0xA9, 0xC3, 0xA6}; - testHelper( input, sizeof(input)/sizeof(unsigned char), NULL, 0, true ); + unsigned char expect[] = {0x00, 0x04, 0xC2, 0xA9, 0xC3, 0x00, 0xA6 }; + unsigned char input[] = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 }; + + readTestHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); } - // Test data with value greater than 255 in 3-byte encoding. - // Expect : IO Exception + // Test with bad UTF-8 encoding, missing 2nd byte of two byte value { - unsigned char input[] = {0x00, 0x05, 0xE8, 0xA8, 0xA9, 0xC3, 0xA6}; - testHelper( input, sizeof(input)/sizeof(unsigned char), NULL, 0, true ); + unsigned char input[] = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 }; + + ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) ); + DataInputStream reader( &myStream ); + + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw a IOException", + OpenwireStringSupport::readString( reader ), + IOException ); } - // Test data with 1-byte encoding with embedded NULL's. + // Test with bad UTF-8 encoding, encoded value greater than 255 { - unsigned char input[] = {0x00, 0x0D, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x00, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00}; - unsigned char output[] = {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x00, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00}; + unsigned char input[] = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 }; + + ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) ); + DataInputStream reader( &myStream ); - testHelper( input, sizeof(input)/sizeof(unsigned char), - output, sizeof(output)/sizeof(unsigned char), false ); + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw a IOException", + OpenwireStringSupport::readString( reader ), + IOException ); } - // Test data with 1-byte and 2-byte encoding with embedded NULL's. + // Test data with value greater than 255 in 2-byte encoding. { - unsigned char input[] = {0x00, 0x11, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x00, 0xC2, 0xA9, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00, 0xC3, 0xA6}; - unsigned char output[] = {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x00, 0xA9, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00, 0xE6}; + unsigned char input[] = { 0x00, 0x00, 0x00, 0x04, 0xC8, 0xA9, 0xC3, 0xA6}; + ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) ); + DataInputStream reader( &myStream ); + + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw a IOException", + OpenwireStringSupport::readString( reader ), + IOException ); + } - testHelper( input, sizeof(input)/sizeof(unsigned char), - output, sizeof(output)/sizeof(unsigned char), false ); + // Test data with value greater than 255 in 3-byte encoding. + { + unsigned char input[] = { 0x00, 0x00, 0x00, 0x05, 0xE8, 0xA8, 0xA9, 0xC3, 0xA6}; + ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) ); + DataInputStream reader( &myStream ); + + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw a IOException", + OpenwireStringSupport::readString( reader ), + IOException ); + } + + // Test with three byte encode that's missing a last byte. + { + unsigned char input[] = { 0x00, 0x00, 0x00, 0x02, 0xE8, 0xA8}; + ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) ); + DataInputStream reader( &myStream ); + + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw a IOException", + OpenwireStringSupport::readString( reader ), + IOException ); } } + +//////////////////////////////////////////////////////////////////////////////// +void OpenwireStringSupportTest::test() { + + ByteArrayInputStream bytesIn; + ByteArrayOutputStream bytesOut; + + DataInputStream dataIn( &bytesIn ); + DataOutputStream dataOut( &bytesOut ); + + string testStr = "This is a test string for Openwire"; + + OpenwireStringSupport::writeString( dataOut, &testStr ); + + // Move the output back to the input. + bytesIn.setByteArray( bytesOut.toByteArray(), bytesOut.size() ); + + string resultStr = OpenwireStringSupport::readString( dataIn ); + + CPPUNIT_ASSERT( testStr == resultStr ); +} Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.h URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.h?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.h (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.h Tue Apr 14 14:05:04 2009 @@ -30,6 +30,8 @@ CPPUNIT_TEST_SUITE( OpenwireStringSupportTest ); CPPUNIT_TEST( test ); + CPPUNIT_TEST( testWriteString ); + CPPUNIT_TEST( testReadString ); CPPUNIT_TEST_SUITE_END(); public: @@ -39,8 +41,16 @@ void test(); - void testHelper( unsigned char* input, int inputLength, - unsigned char* output, int outputLength, bool negative ); + void testWriteString(); + void testReadString(); + + private: + + void readTestHelper( unsigned char* input, int inputLength, + unsigned char* expect, int expectLength ); + + void writeTestHelper( unsigned char* input, int inputLength, + unsigned char* expect, int expectLength ); }; Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.cpp URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.cpp?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.cpp (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.cpp Tue Apr 14 14:05:04 2009 @@ -516,3 +516,110 @@ CPPUNIT_ASSERT( true ); } } + +//////////////////////////////////////////////////////////////////////////////// +void DataInputStreamTest::testHelper( unsigned char* input, int inputLength, + unsigned char* expect, int expectLength ) { + + ByteArrayInputStream myStream( input, inputLength ); + DataInputStream reader( &myStream ); + + std::string result = reader.readUTF(); + + for( std::size_t i; i < result.length(); ++i ) { + CPPUNIT_ASSERT( (unsigned char)result[i] == expect[i] ); + } +} + +//////////////////////////////////////////////////////////////////////////////// +void DataInputStreamTest::testUTFDecoding() { + + // Test data with 1-byte UTF8 encoding. + { + unsigned char expect[] = {0x00, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64}; + unsigned char input[] = { 0x00, 0x0E ,0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64}; + + testHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); + } + + // Test data with 2-byte UT8 encoding. + { + unsigned char expect[] = {0x00, 0xC2, 0xA9, 0xC3, 0xA6 }; + unsigned char input[] = { 0x00, 0x0A, 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 }; + testHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); + } + + // Test data with 1-byte and 2-byte encoding with embedded NULL's. + { + unsigned char expect[] = {0x00, 0x04, 0xC2, 0xA9, 0xC3, 0x00, 0xA6 }; + unsigned char input[] = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 }; + + testHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); + } + + // Test with bad UTF-8 encoding, missing 2nd byte of two byte value + { + unsigned char input[] = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 }; + + ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) ); + DataInputStream reader( &myStream ); + + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw a UTFDataFormatException", + reader.readUTF(), + UTFDataFormatException ); + } + + // Test with bad UTF-8 encoding, encoded value greater than 255 + { + unsigned char input[] = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 }; + + ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) ); + DataInputStream reader( &myStream ); + + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw a UTFDataFormatException", + reader.readUTF(), + UTFDataFormatException ); + } + + // Test data with value greater than 255 in 2-byte encoding. + { + unsigned char input[] = {0x00, 0x04, 0xC8, 0xA9, 0xC3, 0xA6}; + ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) ); + DataInputStream reader( &myStream ); + + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw a UTFDataFormatException", + reader.readUTF(), + UTFDataFormatException ); + } + + // Test data with value greater than 255 in 3-byte encoding. + { + unsigned char input[] = {0x00, 0x05, 0xE8, 0xA8, 0xA9, 0xC3, 0xA6}; + ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) ); + DataInputStream reader( &myStream ); + + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw a UTFDataFormatException", + reader.readUTF(), + UTFDataFormatException ); + } + + // Test with three byte encode that's missing a last byte. + { + unsigned char input[] = {0x00, 0x02, 0xE8, 0xA8}; + ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) ); + DataInputStream reader( &myStream ); + + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw a UTFDataFormatException", + reader.readUTF(), + UTFDataFormatException ); + } + +} Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.h URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.h?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.h (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.h Tue Apr 14 14:05:04 2009 @@ -28,6 +28,7 @@ #include #include #include +#include namespace decaf{ namespace io{ @@ -38,6 +39,7 @@ CPPUNIT_TEST( test ); CPPUNIT_TEST( testString ); CPPUNIT_TEST( testUTF ); + CPPUNIT_TEST( testUTFDecoding ); CPPUNIT_TEST( testConstructor ); CPPUNIT_TEST( testRead1 ); CPPUNIT_TEST( testRead2 ); @@ -59,11 +61,11 @@ CPPUNIT_TEST( test_skipBytes ); CPPUNIT_TEST_SUITE_END(); - ByteArrayOutputStream* baos; - ByteArrayInputStream* bais; + std::auto_ptr baos; + std::auto_ptr bais; - DataOutputStream* os; - DataInputStream* is; + std::auto_ptr os; + std::auto_ptr is; std::string testData; @@ -72,23 +74,22 @@ virtual ~DataInputStreamTest(){} virtual void setUp(){ testData = "Test_All_Tests\nTest_decaf_io_BufferedInputStream\nTest_BufferedOutputStream\nTest_decaf_io_ByteArrayInputStream\nTest_decaf_io_ByteArrayOutputStream\nTest_decaf_io_DataInputStream\nTest_decaf_io_File\nTest_decaf_io_FileDescriptor\nTest_decaf_io_FileInputStream\nTest_decaf_io_FileNotFoundException\nTest_decaf_io_FileOutputStream\nTest_decaf_io_FilterInputStream\nTest_decaf_io_FilterOutputStream\nTest_decaf_io_InputStream\nTest_decaf_io_IOException\nTest_decaf_io_OutputStream\nTest_decaf_io_PrintStream\nTest_decaf_io_RandomAccessFile\nTest_decaf_io_SyncFailedException\nTest_decaf_lang_AbstractMethodError\nTest_decaf_lang_ArithmeticException\nTest_decaf_lang_ArrayIndexOutOfBoundsException\nTest_decaf_lang_ArrayStoreException\nTest_decaf_lang_Boolean\nTest_decaf_lang_Byte\nTest_decaf_lang_Character\nTest_decaf_lang_Class\nTest_decaf_lang_ClassCastException\nTest_decaf_lang_ClassCircularityError\nTest_decaf_lang_ClassFormatError\nTest_decaf_lang_ClassLoad er\nTest_decaf_lang_ClassNotFoundException\nTest_decaf_lang_CloneNotSupportedException\nTest_decaf_lang_Double\nTest_decaf_lang_Error\nTest_decaf_lang_Exception\nTest_decaf_lang_ExceptionInInitializerError\nTest_decaf_lang_Float\nTest_decaf_lang_IllegalAccessError\nTest_decaf_lang_IllegalAccessException\nTest_decaf_lang_IllegalArgumentException\nTest_decaf_lang_IllegalMonitorStateException\nTest_decaf_lang_IllegalThreadStateException\nTest_decaf_lang_IncompatibleClassChangeError\nTest_decaf_lang_IndexOutOfBoundsException\nTest_decaf_lang_InstantiationError\nTest_decaf_lang_InstantiationException\nTest_decaf_lang_Integer\nTest_decaf_lang_InternalError\nTest_decaf_lang_InterruptedException\nTest_decaf_lang_LinkageError\nTest_decaf_lang_Long\nTest_decaf_lang_Math\nTest_decaf_lang_NegativeArraySizeException\nTest_decaf_lang_NoClassDefFoundError\nTest_decaf_lang_NoSuchFieldError\nTest_decaf_lang_NoSuchMethodError\nTest_decaf_lang_NullPointerException\nTest_decaf_lang_Number\nTest _decaf_lang_NumberFormatException\nTest_decaf_lang_Object\nTest_decaf_lang_OutOfMemoryError\nTest_decaf_lang_RuntimeException\nTest_decaf_lang_SecurityManager\nTest_decaf_lang_Short\nTest_decaf_lang_StackOverflowError\nTest_decaf_lang_String\nTest_decaf_lang_StringBuffer\nTest_decaf_lang_StringIndexOutOfBoundsException\nTest_decaf_lang_System\nTest_decaf_lang_Thread\nTest_decaf_lang_ThreadDeath\nTest_decaf_lang_ThreadGroup\nTest_decaf_lang_Throwable\nTest_decaf_lang_UnknownError\nTest_decaf_lang_UnsatisfiedLinkError\nTest_decaf_lang_VerifyError\nTest_decaf_lang_VirtualMachineError\nTest_decaf_lang_vm_Image\nTest_decaf_lang_vm_MemorySegment\nTest_decaf_lang_vm_ROMStoreException\nTest_decaf_lang_vm_VM\nTest_decaf_lang_Void\nTest_decaf_net_BindException\nTest_decaf_net_ConnectException\nTest_decaf_net_DatagramPacket\nTest_decaf_net_DatagramSocket\nTest_decaf_net_DatagramSocketImpl\nTest_decaf_net_InetAddress\nTest_decaf_net_NoRouteToHostException\nTest_decaf_net_PlainDatagramSo cketImpl\nTest_decaf_net_PlainSocketImpl\nTest_decaf_net_Socket\nTest_decaf_net_SocketException\nTest_decaf_net_SocketImpl\nTest_decaf_net_SocketInputStream\nTest_decaf_net_SocketOutputStream\nTest_decaf_net_UnknownHostException\nTest_decaf_util_ArrayEnumerator\nTest_decaf_util_Date\nTest_decaf_util_EventObject\nTest_decaf_util_HashEnumerator\nTest_decaf_util_Hashtable\nTest_decaf_util_Properties\nTest_decaf_util_ResourceBundle\nTest_decaf_util_tm\nTest_decaf_util_Vector\n"; - baos = new ByteArrayOutputStream(); - os = new DataOutputStream( baos ); - is = NULL; - bais = NULL; + this->baos.reset( new ByteArrayOutputStream() ); + this->os.reset( new DataOutputStream( baos.get() ) ); } virtual void tearDown(){ try { - delete os; - delete baos; - delete is; - delete bais; + this->os.reset( NULL ); + this->baos.reset( NULL ); + this->is.reset( NULL ); + this->bais.reset( NULL ); } catch(...) {} } void test(); void testString(); void testUTF(); + void testUTFDecoding(); void testConstructor(); void testRead1(); void testRead2(); @@ -111,12 +112,12 @@ private: - void openDataInputStream() { - delete bais; - delete is; + void testHelper( unsigned char* input, int inputLength, + unsigned char* expect, int expectLength ); - bais = new ByteArrayInputStream( baos->toByteArray(), baos->size() ); - is = new DataInputStream( bais ); + void openDataInputStream() { + this->bais.reset( new ByteArrayInputStream( baos->toByteArray(), baos->size() ) ); + this->is.reset( new DataInputStream( bais.get() ) ); } }; Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.cpp URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.cpp?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.cpp (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.cpp Tue Apr 14 14:05:04 2009 @@ -251,6 +251,95 @@ } //////////////////////////////////////////////////////////////////////////////// +void DataOutputStreamTest::testWriteUTFStringLength() { + + // String of length 65536 of Null Characters. + // Expect: UTFDataFormatException. + std::string testStr( 65536, char('a') ); + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw a UTFDataFormatException", + os->writeUTF( testStr ), + UTFDataFormatException ); + + baos->reset(); + // String of length 65535 of non Null Characters since Null encodes as UTF-8. + // Expect: Success. + testStr.resize( 65535 ); + CPPUNIT_ASSERT_NO_THROW_MESSAGE( + "String of 65535 Non-Null chars should not throw.", + os->writeUTF( testStr ) ); + + baos->reset(); + // Set one of the 65535 bytes to a value that will result in a 2 byte UTF8 encoded sequence. + // This will cause the string of length 65535 to have a utf length of 65536. + // Expect: UTFDataFormatException. + testStr[0] = char( 255 ); + CPPUNIT_ASSERT_THROW_MESSAGE( + "Should throw an UTFDataFormatException", + os->writeUTF( testStr ), + UTFDataFormatException ); + + // Test that a zero length string write the zero size marker. + ByteArrayInputStream byteIn; + ByteArrayOutputStream byteOut; + DataInputStream dataIn( &byteIn ); + DataOutputStream dataOut( &byteOut ); + dataOut.writeUTF( "" ); + CPPUNIT_ASSERT( dataOut.size() == 2 ); + byteIn.setByteArray( byteOut.toByteArray(), byteOut.size() ); + CPPUNIT_ASSERT( dataIn.readUnsignedShort() == 0 ); +} + +//////////////////////////////////////////////////////////////////////////////// +void DataOutputStreamTest::testHelper( unsigned char* input, int inputLength, + unsigned char* expect, int expectLength ) { + + std::string testStr( (char*)input, inputLength ); + os->writeUTF( testStr ); + + const unsigned char* result = baos->toByteArray(); + + CPPUNIT_ASSERT( result[0] == 0x00 ); + CPPUNIT_ASSERT( result[1] == (unsigned char)( expectLength ) ); + + for( std::size_t i = 2; i < baos->size(); ++i ) { + CPPUNIT_ASSERT( result[i] == expect[i-2] ); + } + + baos->reset(); +} + +//////////////////////////////////////////////////////////////////////////////// +void DataOutputStreamTest::testWriteUTFEncoding() { + + // Test data with 1-byte UTF8 encoding. + { + unsigned char input[] = {0x00, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64}; + unsigned char expect[] = {0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64}; + + testHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); + } + + // Test data with 2-byte UT8 encoding. + { + unsigned char input[] = {0x00, 0xC2, 0xA9, 0xC3, 0xA6 }; + unsigned char expect[] = {0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 }; + testHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); + } + + // Test data with 1-byte and 2-byte encoding with embedded NULL's. + { + unsigned char input[] = {0x00, 0x04, 0xC2, 0xA9, 0xC3, 0x00, 0xA6 }; + unsigned char expect[] = {0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 }; + + testHelper( input, sizeof(input)/sizeof(unsigned char), + expect, sizeof(expect)/sizeof(unsigned char) ); + } +} + +//////////////////////////////////////////////////////////////////////////////// void DataOutputStreamTest::test(){ unsigned char byteVal = (unsigned char)'T'; Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.h URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.h?rev=764780&r1=764779&r2=764780&view=diff ============================================================================== --- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.h (original) +++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.h Tue Apr 14 14:05:04 2009 @@ -26,6 +26,7 @@ #include #include #include +#include namespace decaf{ namespace io{ @@ -49,13 +50,15 @@ CPPUNIT_TEST( testWriteLong ); CPPUNIT_TEST( testWriteShort ); CPPUNIT_TEST( testWriteUTF ); + CPPUNIT_TEST( testWriteUTFStringLength ); + CPPUNIT_TEST( testWriteUTFEncoding ); CPPUNIT_TEST_SUITE_END(); - ByteArrayOutputStream* baos; - ByteArrayInputStream* bais; + std::auto_ptr baos; + std::auto_ptr bais; - DataOutputStream* os; - DataInputStream* is; + std::auto_ptr os; + std::auto_ptr is; std::string testData; @@ -64,17 +67,15 @@ virtual ~DataOutputStreamTest(){} virtual void setUp(){ testData = "Test_All_Tests\nTest_decaf_io_BufferedInputStream\nTest_BufferedOutputStream\nTest_decaf_io_ByteArrayInputStream\nTest_decaf_io_ByteArrayOutputStream\nTest_decaf_io_DataInputStream\nTest_decaf_io_File\nTest_decaf_io_FileDescriptor\nTest_decaf_io_FileInputStream\nTest_decaf_io_FileNotFoundException\nTest_decaf_io_FileOutputStream\nTest_decaf_io_FilterInputStream\nTest_decaf_io_FilterOutputStream\nTest_decaf_io_InputStream\nTest_decaf_io_IOException\nTest_decaf_io_OutputStream\nTest_decaf_io_PrintStream\nTest_decaf_io_RandomAccessFile\nTest_decaf_io_SyncFailedException\nTest_decaf_lang_AbstractMethodError\nTest_decaf_lang_ArithmeticException\nTest_decaf_lang_ArrayIndexOutOfBoundsException\nTest_decaf_lang_ArrayStoreException\nTest_decaf_lang_Boolean\nTest_decaf_lang_Byte\nTest_decaf_lang_Character\nTest_decaf_lang_Class\nTest_decaf_lang_ClassCastException\nTest_decaf_lang_ClassCircularityError\nTest_decaf_lang_ClassFormatError\nTest_decaf_lang_ClassLoad er\nTest_decaf_lang_ClassNotFoundException\nTest_decaf_lang_CloneNotSupportedException\nTest_decaf_lang_Double\nTest_decaf_lang_Error\nTest_decaf_lang_Exception\nTest_decaf_lang_ExceptionInInitializerError\nTest_decaf_lang_Float\nTest_decaf_lang_IllegalAccessError\nTest_decaf_lang_IllegalAccessException\nTest_decaf_lang_IllegalArgumentException\nTest_decaf_lang_IllegalMonitorStateException\nTest_decaf_lang_IllegalThreadStateException\nTest_decaf_lang_IncompatibleClassChangeError\nTest_decaf_lang_IndexOutOfBoundsException\nTest_decaf_lang_InstantiationError\nTest_decaf_lang_InstantiationException\nTest_decaf_lang_Integer\nTest_decaf_lang_InternalError\nTest_decaf_lang_InterruptedException\nTest_decaf_lang_LinkageError\nTest_decaf_lang_Long\nTest_decaf_lang_Math\nTest_decaf_lang_NegativeArraySizeException\nTest_decaf_lang_NoClassDefFoundError\nTest_decaf_lang_NoSuchFieldError\nTest_decaf_lang_NoSuchMethodError\nTest_decaf_lang_NullPointerException\nTest_decaf_lang_Number\nTest _decaf_lang_NumberFormatException\nTest_decaf_lang_Object\nTest_decaf_lang_OutOfMemoryError\nTest_decaf_lang_RuntimeException\nTest_decaf_lang_SecurityManager\nTest_decaf_lang_Short\nTest_decaf_lang_StackOverflowError\nTest_decaf_lang_String\nTest_decaf_lang_StringBuffer\nTest_decaf_lang_StringIndexOutOfBoundsException\nTest_decaf_lang_System\nTest_decaf_lang_Thread\nTest_decaf_lang_ThreadDeath\nTest_decaf_lang_ThreadGroup\nTest_decaf_lang_Throwable\nTest_decaf_lang_UnknownError\nTest_decaf_lang_UnsatisfiedLinkError\nTest_decaf_lang_VerifyError\nTest_decaf_lang_VirtualMachineError\nTest_decaf_lang_vm_Image\nTest_decaf_lang_vm_MemorySegment\nTest_decaf_lang_vm_ROMStoreException\nTest_decaf_lang_vm_VM\nTest_decaf_lang_Void\nTest_decaf_net_BindException\nTest_decaf_net_ConnectException\nTest_decaf_net_DatagramPacket\nTest_decaf_net_DatagramSocket\nTest_decaf_net_DatagramSocketImpl\nTest_decaf_net_InetAddress\nTest_decaf_net_NoRouteToHostException\nTest_decaf_net_PlainDatagramSo cketImpl\nTest_decaf_net_PlainSocketImpl\nTest_decaf_net_Socket\nTest_decaf_net_SocketException\nTest_decaf_net_SocketImpl\nTest_decaf_net_SocketInputStream\nTest_decaf_net_SocketOutputStream\nTest_decaf_net_UnknownHostException\nTest_decaf_util_ArrayEnumerator\nTest_decaf_util_Date\nTest_decaf_util_EventObject\nTest_decaf_util_HashEnumerator\nTest_decaf_util_Hashtable\nTest_decaf_util_Properties\nTest_decaf_util_ResourceBundle\nTest_decaf_util_tm\nTest_decaf_util_Vector\n"; - baos = new ByteArrayOutputStream(); - os = new DataOutputStream( baos ); - is = NULL; - bais = NULL; + this->baos.reset( new ByteArrayOutputStream() ); + this->os.reset( new DataOutputStream( baos.get() ) ); } virtual void tearDown(){ try { - delete os; - delete baos; - delete is; - delete bais; + os.reset( NULL ); + baos.reset( NULL ); + is.reset( NULL ); + bais.reset( NULL ); } catch(...) {} } @@ -94,12 +95,17 @@ void testWriteLong(); void testWriteShort(); void testWriteUTF(); + void testWriteUTFStringLength(); + void testWriteUTFEncoding(); private: + void testHelper( unsigned char* input, int inputLength, + unsigned char* expect, int expectLength ); + void openDataInputStream() { - bais = new ByteArrayInputStream( baos->toByteArray(), baos->size() ); - is = new DataInputStream( bais ); + this->bais.reset( new ByteArrayInputStream( baos->toByteArray(), baos->size() ) ); + this->is.reset( new DataInputStream( bais.get() ) ); } };