You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ta...@apache.org on 2009/04/14 16:05:05 UTC
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...
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 <decaf/io/ByteArrayOutputStream.h>
#include <decaf/io/DataOutputStream.h>
+#include <activemq/wireformat/openwire/utils/OpenwireStringSupport.h>
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<unsigned char>& 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 <decaf/io/DataOutputStream.h>
#include <activemq/wireformat/openwire/utils/OpenwireStringSupport.h>
#include <activemq/exceptions/ActiveMQException.h>
+#include <decaf/lang/Short.h>
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<unsigned char> 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<unsigned char> 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<const char*>(&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<unsigned char> 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<unsigned char> 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<unsigned char>& buffer )
- throw ( io::IOException ) {
+int DataInputStream::read( std::vector<unsigned char>& 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<unsigned char> 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<unsigned char> 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 <decaf/io/FilterInputStream.h>
#include <decaf/io/IOException.h>
#include <decaf/io/EOFException.h>
+#include <decaf/io/UTFDataFormatException.h>
#include <decaf/lang/exceptions/NullPointerException.h>
#include <decaf/lang/exceptions/IndexOutOfBoundsException.h>
@@ -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 <decaf/io/DataOutputStream.h>
+#include <decaf/io/UTFDataFormatException.h>
#include <decaf/util/Config.h>
#include <string.h>
#include <stdio.h>
@@ -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<unsigned char> 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 <decaf/io/FilterOutputStream.h>
+#include <decaf/io/IOException.h>
+#include <decaf/io/UTFDataFormatException.h>
+#include <string>
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 <decaf/io/IOException.h>
+
+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 <decaf/io/ByteArrayOutputStream.h>
#include <decaf/io/DataInputStream.h>
#include <decaf/io/DataOutputStream.h>
+#include <decaf/lang/Integer.h>
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 <decaf/io/DataInputStream.h>
#include <decaf/io/DataOutputStream.h>
#include <algorithm>
+#include <memory>
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<ByteArrayOutputStream> baos;
+ std::auto_ptr<ByteArrayInputStream> bais;
- DataOutputStream* os;
- DataInputStream* is;
+ std::auto_ptr<DataOutputStream> os;
+ std::auto_ptr<DataInputStream> 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 <decaf/io/DataInputStream.h>
#include <decaf/io/ByteArrayOutputStream.h>
#include <decaf/io/ByteArrayInputStream.h>
+#include <memory>
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<ByteArrayOutputStream> baos;
+ std::auto_ptr<ByteArrayInputStream> bais;
- DataOutputStream* os;
- DataInputStream* is;
+ std::auto_ptr<DataOutputStream> os;
+ std::auto_ptr<DataInputStream> 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() ) );
}
};