diff --git a/OSC/Source/OSC/OSC.Build.cs b/OSC/Source/OSC/OSC.Build.cs index 0d9a9fe..ca6a212 100644 --- a/OSC/Source/OSC/OSC.Build.cs +++ b/OSC/Source/OSC/OSC.Build.cs @@ -38,8 +38,6 @@ namespace UnrealBuildTool.Rules } ); - bEnableExceptions = true; - if (Target.Type.HasValue && TargetRules.IsEditorType(Target.Type.Value)) { Definitions.Add("OSC_EDITOR_BUILD=1"); diff --git a/OSC/Source/OSC/Private/Common/OscFunctionLibrary.cpp b/OSC/Source/OSC/Private/Common/OscFunctionLibrary.cpp index 8b40634..2b0bccd 100644 --- a/OSC/Source/OSC/Private/Common/OscFunctionLibrary.cpp +++ b/OSC/Source/OSC/Private/Common/OscFunctionLibrary.cpp @@ -167,9 +167,21 @@ void UOscFunctionLibrary::SendOsc(FName Address, const TArray(buffer) == reinterpret_cast(output.Data())); GetMutableDefault()->Send(buffer, output.Size(), TargetIndex); } diff --git a/OSC/Source/OSC/Private/Common/oscpack/osc/OscException.h b/OSC/Source/OSC/Private/Common/oscpack/osc/OscException.h deleted file mode 100644 index e9be222..0000000 --- a/OSC/Source/OSC/Private/Common/oscpack/osc/OscException.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - oscpack -- Open Sound Control (OSC) packet manipulation library - http://www.rossbencina.com/code/oscpack - - Copyright (c) 2004-2013 Ross Bencina - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* - The text above constitutes the entire oscpack license; however, - the oscpack developer(s) also make the following non-binding requests: - - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. It is also - requested that these non-binding requests be included whenever the - above license is reproduced. -*/ -#ifndef INCLUDED_OSCPACK_OSCEXCEPTION_H -#define INCLUDED_OSCPACK_OSCEXCEPTION_H - -#include - -namespace osc{ - -class Exception : public std::exception { - const char *what_; - -public: - Exception() throw() {} - Exception( const Exception& src ) throw() - : std::exception( src ) - , what_( src.what_ ) {} - Exception( const char *w ) throw() - : what_( w ) {} - Exception& operator=( const Exception& src ) throw() - { what_ = src.what_; return *this; } - virtual ~Exception() throw() {} - virtual const char* what() const throw() { return what_; } -}; - -} // namespace osc - -#endif /* INCLUDED_OSCPACK_OSCEXCEPTION_H */ diff --git a/OSC/Source/OSC/Private/Common/oscpack/osc/OscOutboundPacketStream.cpp b/OSC/Source/OSC/Private/Common/oscpack/osc/OscOutboundPacketStream.cpp index 58234ba..7c35ed2 100644 --- a/OSC/Source/OSC/Private/Common/oscpack/osc/OscOutboundPacketStream.cpp +++ b/OSC/Source/OSC/Private/Common/oscpack/osc/OscOutboundPacketStream.cpp @@ -163,6 +163,7 @@ OutboundPacketStream::OutboundPacketStream( char *buffer, std::size_t capacity ) , argumentCurrent_( data_ ) , elementSizePtr_( 0 ) , messageIsInProgress_( false ) + , state_( SUCCESS ) { // sanity check integer types declared in OscTypes.h // you'll need to fix OscTypes.h if any of these asserts fail @@ -236,34 +237,30 @@ bool OutboundPacketStream::ElementSizeSlotRequired() const } -void OutboundPacketStream::CheckForAvailableBundleSpace() +Errors OutboundPacketStream::CheckForAvailableBundleSpace() { std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0) + 16; - - if( required > Capacity() ) - throw OutOfBufferMemoryException(); + return (required > Capacity()) ? OUT_OF_BUFFER_MEMORY_ERROR : SUCCESS; } -void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern ) +Errors OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern ) { // plus 4 for at least four bytes of type tag std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0) + RoundUp4(std::strlen(addressPattern) + 1) + 4; - if( required > Capacity() ) - throw OutOfBufferMemoryException(); + return (required > Capacity()) ? OUT_OF_BUFFER_MEMORY_ERROR : SUCCESS; } -void OutboundPacketStream::CheckForAvailableArgumentSpace( std::size_t argumentLength ) +Errors OutboundPacketStream::CheckForAvailableArgumentSpace( std::size_t argumentLength ) { // plus three for extra type tag, comma and null terminator std::size_t required = (argumentCurrent_ - data_) + argumentLength + RoundUp4( (end_ - typeTagsCurrent_) + 3 ); - if( required > Capacity() ) - throw OutOfBufferMemoryException(); + return (required > Capacity()) ? OUT_OF_BUFFER_MEMORY_ERROR : SUCCESS; } @@ -274,6 +271,7 @@ void OutboundPacketStream::Clear() argumentCurrent_ = data_; elementSizePtr_ = 0; messageIsInProgress_ = false; + state_ = SUCCESS; } @@ -322,18 +320,19 @@ bool OutboundPacketStream::IsBundleInProgress() const OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs ) { - if( IsMessageInProgress() ) - throw MessageInProgressException(); + check( !IsMessageInProgress() ) - CheckForAvailableBundleSpace(); + state_ = CheckForAvailableBundleSpace(); + if(state_ == SUCCESS) + { + messageCursor_ = BeginElement( messageCursor_ ); - messageCursor_ = BeginElement( messageCursor_ ); + std::memcpy( messageCursor_, "#bundle\0", 8 ); + FromUInt64( messageCursor_ + 8, rhs.timeTag ); - std::memcpy( messageCursor_, "#bundle\0", 8 ); - FromUInt64( messageCursor_ + 8, rhs.timeTag ); - - messageCursor_ += 16; - argumentCurrent_ = messageCursor_; + messageCursor_ += 16; + argumentCurrent_ = messageCursor_; + } return *this; } @@ -343,10 +342,8 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator& { (void) rhs; - if( !IsBundleInProgress() ) - throw BundleNotInProgressException(); - if( IsMessageInProgress() ) - throw MessageInProgressException(); + check( IsBundleInProgress() ) + check( !IsMessageInProgress() ) EndElement( messageCursor_ ); @@ -356,29 +353,31 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator& OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs ) { - if( IsMessageInProgress() ) - throw MessageInProgressException(); + check( !IsMessageInProgress() ) - CheckForAvailableMessageSpace( rhs.addressPattern ); + state_ = CheckForAvailableMessageSpace( rhs.addressPattern ); - messageCursor_ = BeginElement( messageCursor_ ); + if(state_ == SUCCESS) + { + messageCursor_ = BeginElement( messageCursor_ ); - std::strcpy( messageCursor_, rhs.addressPattern ); - std::size_t rhsLength = std::strlen(rhs.addressPattern); - messageCursor_ += rhsLength + 1; + std::strcpy( messageCursor_, rhs.addressPattern ); + std::size_t rhsLength = std::strlen(rhs.addressPattern); + messageCursor_ += rhsLength + 1; - // zero pad to 4-byte boundary - std::size_t i = rhsLength + 1; - while( i & 0x3 ){ - *messageCursor_++ = '\0'; - ++i; + // zero pad to 4-byte boundary + std::size_t i = rhsLength + 1; + while( i & 0x3 ){ + *messageCursor_++ = '\0'; + ++i; + } + + argumentCurrent_ = messageCursor_; + typeTagsCurrent_ = end_; + + messageIsInProgress_ = true; } - argumentCurrent_ = messageCursor_; - typeTagsCurrent_ = end_; - - messageIsInProgress_ = true; - return *this; } @@ -387,8 +386,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& { (void) rhs; - if( !IsMessageInProgress() ) - throw MessageNotInProgressException(); + check( IsMessageInProgress() ) std::size_t typeTagsCount = end_ - typeTagsCurrent_; @@ -438,9 +436,11 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs ) { - CheckForAvailableArgumentSpace(0); - - *(--typeTagsCurrent_) = (char)((rhs) ? TRUE_TYPE_TAG : FALSE_TYPE_TAG); + state_ = CheckForAvailableArgumentSpace(0); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = (char)((rhs) ? TRUE_TYPE_TAG : FALSE_TYPE_TAG); + } return *this; } @@ -449,9 +449,11 @@ OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs ) { (void) rhs; - CheckForAvailableArgumentSpace(0); - - *(--typeTagsCurrent_) = NIL_TYPE_TAG; + state_ = CheckForAvailableArgumentSpace(0); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = NIL_TYPE_TAG; + } return *this; } @@ -460,9 +462,11 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs ) { (void) rhs; - CheckForAvailableArgumentSpace(0); - - *(--typeTagsCurrent_) = INFINITUM_TYPE_TAG; + state_ = CheckForAvailableArgumentSpace(0); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = INFINITUM_TYPE_TAG; + } return *this; } @@ -470,11 +474,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs ) { - CheckForAvailableArgumentSpace(4); - - *(--typeTagsCurrent_) = INT32_TYPE_TAG; - FromInt32( argumentCurrent_, rhs ); - argumentCurrent_ += 4; + state_ = CheckForAvailableArgumentSpace(4); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = INT32_TYPE_TAG; + FromInt32( argumentCurrent_, rhs ); + argumentCurrent_ += 4; + } return *this; } @@ -482,27 +488,29 @@ OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( float rhs ) { - CheckForAvailableArgumentSpace(4); - - *(--typeTagsCurrent_) = FLOAT_TYPE_TAG; + state_ = CheckForAvailableArgumentSpace(4); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = FLOAT_TYPE_TAG; #ifdef OSC_HOST_LITTLE_ENDIAN - union{ - float f; - char c[4]; - } u; + union{ + float f; + char c[4]; + } u; - u.f = rhs; + u.f = rhs; - argumentCurrent_[3] = u.c[0]; - argumentCurrent_[2] = u.c[1]; - argumentCurrent_[1] = u.c[2]; - argumentCurrent_[0] = u.c[3]; + argumentCurrent_[3] = u.c[0]; + argumentCurrent_[2] = u.c[1]; + argumentCurrent_[1] = u.c[2]; + argumentCurrent_[0] = u.c[3]; #else - *reinterpret_cast(argumentCurrent_) = rhs; + *reinterpret_cast(argumentCurrent_) = rhs; #endif - argumentCurrent_ += 4; + argumentCurrent_ += 4; + } return *this; } @@ -510,11 +518,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( float rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( char rhs ) { - CheckForAvailableArgumentSpace(4); - - *(--typeTagsCurrent_) = CHAR_TYPE_TAG; - FromInt32( argumentCurrent_, rhs ); - argumentCurrent_ += 4; + state_ = CheckForAvailableArgumentSpace(4); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = CHAR_TYPE_TAG; + FromInt32( argumentCurrent_, rhs ); + argumentCurrent_ += 4; + } return *this; } @@ -522,11 +532,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( char rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs ) { - CheckForAvailableArgumentSpace(4); - - *(--typeTagsCurrent_) = RGBA_COLOR_TYPE_TAG; - FromUInt32( argumentCurrent_, rhs ); - argumentCurrent_ += 4; + state_ = CheckForAvailableArgumentSpace(4); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = RGBA_COLOR_TYPE_TAG; + FromUInt32( argumentCurrent_, rhs ); + argumentCurrent_ += 4; + } return *this; } @@ -534,11 +546,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs ) { - CheckForAvailableArgumentSpace(4); - - *(--typeTagsCurrent_) = MIDI_MESSAGE_TYPE_TAG; - FromUInt32( argumentCurrent_, rhs ); - argumentCurrent_ += 4; + state_ = CheckForAvailableArgumentSpace(4); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = MIDI_MESSAGE_TYPE_TAG; + FromUInt32( argumentCurrent_, rhs ); + argumentCurrent_ += 4; + } return *this; } @@ -546,11 +560,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs ) { - CheckForAvailableArgumentSpace(8); - - *(--typeTagsCurrent_) = INT64_TYPE_TAG; - FromInt64( argumentCurrent_, rhs ); - argumentCurrent_ += 8; + state_ = CheckForAvailableArgumentSpace(8); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = INT64_TYPE_TAG; + FromInt64( argumentCurrent_, rhs ); + argumentCurrent_ += 8; + } return *this; } @@ -558,11 +574,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs ) { - CheckForAvailableArgumentSpace(8); - - *(--typeTagsCurrent_) = TIME_TAG_TYPE_TAG; - FromUInt64( argumentCurrent_, rhs ); - argumentCurrent_ += 8; + state_ = CheckForAvailableArgumentSpace(8); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = TIME_TAG_TYPE_TAG; + FromUInt64( argumentCurrent_, rhs ); + argumentCurrent_ += 8; + } return *this; } @@ -570,31 +588,33 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( double rhs ) { - CheckForAvailableArgumentSpace(8); - - *(--typeTagsCurrent_) = DOUBLE_TYPE_TAG; + state_ = CheckForAvailableArgumentSpace(8); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = DOUBLE_TYPE_TAG; #ifdef OSC_HOST_LITTLE_ENDIAN - union{ - double f; - char c[8]; - } u; + union{ + double f; + char c[8]; + } u; - u.f = rhs; + u.f = rhs; - argumentCurrent_[7] = u.c[0]; - argumentCurrent_[6] = u.c[1]; - argumentCurrent_[5] = u.c[2]; - argumentCurrent_[4] = u.c[3]; - argumentCurrent_[3] = u.c[4]; - argumentCurrent_[2] = u.c[5]; - argumentCurrent_[1] = u.c[6]; - argumentCurrent_[0] = u.c[7]; + argumentCurrent_[7] = u.c[0]; + argumentCurrent_[6] = u.c[1]; + argumentCurrent_[5] = u.c[2]; + argumentCurrent_[4] = u.c[3]; + argumentCurrent_[3] = u.c[4]; + argumentCurrent_[2] = u.c[5]; + argumentCurrent_[1] = u.c[6]; + argumentCurrent_[0] = u.c[7]; #else - *reinterpret_cast(argumentCurrent_) = rhs; + *reinterpret_cast(argumentCurrent_) = rhs; #endif - argumentCurrent_ += 8; + argumentCurrent_ += 8; + } return *this; } @@ -602,18 +622,20 @@ OutboundPacketStream& OutboundPacketStream::operator<<( double rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs ) { - CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) ); + state_ = CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) ); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = STRING_TYPE_TAG; + std::strcpy( argumentCurrent_, rhs ); + std::size_t rhsLength = std::strlen(rhs); + argumentCurrent_ += rhsLength + 1; - *(--typeTagsCurrent_) = STRING_TYPE_TAG; - std::strcpy( argumentCurrent_, rhs ); - std::size_t rhsLength = std::strlen(rhs); - argumentCurrent_ += rhsLength + 1; - - // zero pad to 4-byte boundary - std::size_t i = rhsLength + 1; - while( i & 0x3 ){ - *argumentCurrent_++ = '\0'; - ++i; + // zero pad to 4-byte boundary + std::size_t i = rhsLength + 1; + while( i & 0x3 ){ + *argumentCurrent_++ = '\0'; + ++i; + } } return *this; @@ -622,18 +644,20 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs ) { - CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) ); + state_ = CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) ); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG; + std::strcpy( argumentCurrent_, rhs ); + std::size_t rhsLength = std::strlen(rhs); + argumentCurrent_ += rhsLength + 1; - *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG; - std::strcpy( argumentCurrent_, rhs ); - std::size_t rhsLength = std::strlen(rhs); - argumentCurrent_ += rhsLength + 1; - - // zero pad to 4-byte boundary - std::size_t i = rhsLength + 1; - while( i & 0x3 ){ - *argumentCurrent_++ = '\0'; - ++i; + // zero pad to 4-byte boundary + std::size_t i = rhsLength + 1; + while( i & 0x3 ){ + *argumentCurrent_++ = '\0'; + ++i; + } } return *this; @@ -642,20 +666,22 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs ) { - CheckForAvailableArgumentSpace( 4 + RoundUp4(rhs.size) ); - - *(--typeTagsCurrent_) = BLOB_TYPE_TAG; - FromUInt32( argumentCurrent_, rhs.size ); - argumentCurrent_ += 4; + state_ = CheckForAvailableArgumentSpace( 4 + RoundUp4(rhs.size) ); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = BLOB_TYPE_TAG; + FromUInt32( argumentCurrent_, rhs.size ); + argumentCurrent_ += 4; - std::memcpy( argumentCurrent_, rhs.data, rhs.size ); - argumentCurrent_ += rhs.size; + std::memcpy( argumentCurrent_, rhs.data, rhs.size ); + argumentCurrent_ += rhs.size; - // zero pad to 4-byte boundary - unsigned long i = rhs.size; - while( i & 0x3 ){ - *argumentCurrent_++ = '\0'; - ++i; + // zero pad to 4-byte boundary + unsigned long i = rhs.size; + while( i & 0x3 ){ + *argumentCurrent_++ = '\0'; + ++i; + } } return *this; @@ -664,9 +690,11 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayInitiator& rhs ) { (void) rhs; - CheckForAvailableArgumentSpace(0); - - *(--typeTagsCurrent_) = ARRAY_BEGIN_TYPE_TAG; + state_ = CheckForAvailableArgumentSpace(0); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = ARRAY_BEGIN_TYPE_TAG; + } return *this; } @@ -674,9 +702,11 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayInitiator& rh OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayTerminator& rhs ) { (void) rhs; - CheckForAvailableArgumentSpace(0); - - *(--typeTagsCurrent_) = ARRAY_END_TYPE_TAG; + state_ = CheckForAvailableArgumentSpace(0); + if(state_ == SUCCESS) + { + *(--typeTagsCurrent_) = ARRAY_END_TYPE_TAG; + } return *this; } diff --git a/OSC/Source/OSC/Private/Common/oscpack/osc/OscOutboundPacketStream.h b/OSC/Source/OSC/Private/Common/oscpack/osc/OscOutboundPacketStream.h index cff16f9..26eb58d 100644 --- a/OSC/Source/OSC/Private/Common/oscpack/osc/OscOutboundPacketStream.h +++ b/OSC/Source/OSC/Private/Common/oscpack/osc/OscOutboundPacketStream.h @@ -40,44 +40,18 @@ #include // size_t #include "OscTypes.h" -#include "OscException.h" namespace osc{ -class OutOfBufferMemoryException : public Exception{ -public: - OutOfBufferMemoryException( const char *w="out of buffer memory" ) - : Exception( w ) {} -}; - -class BundleNotInProgressException : public Exception{ -public: - BundleNotInProgressException( - const char *w="call to EndBundle when bundle is not in progress" ) - : Exception( w ) {} -}; - -class MessageInProgressException : public Exception{ -public: - MessageInProgressException( - const char *w="opening or closing bundle or message while message is in progress" ) - : Exception( w ) {} -}; - -class MessageNotInProgressException : public Exception{ -public: - MessageNotInProgressException( - const char *w="call to EndMessage when message is not in progress" ) - : Exception( w ) {} -}; - class OutboundPacketStream{ public: OutboundPacketStream( char *buffer, std::size_t capacity ); ~OutboundPacketStream(); + Errors State() const { return state_; } + void Clear(); std::size_t Capacity() const; @@ -130,9 +104,9 @@ private: void EndElement( char *endPtr ); bool ElementSizeSlotRequired() const; - void CheckForAvailableBundleSpace(); - void CheckForAvailableMessageSpace( const char *addressPattern ); - void CheckForAvailableArgumentSpace( std::size_t argumentLength ); + Errors CheckForAvailableBundleSpace(); + Errors CheckForAvailableMessageSpace( const char *addressPattern ); + Errors CheckForAvailableArgumentSpace( std::size_t argumentLength ); char *data_; char *end_; @@ -147,6 +121,8 @@ private: uint32 *elementSizePtr_; bool messageIsInProgress_; + + Errors state_; }; } // namespace osc diff --git a/OSC/Source/OSC/Private/Common/oscpack/osc/OscReceivedElements.cpp b/OSC/Source/OSC/Private/Common/oscpack/osc/OscReceivedElements.cpp index 2af395a..c9d895b 100644 --- a/OSC/Source/OSC/Private/Common/oscpack/osc/OscReceivedElements.cpp +++ b/OSC/Source/OSC/Private/Common/oscpack/osc/OscReceivedElements.cpp @@ -202,38 +202,44 @@ osc_bundle_element_size_t ReceivedBundleElement::Size() const //------------------------------------------------------------------------------ -bool ReceivedMessageArgument::AsBool() const +bool ReceivedMessageArgument::AsBool(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == TRUE_TYPE_TAG ) return true; else if( *typeTagPtr_ == FALSE_TYPE_TAG ) return false; else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; + return false; } -bool ReceivedMessageArgument::AsBoolUnchecked() const +bool ReceivedMessageArgument::AsBoolUnchecked(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == TRUE_TYPE_TAG ) return true; else return false; + return false; } -int32 ReceivedMessageArgument::AsInt32() const +int32 ReceivedMessageArgument::AsInt32(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == INT32_TYPE_TAG ) return AsInt32Unchecked(); else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; + return 0; } @@ -257,14 +263,16 @@ int32 ReceivedMessageArgument::AsInt32Unchecked() const } -float ReceivedMessageArgument::AsFloat() const +float ReceivedMessageArgument::AsFloat(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == FLOAT_TYPE_TAG ) return AsFloatUnchecked(); else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; + return 0.f; } @@ -288,14 +296,16 @@ float ReceivedMessageArgument::AsFloatUnchecked() const } -char ReceivedMessageArgument::AsChar() const +char ReceivedMessageArgument::AsChar(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == CHAR_TYPE_TAG ) return AsCharUnchecked(); else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; + return '\0'; } @@ -305,14 +315,16 @@ char ReceivedMessageArgument::AsCharUnchecked() const } -uint32 ReceivedMessageArgument::AsRgbaColor() const +uint32 ReceivedMessageArgument::AsRgbaColor(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == RGBA_COLOR_TYPE_TAG ) return AsRgbaColorUnchecked(); else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; + return 0u; } @@ -322,14 +334,16 @@ uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const } -uint32 ReceivedMessageArgument::AsMidiMessage() const +uint32 ReceivedMessageArgument::AsMidiMessage(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG ) return AsMidiMessageUnchecked(); else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; + return 0u; } @@ -339,14 +353,16 @@ uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const } -int64 ReceivedMessageArgument::AsInt64() const +int64 ReceivedMessageArgument::AsInt64(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == INT64_TYPE_TAG ) return AsInt64Unchecked(); else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; + return 0LL; } @@ -356,14 +372,16 @@ int64 ReceivedMessageArgument::AsInt64Unchecked() const } -uint64 ReceivedMessageArgument::AsTimeTag() const +uint64 ReceivedMessageArgument::AsTimeTag(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == TIME_TAG_TYPE_TAG ) return AsTimeTagUnchecked(); else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; + return 0ULL; } @@ -373,14 +391,16 @@ uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const } -double ReceivedMessageArgument::AsDouble() const +double ReceivedMessageArgument::AsDouble(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == DOUBLE_TYPE_TAG ) return AsDoubleUnchecked(); else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; + return 0.; } @@ -408,55 +428,69 @@ double ReceivedMessageArgument::AsDoubleUnchecked() const } -const char* ReceivedMessageArgument::AsString() const +const char* ReceivedMessageArgument::AsString(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == STRING_TYPE_TAG ) return argumentPtr_; else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; + return ""; } -const char* ReceivedMessageArgument::AsSymbol() const +const char* ReceivedMessageArgument::AsSymbol(Errors & state) const { + state = SUCCESS; if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == SYMBOL_TYPE_TAG ) return argumentPtr_; else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; + return ""; } -void ReceivedMessageArgument::AsBlob( const void*& data, osc_bundle_element_size_t& size ) const +void ReceivedMessageArgument::AsBlob( const void*& data, osc_bundle_element_size_t& size, Errors & state ) const { if( !typeTagPtr_ ) - throw MissingArgumentException(); + state = MISSING_ARGUMENT_ERROR; else if( *typeTagPtr_ == BLOB_TYPE_TAG ) - AsBlobUnchecked( data, size ); + AsBlobUnchecked( data, size, state ); else - throw WrongArgumentTypeException(); + state = WRONG_ARGUMENT_TYPE_ERROR; } -void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const +void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size, Errors & state ) const { // read blob size as an unsigned int then validate osc_bundle_element_size_t sizeResult = (osc_bundle_element_size_t)ToUInt32( argumentPtr_ ); if( !IsValidElementSizeValue(sizeResult) ) - throw MalformedMessageException("invalid blob size"); - - size = sizeResult; - data = (void*)(argumentPtr_+ osc::OSC_SIZEOF_INT32); + { + state = MALFORMED_MESSAGE_INVALID_BLOB_SIZE_ERROR; + } + else + { + state = SUCCESS; + size = sizeResult; + data = (void*)(argumentPtr_+ osc::OSC_SIZEOF_INT32); + } } -std::size_t ReceivedMessageArgument::ComputeArrayItemCount() const +std::size_t ReceivedMessageArgument::ComputeArrayItemCount(Errors & state) const { // it is only valid to call ComputeArrayItemCount when the argument is the array start marker if( !IsArrayBegin() ) - throw WrongArgumentTypeException(); + { + state = WRONG_ARGUMENT_TYPE_ERROR; + return 0; + } + + state = SUCCESS; std::size_t result = 0; unsigned int level = 0; @@ -561,6 +595,7 @@ void ReceivedMessageArgumentIterator::Advance() ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet ) : addressPattern_( packet.Contents() ) + , state_( SUCCESS ) { Init( packet.Contents(), packet.Size() ); } @@ -568,6 +603,7 @@ ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet ) ReceivedMessage::ReceivedMessage( const ReceivedBundleElement& bundleElement ) : addressPattern_( bundleElement.Contents() ) + , state_( SUCCESS ) { Init( bundleElement.Contents(), bundleElement.Size() ); } @@ -588,20 +624,30 @@ uint32 ReceivedMessage::AddressPatternAsUInt32() const void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size ) { if( !IsValidElementSizeValue(size) ) - throw MalformedMessageException( "invalid message size" ); + { + state_ = MALFORMED_MESSAGE_INVALID_SIZE_ERROR; + return; + } if( size == 0 ) - throw MalformedMessageException( "zero length messages not permitted" ); + { + state_ = MALFORMED_MESSAGE_ZERO_SIZE_ERROR; + return; + } if( !IsMultipleOf4(size) ) - throw MalformedMessageException( "message size must be multiple of four" ); + { + state_ = MALFORMED_MESSAGE_NOT_MULTIPLE_OF_4_ERROR; + return; + } const char *end = message + size; typeTagsBegin_ = FindStr4End( addressPattern_, end ); if( typeTagsBegin_ == 0 ){ // address pattern was not terminated before end - throw MalformedMessageException( "unterminated address pattern" ); + state_ = MALFORMED_MESSAGE_UNTERMINATED_ADDRESS_PATTERN_ERROR; + return; } if( typeTagsBegin_ == end ){ @@ -612,7 +658,10 @@ void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size }else{ if( *typeTagsBegin_ != ',' ) - throw MalformedMessageException( "type tags not present" ); + { + state_ = MALFORMED_MESSAGE_NO_TYPE_TAGS_ERROR; + return; + } if( *(typeTagsBegin_ + 1) == '\0' ){ // zero length type tags @@ -624,8 +673,10 @@ void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size // check that all arguments are present and well formed arguments_ = FindStr4End( typeTagsBegin_, end ); - if( arguments_ == 0 ){ - throw MalformedMessageException( "type tags were not terminated before end of message" ); + if( arguments_ == 0 ) + { + state_ = MALFORMED_MESSAGE_UNTERMINATED_TYPE_TAGS_ERROR; + return; } ++typeTagsBegin_; // advance past initial ',' @@ -663,10 +714,16 @@ void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size case MIDI_MESSAGE_TYPE_TAG: if( argument == end ) - throw MalformedMessageException( "arguments exceed message size" ); + { + state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR; + return; + } argument += 4; if( argument > end ) - throw MalformedMessageException( "arguments exceed message size" ); + { + state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR; + return; + } break; case INT64_TYPE_TAG: @@ -674,44 +731,66 @@ void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size case DOUBLE_TYPE_TAG: if( argument == end ) - throw MalformedMessageException( "arguments exceed message size" ); + { + state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR; + return; + } argument += 8; if( argument > end ) - throw MalformedMessageException( "arguments exceed message size" ); + { + state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR; + return; + } break; case STRING_TYPE_TAG: case SYMBOL_TYPE_TAG: if( argument == end ) - throw MalformedMessageException( "arguments exceed message size" ); + { + state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR; + return; + } argument = FindStr4End( argument, end ); if( argument == 0 ) - throw MalformedMessageException( "unterminated string argument" ); + { + state_ = MALFORMED_MESSAGE_UNTERMINATED_STRING_ERROR; + return; + } break; case BLOB_TYPE_TAG: { if( argument + osc::OSC_SIZEOF_INT32 > end ) - MalformedMessageException( "arguments exceed message size" ); + { + state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR; + return; + } // treat blob size as an unsigned int for the purposes of this calculation uint32 blobSize = ToUInt32( argument ); argument = argument + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize ); if( argument > end ) - MalformedMessageException( "arguments exceed message size" ); + { + state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR; + return; + } } break; default: - throw MalformedMessageException( "unknown type tag" ); + state_ = MALFORMED_MESSAGE_UNKNOWN_TYPE_TAG_ERROR; + return; } }while( *++typeTag != '\0' ); typeTagsEnd_ = typeTag; if( arrayLevel != 0 ) - throw MalformedMessageException( "array was not terminated before end of message (expected ']' end of array tag)" ); + { + state_ = MALFORMED_MESSAGE_UNTERMINATED_ARRAY_ERROR; + return; + } } // These invariants should be guaranteed by the above code. @@ -728,6 +807,7 @@ void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size ReceivedBundle::ReceivedBundle( const ReceivedPacket& packet ) : elementCount_( 0 ) + , state_( SUCCESS ) { Init( packet.Contents(), packet.Size() ); } @@ -735,6 +815,7 @@ ReceivedBundle::ReceivedBundle( const ReceivedPacket& packet ) ReceivedBundle::ReceivedBundle( const ReceivedBundleElement& bundleElement ) : elementCount_( 0 ) + , state_( SUCCESS ) { Init( bundleElement.Contents(), bundleElement.Size() ); } @@ -744,13 +825,22 @@ void ReceivedBundle::Init( const char *bundle, osc_bundle_element_size_t size ) { if( !IsValidElementSizeValue(size) ) - throw MalformedBundleException( "invalid bundle size" ); + { + state_ = MALFORMED_BUNDLE_INVALID_SIZE_ERROR; + return; + } if( size < 16 ) - throw MalformedBundleException( "packet too short for bundle" ); + { + state_ = MALFORMED_BUNDLE_TOO_SHORT_ERROR; + return; + } if( !IsMultipleOf4(size) ) - throw MalformedBundleException( "bundle size must be multiple of four" ); + { + state_ = MALFORMED_BUNDLE_NOT_MULTIPLE_OF_4_ERROR; + return; + } if( bundle[0] != '#' || bundle[1] != 'b' @@ -760,7 +850,10 @@ void ReceivedBundle::Init( const char *bundle, osc_bundle_element_size_t size ) || bundle[5] != 'l' || bundle[6] != 'e' || bundle[7] != '\0' ) - throw MalformedBundleException( "bad bundle address pattern" ); + { + state_ = MALFORMED_BUNDLE_INVALID_ADDRESS_PATTERN_ERROR; + return; + } end_ = bundle + size; @@ -770,22 +863,33 @@ void ReceivedBundle::Init( const char *bundle, osc_bundle_element_size_t size ) while( p < end_ ){ if( p + osc::OSC_SIZEOF_INT32 > end_ ) - throw MalformedBundleException( "packet too short for elementSize" ); + { + state_ = MALFORMED_BUNDLE_TOO_SHORT_FOR_ELEMENT_SIZE_ERROR; + return; + } // treat element size as an unsigned int for the purposes of this calculation uint32 elementSize = ToUInt32( p ); if( (elementSize & ((uint32)0x03)) != 0 ) - throw MalformedBundleException( "bundle element size must be multiple of four" ); + { + state_ = MALFORMED_BUNDLE_ELEMENT_NOT_MULTIPLE_OF_4_ERROR; + return; + } p += osc::OSC_SIZEOF_INT32 + elementSize; if( p > end_ ) - throw MalformedBundleException( "packet too short for bundle element" ); + { + state_ = MALFORMED_BUNDLE_TOO_SHORT_FOR_ELEMENT_ERROR; + return; + } ++elementCount_; } if( p != end_ ) - throw MalformedBundleException( "bundle contents " ); + { + state_ = MALFORMED_BUNDLE_CONTENT_ERROR; + } } diff --git a/OSC/Source/OSC/Private/Common/oscpack/osc/OscReceivedElements.h b/OSC/Source/OSC/Private/Common/oscpack/osc/OscReceivedElements.h index f8b0c0d..69dd2b4 100644 --- a/OSC/Source/OSC/Private/Common/oscpack/osc/OscReceivedElements.h +++ b/OSC/Source/OSC/Private/Common/oscpack/osc/OscReceivedElements.h @@ -42,49 +42,11 @@ #include // size_t #include "OscTypes.h" -#include "OscException.h" namespace osc{ -class MalformedPacketException : public Exception{ -public: - MalformedPacketException( const char *w="malformed packet" ) - : Exception( w ) {} -}; - -class MalformedMessageException : public Exception{ -public: - MalformedMessageException( const char *w="malformed message" ) - : Exception( w ) {} -}; - -class MalformedBundleException : public Exception{ -public: - MalformedBundleException( const char *w="malformed bundle" ) - : Exception( w ) {} -}; - -class WrongArgumentTypeException : public Exception{ -public: - WrongArgumentTypeException( const char *w="wrong argument type" ) - : Exception( w ) {} -}; - -class MissingArgumentException : public Exception{ -public: - MissingArgumentException( const char *w="missing argument" ) - : Exception( w ) {} -}; - -class ExcessArgumentException : public Exception{ -public: - ExcessArgumentException( const char *w="too many arguments" ) - : Exception( w ) {} -}; - - class ReceivedPacket{ public: // Although the OSC spec is not entirely clear on this, we only support @@ -94,16 +56,16 @@ public: ReceivedPacket( const char *contents, osc_bundle_element_size_t size ) : contents_( contents ) - , size_( ValidateSize(size) ) {} + , size_( ValidateSize(size, &state_) ) {} ReceivedPacket( const char *contents, std::size_t size ) : contents_( contents ) - , size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {} + , size_( ValidateSize( (osc_bundle_element_size_t)size, &state_ ) ) {} #if !(defined(__x86_64__) || defined(_M_X64)) ReceivedPacket( const char *contents, int size ) : contents_( contents ) - , size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {} + , size_( ValidateSize( (osc_bundle_element_size_t)size, &state_ ) ) {} #endif bool IsMessage() const { return !IsBundle(); } @@ -111,12 +73,14 @@ public: osc_bundle_element_size_t Size() const { return size_; } const char *Contents() const { return contents_; } + Errors State() const { return state_; } private: const char *contents_; osc_bundle_element_size_t size_; + Errors state_; - static osc_bundle_element_size_t ValidateSize( osc_bundle_element_size_t size ) + static osc_bundle_element_size_t ValidateSize( osc_bundle_element_size_t size, Errors * state ) { // sanity check integer types declared in OscTypes.h // you'll need to fix OscTypes.h if any of these asserts fail @@ -126,14 +90,24 @@ private: assert( sizeof(osc::uint64) == 8 ); if( !IsValidElementSizeValue(size) ) - throw MalformedPacketException( "invalid packet size" ); + { + *state = MALFORMED_PACKET_INVALID_SIZE_ERROR; + return 0; + } if( size == 0 ) - throw MalformedPacketException( "zero length elements not permitted" ); + { + *state = MALFORMED_PACKET_ZERO_SIZE_ERROR; + return 0; + } if( !IsMultipleOf4(size) ) - throw MalformedPacketException( "element size must be multiple of four" ); + { + *state = MALFORMED_PACKET_NOT_MULTIPLE_OF_4_ERROR; + return 0; + } + *state = SUCCESS; return size; } }; @@ -222,61 +196,61 @@ public: bool IsBool() const { return *typeTagPtr_ == TRUE_TYPE_TAG || *typeTagPtr_ == FALSE_TYPE_TAG; } - bool AsBool() const; - bool AsBoolUnchecked() const; + bool AsBool(Errors & state) const; + bool AsBoolUnchecked(Errors & state) const; bool IsNil() const { return *typeTagPtr_ == NIL_TYPE_TAG; } bool IsInfinitum() const { return *typeTagPtr_ == INFINITUM_TYPE_TAG; } bool IsInt32() const { return *typeTagPtr_ == INT32_TYPE_TAG; } - int32 AsInt32() const; + int32 AsInt32(Errors & state) const; int32 AsInt32Unchecked() const; bool IsFloat() const { return *typeTagPtr_ == FLOAT_TYPE_TAG; } - float AsFloat() const; + float AsFloat(Errors & state) const; float AsFloatUnchecked() const; bool IsChar() const { return *typeTagPtr_ == CHAR_TYPE_TAG; } - char AsChar() const; + char AsChar(Errors & state) const; char AsCharUnchecked() const; bool IsRgbaColor() const { return *typeTagPtr_ == RGBA_COLOR_TYPE_TAG; } - uint32 AsRgbaColor() const; + uint32 AsRgbaColor(Errors & state) const; uint32 AsRgbaColorUnchecked() const; bool IsMidiMessage() const { return *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG; } - uint32 AsMidiMessage() const; + uint32 AsMidiMessage(Errors & state) const; uint32 AsMidiMessageUnchecked() const; bool IsInt64() const { return *typeTagPtr_ == INT64_TYPE_TAG; } - int64 AsInt64() const; + int64 AsInt64(Errors & state) const; int64 AsInt64Unchecked() const; bool IsTimeTag() const { return *typeTagPtr_ == TIME_TAG_TYPE_TAG; } - uint64 AsTimeTag() const; + uint64 AsTimeTag(Errors & state) const; uint64 AsTimeTagUnchecked() const; bool IsDouble() const { return *typeTagPtr_ == DOUBLE_TYPE_TAG; } - double AsDouble() const; + double AsDouble(Errors & state) const; double AsDoubleUnchecked() const; bool IsString() const { return *typeTagPtr_ == STRING_TYPE_TAG; } - const char* AsString() const; + const char* AsString(Errors & state) const; const char* AsStringUnchecked() const { return argumentPtr_; } bool IsSymbol() const { return *typeTagPtr_ == SYMBOL_TYPE_TAG; } - const char* AsSymbol() const; + const char* AsSymbol(Errors & state) const; const char* AsSymbolUnchecked() const { return argumentPtr_; } bool IsBlob() const { return *typeTagPtr_ == BLOB_TYPE_TAG; } - void AsBlob( const void*& data, osc_bundle_element_size_t& size ) const; - void AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const; + void AsBlob( const void*& data, osc_bundle_element_size_t& size, Errors & state ) const; + void AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size, Errors & state ) const; bool IsArrayBegin() const { return *typeTagPtr_ == ARRAY_BEGIN_TYPE_TAG; } bool IsArrayEnd() const { return *typeTagPtr_ == ARRAY_END_TYPE_TAG; } // Calculate the number of top-level items in the array. Nested arrays count as one item. // Only valid at array start. Will throw an exception if IsArrayStart() == false. - std::size_t ComputeArrayItemCount() const; + std::size_t ComputeArrayItemCount(Errors & state) const; private: const char *typeTagPtr_; @@ -338,21 +312,29 @@ class ReceivedMessageArgumentStream{ ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin, const ReceivedMessageArgumentIterator& end ) : p_( begin ) - , end_( end ) {} + , end_( end ) + , state_( SUCCESS ) {} ReceivedMessageArgumentIterator p_, end_; + Errors state_; public: + Errors State() const { return state_; } + // end of stream bool Eos() const { return p_ == end_; } ReceivedMessageArgumentStream& operator>>( bool& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - rhs = (*p_++).AsBool(); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + rhs = (*p_++).AsBool(state_); + } return *this; } @@ -363,99 +345,143 @@ public: ReceivedMessageArgumentStream& operator>>( int32& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - rhs = (*p_++).AsInt32(); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + rhs = (*p_++).AsInt32(state_); + } return *this; } ReceivedMessageArgumentStream& operator>>( float& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - rhs = (*p_++).AsFloat(); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + rhs = (*p_++).AsFloat(state_); + } return *this; } ReceivedMessageArgumentStream& operator>>( char& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - rhs = (*p_++).AsChar(); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + rhs = (*p_++).AsChar(state_); + } return *this; } ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - rhs.value = (*p_++).AsRgbaColor(); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + rhs.value = (*p_++).AsRgbaColor(state_); + } return *this; } ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - rhs.value = (*p_++).AsMidiMessage(); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + rhs.value = (*p_++).AsMidiMessage(state_); + } return *this; } ReceivedMessageArgumentStream& operator>>( int64& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - rhs = (*p_++).AsInt64(); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + rhs = (*p_++).AsInt64(state_); + } return *this; } ReceivedMessageArgumentStream& operator>>( TimeTag& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - rhs.value = (*p_++).AsTimeTag(); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + rhs.value = (*p_++).AsTimeTag(state_); + } return *this; } ReceivedMessageArgumentStream& operator>>( double& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - rhs = (*p_++).AsDouble(); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + rhs = (*p_++).AsDouble(state_); + } return *this; } ReceivedMessageArgumentStream& operator>>( Blob& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - (*p_++).AsBlob( rhs.data, rhs.size ); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + (*p_++).AsBlob( rhs.data, rhs.size, state_ ); + } return *this; } ReceivedMessageArgumentStream& operator>>( const char*& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - rhs = (*p_++).AsString(); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + rhs = (*p_++).AsString(state_); + } return *this; } ReceivedMessageArgumentStream& operator>>( Symbol& rhs ) { if( Eos() ) - throw MissingArgumentException(); - - rhs.value = (*p_++).AsSymbol(); + { + state_ = MISSING_ARGUMENT_ERROR; + } + else + { + rhs.value = (*p_++).AsSymbol(state_); + } return *this; } @@ -463,9 +489,10 @@ public: { (void) rhs; // suppress unused parameter warning - if( !Eos() ) - throw ExcessArgumentException(); - + if( Eos() ) + { + state_ = EXCESS_ARGUMENT_ERROR; + } return *this; } }; @@ -477,6 +504,8 @@ public: explicit ReceivedMessage( const ReceivedPacket& packet ); explicit ReceivedMessage( const ReceivedBundleElement& bundleElement ); + Errors State() const { return state_; } + const char *AddressPattern() const { return addressPattern_; } // Support for non-standard SuperCollider integer address patterns: @@ -510,6 +539,7 @@ private: const char *typeTagsBegin_; const char *typeTagsEnd_; const char *arguments_; + Errors state_; }; @@ -519,6 +549,8 @@ public: explicit ReceivedBundle( const ReceivedPacket& packet ); explicit ReceivedBundle( const ReceivedBundleElement& bundleElement ); + Errors State() const { return state_; } + uint64 TimeTag() const; uint32 ElementCount() const { return elementCount_; } @@ -539,6 +571,7 @@ private: const char *timeTag_; const char *end_; uint32 elementCount_; + Errors state_; }; diff --git a/OSC/Source/OSC/Private/Common/oscpack/osc/OscTypes.cpp b/OSC/Source/OSC/Private/Common/oscpack/osc/OscTypes.cpp index b096315..5115207 100644 --- a/OSC/Source/OSC/Private/Common/oscpack/osc/OscTypes.cpp +++ b/OSC/Source/OSC/Private/Common/oscpack/osc/OscTypes.cpp @@ -52,4 +52,52 @@ InfinitumType Infinitum; ArrayInitiator BeginArray; ArrayTerminator EndArray; +const TCHAR * errorString(Errors value) +{ + static const TCHAR * ERROR_STR[] = { + TEXT("No Error"), + + TEXT("Malformed packet"), + TEXT("Malformed packet: invalid size"), + TEXT("Malformed packet: zero size"), + TEXT("Malformed packet: not multiple of 4"), + + TEXT("Malformed message"), + TEXT("Malformed message: invalid size"), + TEXT("Malformed message: zero size"), + TEXT("Malformed message: not multiple of 4"), + TEXT("Malformed message: invalid blob size"), + TEXT("Malformed message: unterminated address pattern"), + TEXT("Malformed message: unterminated string"), + TEXT("Malformed message: unterminated array"), + TEXT("Malformed message: no type tags"), + TEXT("Malformed message: unterminated type tags"), + TEXT("Malformed message: argument exceed msg size"), + TEXT("Malformed message: unknown type tag"), + + TEXT("Malformed bundle"), + TEXT("Malformed bundle: invalid size"), + TEXT("Malformed bundle: invalid address pattern"), + TEXT("Malformed bundle: too short"), + TEXT("Malformed bundle: too short for element size"), + TEXT("Malformed bundle: too short for element"), + TEXT("Malformed bundle: not multiple of 4"), + TEXT("Malformed bundle: element not multiple of 4"), + TEXT("Malformed bundle: content"), + + TEXT("Wrong argument type"), + TEXT("Missing argument"), + TEXT("Excess argument"), + TEXT("Out of buffer memory"), + }; + + static_assert((sizeof(ERROR_STR) / sizeof(*ERROR_STR) == ERRORS_COUNT), "Error messages mismatch"); + if(value < 0 || value >= ERRORS_COUNT) + { + check(false); + return TEXT("Unknown error code"); + } + return ERROR_STR[value]; +} + } // namespace osc diff --git a/OSC/Source/OSC/Private/Common/oscpack/osc/OscTypes.h b/OSC/Source/OSC/Private/Common/oscpack/osc/OscTypes.h index a21f23b..aabe09f 100644 --- a/OSC/Source/OSC/Private/Common/oscpack/osc/OscTypes.h +++ b/OSC/Source/OSC/Private/Common/oscpack/osc/OscTypes.h @@ -234,6 +234,48 @@ struct ArrayTerminator{ extern ArrayTerminator EndArray; + +enum Errors { + SUCCESS = 0, + + MALFORMED_PACKET_ERROR, + MALFORMED_PACKET_INVALID_SIZE_ERROR, + MALFORMED_PACKET_ZERO_SIZE_ERROR, + MALFORMED_PACKET_NOT_MULTIPLE_OF_4_ERROR, + + MALFORMED_MESSAGE_ERROR, + MALFORMED_MESSAGE_INVALID_SIZE_ERROR, + MALFORMED_MESSAGE_ZERO_SIZE_ERROR, + MALFORMED_MESSAGE_NOT_MULTIPLE_OF_4_ERROR, + MALFORMED_MESSAGE_INVALID_BLOB_SIZE_ERROR, + MALFORMED_MESSAGE_UNTERMINATED_ADDRESS_PATTERN_ERROR, + MALFORMED_MESSAGE_UNTERMINATED_STRING_ERROR, + MALFORMED_MESSAGE_UNTERMINATED_ARRAY_ERROR, + MALFORMED_MESSAGE_NO_TYPE_TAGS_ERROR, + MALFORMED_MESSAGE_UNTERMINATED_TYPE_TAGS_ERROR, + MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR, + MALFORMED_MESSAGE_UNKNOWN_TYPE_TAG_ERROR, + + MALFORMED_BUNDLE_ERROR, + MALFORMED_BUNDLE_INVALID_SIZE_ERROR, + MALFORMED_BUNDLE_INVALID_ADDRESS_PATTERN_ERROR, + MALFORMED_BUNDLE_TOO_SHORT_ERROR, + MALFORMED_BUNDLE_TOO_SHORT_FOR_ELEMENT_SIZE_ERROR, + MALFORMED_BUNDLE_TOO_SHORT_FOR_ELEMENT_ERROR, + MALFORMED_BUNDLE_NOT_MULTIPLE_OF_4_ERROR, + MALFORMED_BUNDLE_ELEMENT_NOT_MULTIPLE_OF_4_ERROR, + MALFORMED_BUNDLE_CONTENT_ERROR, + + WRONG_ARGUMENT_TYPE_ERROR, + MISSING_ARGUMENT_ERROR, + EXCESS_ARGUMENT_ERROR, + OUT_OF_BUFFER_MEMORY_ERROR, + + ERRORS_COUNT, +}; + +const TCHAR * errorString(Errors value); + } // namespace osc diff --git a/OSC/Source/OSC/Private/Receive/OscDispatcher.cpp b/OSC/Source/OSC/Private/Receive/OscDispatcher.cpp index 5381206..7550cb4 100644 --- a/OSC/Source/OSC/Private/Receive/OscDispatcher.cpp +++ b/OSC/Source/OSC/Private/Receive/OscDispatcher.cpp @@ -87,6 +87,11 @@ void UOscDispatcher::UnregisterReceiver(IOscReceiverInterface * receiver) static void SendMessage(TCircularQueue>> & _pendingMessages, const osc::ReceivedMessage & message) { + if(message.State() != osc::SUCCESS) + { + UE_LOG(LogOSC, Warning, TEXT("OSC Received Message Error: %s"), osc::errorString(message.State())); + return; + } const FName address(message.AddressPattern()); TArray data; @@ -114,7 +119,9 @@ static void SendMessage(TCircularQueueIsBool()) { - elem.SetBool(it->AsBoolUnchecked()); + osc::Errors error = osc::SUCCESS; + elem.SetBool(it->AsBoolUnchecked(error)); + check(error == osc::SUCCESS); } else if(it->IsString()) { @@ -135,6 +142,12 @@ static void SendMessage(TCircularQueue>> & _pendingMessages, const osc::ReceivedBundle & bundle) { + if(bundle.State() != osc::SUCCESS) + { + UE_LOG(LogOSC, Warning, TEXT("OSC Received Bundle Error: %s"), osc::errorString(bundle.State())); + return; + } + const auto begin = bundle.ElementsBegin(); const auto end = bundle.ElementsEnd(); for(auto it = begin; it != end; ++it) @@ -153,26 +166,23 @@ static void SendBundle(TCircularQueueGetData(), data->Num()); + if(packet.State() != osc::SUCCESS) { - const osc::ReceivedPacket packet((const char *)data->GetData(), data->Num()); - if(packet.IsBundle()) - { - SendBundle(_pendingMessages, osc::ReceivedBundle(packet)); - } - else - { - SendMessage(_pendingMessages, osc::ReceivedMessage(packet)); - } + UE_LOG(LogOSC, Warning, TEXT("OSC Received Packet Error: %s"), osc::errorString(packet.State())); + return; } - catch(osc::Exception &e) + + if(packet.IsBundle()) { - // Exceptions are disabled by default, so destructors are not called. - // We don't care: there is no acquired resource to release. - const FString wide(e.what()); - UE_LOG(LogOSC, Warning, TEXT("OSC Message Error: %s"), *wide); + SendBundle(_pendingMessages, osc::ReceivedBundle(packet)); } - + else + { + SendMessage(_pendingMessages, osc::ReceivedMessage(packet)); + } + // Set a single callback in the main thread per frame. if(wasEmpty && !_pendingMessages.IsEmpty()) {