replace exceptions with error code (mobile compilation)

This commit is contained in:
monsieurgustav
2015-10-19 20:45:51 +02:00
parent f9595d5bff
commit 200dc3d138
10 changed files with 627 additions and 436 deletions
-2
View File
@@ -38,8 +38,6 @@ namespace UnrealBuildTool.Rules
} }
); );
bEnableExceptions = true;
if (Target.Type.HasValue && TargetRules.IsEditorType(Target.Type.Value)) if (Target.Type.HasValue && TargetRules.IsEditorType(Target.Type.Value))
{ {
Definitions.Add("OSC_EDITOR_BUILD=1"); Definitions.Add("OSC_EDITOR_BUILD=1");
@@ -167,9 +167,21 @@ void UOscFunctionLibrary::SendOsc(FName Address, const TArray<FOscDataElemStruct
{ {
output << elem.AsStringValue().GetPlainANSIString(); output << elem.AsStringValue().GetPlainANSIString();
} }
if(output.State() != osc::SUCCESS)
{
UE_LOG(LogOSC, Error, TEXT("OSC Send Message Error: %s"), osc::errorString(output.State()));
return;
}
} }
output << osc::EndMessage; output << osc::EndMessage;
if(output.State() != osc::SUCCESS)
{
UE_LOG(LogOSC, Error, TEXT("OSC Send Message Error: %s"), osc::errorString(output.State()));
return;
}
check(reinterpret_cast<const void *>(buffer) == reinterpret_cast<const void *>(output.Data())); check(reinterpret_cast<const void *>(buffer) == reinterpret_cast<const void *>(output.Data()));
GetMutableDefault<UOscSettings>()->Send(buffer, output.Size(), TargetIndex); GetMutableDefault<UOscSettings>()->Send(buffer, output.Size(), TargetIndex);
} }
@@ -1,62 +0,0 @@
/*
oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
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 <exception>
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 */
@@ -163,6 +163,7 @@ OutboundPacketStream::OutboundPacketStream( char *buffer, std::size_t capacity )
, argumentCurrent_( data_ ) , argumentCurrent_( data_ )
, elementSizePtr_( 0 ) , elementSizePtr_( 0 )
, messageIsInProgress_( false ) , messageIsInProgress_( false )
, state_( SUCCESS )
{ {
// sanity check integer types declared in OscTypes.h // sanity check integer types declared in OscTypes.h
// you'll need to fix OscTypes.h if any of these asserts fail // 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; std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0) + 16;
return (required > Capacity()) ? OUT_OF_BUFFER_MEMORY_ERROR : SUCCESS;
if( required > Capacity() )
throw OutOfBufferMemoryException();
} }
void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern ) Errors OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern )
{ {
// plus 4 for at least four bytes of type tag // plus 4 for at least four bytes of type tag
std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0) std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0)
+ RoundUp4(std::strlen(addressPattern) + 1) + 4; + RoundUp4(std::strlen(addressPattern) + 1) + 4;
if( required > Capacity() ) return (required > Capacity()) ? OUT_OF_BUFFER_MEMORY_ERROR : SUCCESS;
throw OutOfBufferMemoryException();
} }
void OutboundPacketStream::CheckForAvailableArgumentSpace( std::size_t argumentLength ) Errors OutboundPacketStream::CheckForAvailableArgumentSpace( std::size_t argumentLength )
{ {
// plus three for extra type tag, comma and null terminator // plus three for extra type tag, comma and null terminator
std::size_t required = (argumentCurrent_ - data_) + argumentLength std::size_t required = (argumentCurrent_ - data_) + argumentLength
+ RoundUp4( (end_ - typeTagsCurrent_) + 3 ); + RoundUp4( (end_ - typeTagsCurrent_) + 3 );
if( required > Capacity() ) return (required > Capacity()) ? OUT_OF_BUFFER_MEMORY_ERROR : SUCCESS;
throw OutOfBufferMemoryException();
} }
@@ -274,6 +271,7 @@ void OutboundPacketStream::Clear()
argumentCurrent_ = data_; argumentCurrent_ = data_;
elementSizePtr_ = 0; elementSizePtr_ = 0;
messageIsInProgress_ = false; messageIsInProgress_ = false;
state_ = SUCCESS;
} }
@@ -322,18 +320,19 @@ bool OutboundPacketStream::IsBundleInProgress() const
OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs )
{ {
if( IsMessageInProgress() ) check( !IsMessageInProgress() )
throw MessageInProgressException();
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 ); messageCursor_ += 16;
FromUInt64( messageCursor_ + 8, rhs.timeTag ); argumentCurrent_ = messageCursor_;
}
messageCursor_ += 16;
argumentCurrent_ = messageCursor_;
return *this; return *this;
} }
@@ -343,10 +342,8 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator&
{ {
(void) rhs; (void) rhs;
if( !IsBundleInProgress() ) check( IsBundleInProgress() )
throw BundleNotInProgressException(); check( !IsMessageInProgress() )
if( IsMessageInProgress() )
throw MessageInProgressException();
EndElement( messageCursor_ ); EndElement( messageCursor_ );
@@ -356,29 +353,31 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator&
OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs )
{ {
if( IsMessageInProgress() ) check( !IsMessageInProgress() )
throw MessageInProgressException();
CheckForAvailableMessageSpace( rhs.addressPattern ); state_ = CheckForAvailableMessageSpace( rhs.addressPattern );
messageCursor_ = BeginElement( messageCursor_ ); if(state_ == SUCCESS)
{
messageCursor_ = BeginElement( messageCursor_ );
std::strcpy( messageCursor_, rhs.addressPattern ); std::strcpy( messageCursor_, rhs.addressPattern );
std::size_t rhsLength = std::strlen(rhs.addressPattern); std::size_t rhsLength = std::strlen(rhs.addressPattern);
messageCursor_ += rhsLength + 1; messageCursor_ += rhsLength + 1;
// zero pad to 4-byte boundary // zero pad to 4-byte boundary
std::size_t i = rhsLength + 1; std::size_t i = rhsLength + 1;
while( i & 0x3 ){ while( i & 0x3 ){
*messageCursor_++ = '\0'; *messageCursor_++ = '\0';
++i; ++i;
}
argumentCurrent_ = messageCursor_;
typeTagsCurrent_ = end_;
messageIsInProgress_ = true;
} }
argumentCurrent_ = messageCursor_;
typeTagsCurrent_ = end_;
messageIsInProgress_ = true;
return *this; return *this;
} }
@@ -387,8 +386,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator&
{ {
(void) rhs; (void) rhs;
if( !IsMessageInProgress() ) check( IsMessageInProgress() )
throw MessageNotInProgressException();
std::size_t typeTagsCount = end_ - typeTagsCurrent_; std::size_t typeTagsCount = end_ - typeTagsCurrent_;
@@ -438,9 +436,11 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator&
OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs )
{ {
CheckForAvailableArgumentSpace(0); state_ = CheckForAvailableArgumentSpace(0);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = (char)((rhs) ? TRUE_TYPE_TAG : FALSE_TYPE_TAG); {
*(--typeTagsCurrent_) = (char)((rhs) ? TRUE_TYPE_TAG : FALSE_TYPE_TAG);
}
return *this; return *this;
} }
@@ -449,9 +449,11 @@ OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs )
{ {
(void) rhs; (void) rhs;
CheckForAvailableArgumentSpace(0); state_ = CheckForAvailableArgumentSpace(0);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = NIL_TYPE_TAG; {
*(--typeTagsCurrent_) = NIL_TYPE_TAG;
}
return *this; return *this;
} }
@@ -460,9 +462,11 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs )
{ {
(void) rhs; (void) rhs;
CheckForAvailableArgumentSpace(0); state_ = CheckForAvailableArgumentSpace(0);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = INFINITUM_TYPE_TAG; {
*(--typeTagsCurrent_) = INFINITUM_TYPE_TAG;
}
return *this; return *this;
} }
@@ -470,11 +474,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs
OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs )
{ {
CheckForAvailableArgumentSpace(4); state_ = CheckForAvailableArgumentSpace(4);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = INT32_TYPE_TAG; {
FromInt32( argumentCurrent_, rhs ); *(--typeTagsCurrent_) = INT32_TYPE_TAG;
argumentCurrent_ += 4; FromInt32( argumentCurrent_, rhs );
argumentCurrent_ += 4;
}
return *this; return *this;
} }
@@ -482,27 +488,29 @@ OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( float rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( float rhs )
{ {
CheckForAvailableArgumentSpace(4); state_ = CheckForAvailableArgumentSpace(4);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = FLOAT_TYPE_TAG; {
*(--typeTagsCurrent_) = FLOAT_TYPE_TAG;
#ifdef OSC_HOST_LITTLE_ENDIAN #ifdef OSC_HOST_LITTLE_ENDIAN
union{ union{
float f; float f;
char c[4]; char c[4];
} u; } u;
u.f = rhs; u.f = rhs;
argumentCurrent_[3] = u.c[0]; argumentCurrent_[3] = u.c[0];
argumentCurrent_[2] = u.c[1]; argumentCurrent_[2] = u.c[1];
argumentCurrent_[1] = u.c[2]; argumentCurrent_[1] = u.c[2];
argumentCurrent_[0] = u.c[3]; argumentCurrent_[0] = u.c[3];
#else #else
*reinterpret_cast<float*>(argumentCurrent_) = rhs; *reinterpret_cast<float*>(argumentCurrent_) = rhs;
#endif #endif
argumentCurrent_ += 4; argumentCurrent_ += 4;
}
return *this; return *this;
} }
@@ -510,11 +518,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( float rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( char rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( char rhs )
{ {
CheckForAvailableArgumentSpace(4); state_ = CheckForAvailableArgumentSpace(4);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = CHAR_TYPE_TAG; {
FromInt32( argumentCurrent_, rhs ); *(--typeTagsCurrent_) = CHAR_TYPE_TAG;
argumentCurrent_ += 4; FromInt32( argumentCurrent_, rhs );
argumentCurrent_ += 4;
}
return *this; return *this;
} }
@@ -522,11 +532,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( char rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs )
{ {
CheckForAvailableArgumentSpace(4); state_ = CheckForAvailableArgumentSpace(4);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = RGBA_COLOR_TYPE_TAG; {
FromUInt32( argumentCurrent_, rhs ); *(--typeTagsCurrent_) = RGBA_COLOR_TYPE_TAG;
argumentCurrent_ += 4; FromUInt32( argumentCurrent_, rhs );
argumentCurrent_ += 4;
}
return *this; return *this;
} }
@@ -534,11 +546,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs )
{ {
CheckForAvailableArgumentSpace(4); state_ = CheckForAvailableArgumentSpace(4);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = MIDI_MESSAGE_TYPE_TAG; {
FromUInt32( argumentCurrent_, rhs ); *(--typeTagsCurrent_) = MIDI_MESSAGE_TYPE_TAG;
argumentCurrent_ += 4; FromUInt32( argumentCurrent_, rhs );
argumentCurrent_ += 4;
}
return *this; return *this;
} }
@@ -546,11 +560,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs )
{ {
CheckForAvailableArgumentSpace(8); state_ = CheckForAvailableArgumentSpace(8);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = INT64_TYPE_TAG; {
FromInt64( argumentCurrent_, rhs ); *(--typeTagsCurrent_) = INT64_TYPE_TAG;
argumentCurrent_ += 8; FromInt64( argumentCurrent_, rhs );
argumentCurrent_ += 8;
}
return *this; return *this;
} }
@@ -558,11 +574,13 @@ OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs )
{ {
CheckForAvailableArgumentSpace(8); state_ = CheckForAvailableArgumentSpace(8);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = TIME_TAG_TYPE_TAG; {
FromUInt64( argumentCurrent_, rhs ); *(--typeTagsCurrent_) = TIME_TAG_TYPE_TAG;
argumentCurrent_ += 8; FromUInt64( argumentCurrent_, rhs );
argumentCurrent_ += 8;
}
return *this; return *this;
} }
@@ -570,31 +588,33 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( double rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )
{ {
CheckForAvailableArgumentSpace(8); state_ = CheckForAvailableArgumentSpace(8);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = DOUBLE_TYPE_TAG; {
*(--typeTagsCurrent_) = DOUBLE_TYPE_TAG;
#ifdef OSC_HOST_LITTLE_ENDIAN #ifdef OSC_HOST_LITTLE_ENDIAN
union{ union{
double f; double f;
char c[8]; char c[8];
} u; } u;
u.f = rhs; u.f = rhs;
argumentCurrent_[7] = u.c[0]; argumentCurrent_[7] = u.c[0];
argumentCurrent_[6] = u.c[1]; argumentCurrent_[6] = u.c[1];
argumentCurrent_[5] = u.c[2]; argumentCurrent_[5] = u.c[2];
argumentCurrent_[4] = u.c[3]; argumentCurrent_[4] = u.c[3];
argumentCurrent_[3] = u.c[4]; argumentCurrent_[3] = u.c[4];
argumentCurrent_[2] = u.c[5]; argumentCurrent_[2] = u.c[5];
argumentCurrent_[1] = u.c[6]; argumentCurrent_[1] = u.c[6];
argumentCurrent_[0] = u.c[7]; argumentCurrent_[0] = u.c[7];
#else #else
*reinterpret_cast<double*>(argumentCurrent_) = rhs; *reinterpret_cast<double*>(argumentCurrent_) = rhs;
#endif #endif
argumentCurrent_ += 8; argumentCurrent_ += 8;
}
return *this; return *this;
} }
@@ -602,18 +622,20 @@ OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const char *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; // zero pad to 4-byte boundary
std::strcpy( argumentCurrent_, rhs ); std::size_t i = rhsLength + 1;
std::size_t rhsLength = std::strlen(rhs); while( i & 0x3 ){
argumentCurrent_ += rhsLength + 1; *argumentCurrent_++ = '\0';
++i;
// zero pad to 4-byte boundary }
std::size_t i = rhsLength + 1;
while( i & 0x3 ){
*argumentCurrent_++ = '\0';
++i;
} }
return *this; return *this;
@@ -622,18 +644,20 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& 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; // zero pad to 4-byte boundary
std::strcpy( argumentCurrent_, rhs ); std::size_t i = rhsLength + 1;
std::size_t rhsLength = std::strlen(rhs); while( i & 0x3 ){
argumentCurrent_ += rhsLength + 1; *argumentCurrent_++ = '\0';
++i;
// zero pad to 4-byte boundary }
std::size_t i = rhsLength + 1;
while( i & 0x3 ){
*argumentCurrent_++ = '\0';
++i;
} }
return *this; return *this;
@@ -642,20 +666,22 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )
{ {
CheckForAvailableArgumentSpace( 4 + RoundUp4(rhs.size) ); state_ = CheckForAvailableArgumentSpace( 4 + RoundUp4(rhs.size) );
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = BLOB_TYPE_TAG; {
FromUInt32( argumentCurrent_, rhs.size ); *(--typeTagsCurrent_) = BLOB_TYPE_TAG;
argumentCurrent_ += 4; FromUInt32( argumentCurrent_, rhs.size );
argumentCurrent_ += 4;
std::memcpy( argumentCurrent_, rhs.data, rhs.size ); std::memcpy( argumentCurrent_, rhs.data, rhs.size );
argumentCurrent_ += rhs.size; argumentCurrent_ += rhs.size;
// zero pad to 4-byte boundary // zero pad to 4-byte boundary
unsigned long i = rhs.size; unsigned long i = rhs.size;
while( i & 0x3 ){ while( i & 0x3 ){
*argumentCurrent_++ = '\0'; *argumentCurrent_++ = '\0';
++i; ++i;
}
} }
return *this; return *this;
@@ -664,9 +690,11 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayInitiator& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayInitiator& rhs )
{ {
(void) rhs; (void) rhs;
CheckForAvailableArgumentSpace(0); state_ = CheckForAvailableArgumentSpace(0);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = ARRAY_BEGIN_TYPE_TAG; {
*(--typeTagsCurrent_) = ARRAY_BEGIN_TYPE_TAG;
}
return *this; return *this;
} }
@@ -674,9 +702,11 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayInitiator& rh
OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayTerminator& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayTerminator& rhs )
{ {
(void) rhs; (void) rhs;
CheckForAvailableArgumentSpace(0); state_ = CheckForAvailableArgumentSpace(0);
if(state_ == SUCCESS)
*(--typeTagsCurrent_) = ARRAY_END_TYPE_TAG; {
*(--typeTagsCurrent_) = ARRAY_END_TYPE_TAG;
}
return *this; return *this;
} }
@@ -40,44 +40,18 @@
#include <cstring> // size_t #include <cstring> // size_t
#include "OscTypes.h" #include "OscTypes.h"
#include "OscException.h"
namespace osc{ 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{ class OutboundPacketStream{
public: public:
OutboundPacketStream( char *buffer, std::size_t capacity ); OutboundPacketStream( char *buffer, std::size_t capacity );
~OutboundPacketStream(); ~OutboundPacketStream();
Errors State() const { return state_; }
void Clear(); void Clear();
std::size_t Capacity() const; std::size_t Capacity() const;
@@ -130,9 +104,9 @@ private:
void EndElement( char *endPtr ); void EndElement( char *endPtr );
bool ElementSizeSlotRequired() const; bool ElementSizeSlotRequired() const;
void CheckForAvailableBundleSpace(); Errors CheckForAvailableBundleSpace();
void CheckForAvailableMessageSpace( const char *addressPattern ); Errors CheckForAvailableMessageSpace( const char *addressPattern );
void CheckForAvailableArgumentSpace( std::size_t argumentLength ); Errors CheckForAvailableArgumentSpace( std::size_t argumentLength );
char *data_; char *data_;
char *end_; char *end_;
@@ -147,6 +121,8 @@ private:
uint32 *elementSizePtr_; uint32 *elementSizePtr_;
bool messageIsInProgress_; bool messageIsInProgress_;
Errors state_;
}; };
} // namespace osc } // namespace osc
@@ -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_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == TRUE_TYPE_TAG ) else if( *typeTagPtr_ == TRUE_TYPE_TAG )
return true; return true;
else if( *typeTagPtr_ == FALSE_TYPE_TAG ) else if( *typeTagPtr_ == FALSE_TYPE_TAG )
return false; return false;
else else
throw WrongArgumentTypeException(); state = WRONG_ARGUMENT_TYPE_ERROR;
return false;
} }
bool ReceivedMessageArgument::AsBoolUnchecked() const bool ReceivedMessageArgument::AsBoolUnchecked(Errors & state) const
{ {
state = SUCCESS;
if( !typeTagPtr_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == TRUE_TYPE_TAG ) else if( *typeTagPtr_ == TRUE_TYPE_TAG )
return true; return true;
else else
return false; return false;
return false;
} }
int32 ReceivedMessageArgument::AsInt32() const int32 ReceivedMessageArgument::AsInt32(Errors & state) const
{ {
state = SUCCESS;
if( !typeTagPtr_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == INT32_TYPE_TAG ) else if( *typeTagPtr_ == INT32_TYPE_TAG )
return AsInt32Unchecked(); return AsInt32Unchecked();
else 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_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == FLOAT_TYPE_TAG ) else if( *typeTagPtr_ == FLOAT_TYPE_TAG )
return AsFloatUnchecked(); return AsFloatUnchecked();
else 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_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == CHAR_TYPE_TAG ) else if( *typeTagPtr_ == CHAR_TYPE_TAG )
return AsCharUnchecked(); return AsCharUnchecked();
else 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_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == RGBA_COLOR_TYPE_TAG ) else if( *typeTagPtr_ == RGBA_COLOR_TYPE_TAG )
return AsRgbaColorUnchecked(); return AsRgbaColorUnchecked();
else 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_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG ) else if( *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG )
return AsMidiMessageUnchecked(); return AsMidiMessageUnchecked();
else 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_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == INT64_TYPE_TAG ) else if( *typeTagPtr_ == INT64_TYPE_TAG )
return AsInt64Unchecked(); return AsInt64Unchecked();
else 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_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == TIME_TAG_TYPE_TAG ) else if( *typeTagPtr_ == TIME_TAG_TYPE_TAG )
return AsTimeTagUnchecked(); return AsTimeTagUnchecked();
else 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_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == DOUBLE_TYPE_TAG ) else if( *typeTagPtr_ == DOUBLE_TYPE_TAG )
return AsDoubleUnchecked(); return AsDoubleUnchecked();
else 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_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == STRING_TYPE_TAG ) else if( *typeTagPtr_ == STRING_TYPE_TAG )
return argumentPtr_; return argumentPtr_;
else 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_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == SYMBOL_TYPE_TAG ) else if( *typeTagPtr_ == SYMBOL_TYPE_TAG )
return argumentPtr_; return argumentPtr_;
else 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_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); state = MISSING_ARGUMENT_ERROR;
else if( *typeTagPtr_ == BLOB_TYPE_TAG ) else if( *typeTagPtr_ == BLOB_TYPE_TAG )
AsBlobUnchecked( data, size ); AsBlobUnchecked( data, size, state );
else 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 // read blob size as an unsigned int then validate
osc_bundle_element_size_t sizeResult = (osc_bundle_element_size_t)ToUInt32( argumentPtr_ ); osc_bundle_element_size_t sizeResult = (osc_bundle_element_size_t)ToUInt32( argumentPtr_ );
if( !IsValidElementSizeValue(sizeResult) ) if( !IsValidElementSizeValue(sizeResult) )
throw MalformedMessageException("invalid blob size"); {
state = MALFORMED_MESSAGE_INVALID_BLOB_SIZE_ERROR;
size = sizeResult; }
data = (void*)(argumentPtr_+ osc::OSC_SIZEOF_INT32); 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 // it is only valid to call ComputeArrayItemCount when the argument is the array start marker
if( !IsArrayBegin() ) if( !IsArrayBegin() )
throw WrongArgumentTypeException(); {
state = WRONG_ARGUMENT_TYPE_ERROR;
return 0;
}
state = SUCCESS;
std::size_t result = 0; std::size_t result = 0;
unsigned int level = 0; unsigned int level = 0;
@@ -561,6 +595,7 @@ void ReceivedMessageArgumentIterator::Advance()
ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet ) ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet )
: addressPattern_( packet.Contents() ) : addressPattern_( packet.Contents() )
, state_( SUCCESS )
{ {
Init( packet.Contents(), packet.Size() ); Init( packet.Contents(), packet.Size() );
} }
@@ -568,6 +603,7 @@ ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet )
ReceivedMessage::ReceivedMessage( const ReceivedBundleElement& bundleElement ) ReceivedMessage::ReceivedMessage( const ReceivedBundleElement& bundleElement )
: addressPattern_( bundleElement.Contents() ) : addressPattern_( bundleElement.Contents() )
, state_( SUCCESS )
{ {
Init( bundleElement.Contents(), bundleElement.Size() ); 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 ) void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size )
{ {
if( !IsValidElementSizeValue(size) ) if( !IsValidElementSizeValue(size) )
throw MalformedMessageException( "invalid message size" ); {
state_ = MALFORMED_MESSAGE_INVALID_SIZE_ERROR;
return;
}
if( size == 0 ) if( size == 0 )
throw MalformedMessageException( "zero length messages not permitted" ); {
state_ = MALFORMED_MESSAGE_ZERO_SIZE_ERROR;
return;
}
if( !IsMultipleOf4(size) ) 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; const char *end = message + size;
typeTagsBegin_ = FindStr4End( addressPattern_, end ); typeTagsBegin_ = FindStr4End( addressPattern_, end );
if( typeTagsBegin_ == 0 ){ if( typeTagsBegin_ == 0 ){
// address pattern was not terminated before end // address pattern was not terminated before end
throw MalformedMessageException( "unterminated address pattern" ); state_ = MALFORMED_MESSAGE_UNTERMINATED_ADDRESS_PATTERN_ERROR;
return;
} }
if( typeTagsBegin_ == end ){ if( typeTagsBegin_ == end ){
@@ -612,7 +658,10 @@ void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size
}else{ }else{
if( *typeTagsBegin_ != ',' ) if( *typeTagsBegin_ != ',' )
throw MalformedMessageException( "type tags not present" ); {
state_ = MALFORMED_MESSAGE_NO_TYPE_TAGS_ERROR;
return;
}
if( *(typeTagsBegin_ + 1) == '\0' ){ if( *(typeTagsBegin_ + 1) == '\0' ){
// zero length type tags // 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 // check that all arguments are present and well formed
arguments_ = FindStr4End( typeTagsBegin_, end ); arguments_ = FindStr4End( typeTagsBegin_, end );
if( arguments_ == 0 ){ if( arguments_ == 0 )
throw MalformedMessageException( "type tags were not terminated before end of message" ); {
state_ = MALFORMED_MESSAGE_UNTERMINATED_TYPE_TAGS_ERROR;
return;
} }
++typeTagsBegin_; // advance past initial ',' ++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: case MIDI_MESSAGE_TYPE_TAG:
if( argument == end ) if( argument == end )
throw MalformedMessageException( "arguments exceed message size" ); {
state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR;
return;
}
argument += 4; argument += 4;
if( argument > end ) if( argument > end )
throw MalformedMessageException( "arguments exceed message size" ); {
state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR;
return;
}
break; break;
case INT64_TYPE_TAG: case INT64_TYPE_TAG:
@@ -674,44 +731,66 @@ void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size
case DOUBLE_TYPE_TAG: case DOUBLE_TYPE_TAG:
if( argument == end ) if( argument == end )
throw MalformedMessageException( "arguments exceed message size" ); {
state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR;
return;
}
argument += 8; argument += 8;
if( argument > end ) if( argument > end )
throw MalformedMessageException( "arguments exceed message size" ); {
state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR;
return;
}
break; break;
case STRING_TYPE_TAG: case STRING_TYPE_TAG:
case SYMBOL_TYPE_TAG: case SYMBOL_TYPE_TAG:
if( argument == end ) if( argument == end )
throw MalformedMessageException( "arguments exceed message size" ); {
state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR;
return;
}
argument = FindStr4End( argument, end ); argument = FindStr4End( argument, end );
if( argument == 0 ) if( argument == 0 )
throw MalformedMessageException( "unterminated string argument" ); {
state_ = MALFORMED_MESSAGE_UNTERMINATED_STRING_ERROR;
return;
}
break; break;
case BLOB_TYPE_TAG: case BLOB_TYPE_TAG:
{ {
if( argument + osc::OSC_SIZEOF_INT32 > end ) 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 // treat blob size as an unsigned int for the purposes of this calculation
uint32 blobSize = ToUInt32( argument ); uint32 blobSize = ToUInt32( argument );
argument = argument + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize ); argument = argument + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize );
if( argument > end ) if( argument > end )
MalformedMessageException( "arguments exceed message size" ); {
state_ = MALFORMED_MESSAGE_ARGUMENT_EXCEED_MSG_SIZE_ERROR;
return;
}
} }
break; break;
default: default:
throw MalformedMessageException( "unknown type tag" ); state_ = MALFORMED_MESSAGE_UNKNOWN_TYPE_TAG_ERROR;
return;
} }
}while( *++typeTag != '\0' ); }while( *++typeTag != '\0' );
typeTagsEnd_ = typeTag; typeTagsEnd_ = typeTag;
if( arrayLevel != 0 ) 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. // 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 ) ReceivedBundle::ReceivedBundle( const ReceivedPacket& packet )
: elementCount_( 0 ) : elementCount_( 0 )
, state_( SUCCESS )
{ {
Init( packet.Contents(), packet.Size() ); Init( packet.Contents(), packet.Size() );
} }
@@ -735,6 +815,7 @@ ReceivedBundle::ReceivedBundle( const ReceivedPacket& packet )
ReceivedBundle::ReceivedBundle( const ReceivedBundleElement& bundleElement ) ReceivedBundle::ReceivedBundle( const ReceivedBundleElement& bundleElement )
: elementCount_( 0 ) : elementCount_( 0 )
, state_( SUCCESS )
{ {
Init( bundleElement.Contents(), bundleElement.Size() ); Init( bundleElement.Contents(), bundleElement.Size() );
} }
@@ -744,13 +825,22 @@ void ReceivedBundle::Init( const char *bundle, osc_bundle_element_size_t size )
{ {
if( !IsValidElementSizeValue(size) ) if( !IsValidElementSizeValue(size) )
throw MalformedBundleException( "invalid bundle size" ); {
state_ = MALFORMED_BUNDLE_INVALID_SIZE_ERROR;
return;
}
if( size < 16 ) if( size < 16 )
throw MalformedBundleException( "packet too short for bundle" ); {
state_ = MALFORMED_BUNDLE_TOO_SHORT_ERROR;
return;
}
if( !IsMultipleOf4(size) ) if( !IsMultipleOf4(size) )
throw MalformedBundleException( "bundle size must be multiple of four" ); {
state_ = MALFORMED_BUNDLE_NOT_MULTIPLE_OF_4_ERROR;
return;
}
if( bundle[0] != '#' if( bundle[0] != '#'
|| bundle[1] != 'b' || bundle[1] != 'b'
@@ -760,7 +850,10 @@ void ReceivedBundle::Init( const char *bundle, osc_bundle_element_size_t size )
|| bundle[5] != 'l' || bundle[5] != 'l'
|| bundle[6] != 'e' || bundle[6] != 'e'
|| bundle[7] != '\0' ) || bundle[7] != '\0' )
throw MalformedBundleException( "bad bundle address pattern" ); {
state_ = MALFORMED_BUNDLE_INVALID_ADDRESS_PATTERN_ERROR;
return;
}
end_ = bundle + size; end_ = bundle + size;
@@ -770,22 +863,33 @@ void ReceivedBundle::Init( const char *bundle, osc_bundle_element_size_t size )
while( p < end_ ){ while( p < end_ ){
if( p + osc::OSC_SIZEOF_INT32 > 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 // treat element size as an unsigned int for the purposes of this calculation
uint32 elementSize = ToUInt32( p ); uint32 elementSize = ToUInt32( p );
if( (elementSize & ((uint32)0x03)) != 0 ) 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; p += osc::OSC_SIZEOF_INT32 + elementSize;
if( p > end_ ) if( p > end_ )
throw MalformedBundleException( "packet too short for bundle element" ); {
state_ = MALFORMED_BUNDLE_TOO_SHORT_FOR_ELEMENT_ERROR;
return;
}
++elementCount_; ++elementCount_;
} }
if( p != end_ ) if( p != end_ )
throw MalformedBundleException( "bundle contents " ); {
state_ = MALFORMED_BUNDLE_CONTENT_ERROR;
}
} }
@@ -42,49 +42,11 @@
#include <cstring> // size_t #include <cstring> // size_t
#include "OscTypes.h" #include "OscTypes.h"
#include "OscException.h"
namespace osc{ 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{ class ReceivedPacket{
public: public:
// Although the OSC spec is not entirely clear on this, we only support // 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 ) ReceivedPacket( const char *contents, osc_bundle_element_size_t size )
: contents_( contents ) : contents_( contents )
, size_( ValidateSize(size) ) {} , size_( ValidateSize(size, &state_) ) {}
ReceivedPacket( const char *contents, std::size_t size ) ReceivedPacket( const char *contents, std::size_t size )
: contents_( contents ) : 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)) #if !(defined(__x86_64__) || defined(_M_X64))
ReceivedPacket( const char *contents, int size ) ReceivedPacket( const char *contents, int size )
: contents_( contents ) : contents_( contents )
, size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {} , size_( ValidateSize( (osc_bundle_element_size_t)size, &state_ ) ) {}
#endif #endif
bool IsMessage() const { return !IsBundle(); } bool IsMessage() const { return !IsBundle(); }
@@ -111,12 +73,14 @@ public:
osc_bundle_element_size_t Size() const { return size_; } osc_bundle_element_size_t Size() const { return size_; }
const char *Contents() const { return contents_; } const char *Contents() const { return contents_; }
Errors State() const { return state_; }
private: private:
const char *contents_; const char *contents_;
osc_bundle_element_size_t size_; 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 // sanity check integer types declared in OscTypes.h
// you'll need to fix OscTypes.h if any of these asserts fail // you'll need to fix OscTypes.h if any of these asserts fail
@@ -126,14 +90,24 @@ private:
assert( sizeof(osc::uint64) == 8 ); assert( sizeof(osc::uint64) == 8 );
if( !IsValidElementSizeValue(size) ) if( !IsValidElementSizeValue(size) )
throw MalformedPacketException( "invalid packet size" ); {
*state = MALFORMED_PACKET_INVALID_SIZE_ERROR;
return 0;
}
if( size == 0 ) if( size == 0 )
throw MalformedPacketException( "zero length elements not permitted" ); {
*state = MALFORMED_PACKET_ZERO_SIZE_ERROR;
return 0;
}
if( !IsMultipleOf4(size) ) 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; return size;
} }
}; };
@@ -222,61 +196,61 @@ public:
bool IsBool() const bool IsBool() const
{ return *typeTagPtr_ == TRUE_TYPE_TAG || *typeTagPtr_ == FALSE_TYPE_TAG; } { return *typeTagPtr_ == TRUE_TYPE_TAG || *typeTagPtr_ == FALSE_TYPE_TAG; }
bool AsBool() const; bool AsBool(Errors & state) const;
bool AsBoolUnchecked() const; bool AsBoolUnchecked(Errors & state) const;
bool IsNil() const { return *typeTagPtr_ == NIL_TYPE_TAG; } bool IsNil() const { return *typeTagPtr_ == NIL_TYPE_TAG; }
bool IsInfinitum() const { return *typeTagPtr_ == INFINITUM_TYPE_TAG; } bool IsInfinitum() const { return *typeTagPtr_ == INFINITUM_TYPE_TAG; }
bool IsInt32() const { return *typeTagPtr_ == INT32_TYPE_TAG; } bool IsInt32() const { return *typeTagPtr_ == INT32_TYPE_TAG; }
int32 AsInt32() const; int32 AsInt32(Errors & state) const;
int32 AsInt32Unchecked() const; int32 AsInt32Unchecked() const;
bool IsFloat() const { return *typeTagPtr_ == FLOAT_TYPE_TAG; } bool IsFloat() const { return *typeTagPtr_ == FLOAT_TYPE_TAG; }
float AsFloat() const; float AsFloat(Errors & state) const;
float AsFloatUnchecked() const; float AsFloatUnchecked() const;
bool IsChar() const { return *typeTagPtr_ == CHAR_TYPE_TAG; } bool IsChar() const { return *typeTagPtr_ == CHAR_TYPE_TAG; }
char AsChar() const; char AsChar(Errors & state) const;
char AsCharUnchecked() const; char AsCharUnchecked() const;
bool IsRgbaColor() const { return *typeTagPtr_ == RGBA_COLOR_TYPE_TAG; } bool IsRgbaColor() const { return *typeTagPtr_ == RGBA_COLOR_TYPE_TAG; }
uint32 AsRgbaColor() const; uint32 AsRgbaColor(Errors & state) const;
uint32 AsRgbaColorUnchecked() const; uint32 AsRgbaColorUnchecked() const;
bool IsMidiMessage() const { return *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG; } bool IsMidiMessage() const { return *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG; }
uint32 AsMidiMessage() const; uint32 AsMidiMessage(Errors & state) const;
uint32 AsMidiMessageUnchecked() const; uint32 AsMidiMessageUnchecked() const;
bool IsInt64() const { return *typeTagPtr_ == INT64_TYPE_TAG; } bool IsInt64() const { return *typeTagPtr_ == INT64_TYPE_TAG; }
int64 AsInt64() const; int64 AsInt64(Errors & state) const;
int64 AsInt64Unchecked() const; int64 AsInt64Unchecked() const;
bool IsTimeTag() const { return *typeTagPtr_ == TIME_TAG_TYPE_TAG; } bool IsTimeTag() const { return *typeTagPtr_ == TIME_TAG_TYPE_TAG; }
uint64 AsTimeTag() const; uint64 AsTimeTag(Errors & state) const;
uint64 AsTimeTagUnchecked() const; uint64 AsTimeTagUnchecked() const;
bool IsDouble() const { return *typeTagPtr_ == DOUBLE_TYPE_TAG; } bool IsDouble() const { return *typeTagPtr_ == DOUBLE_TYPE_TAG; }
double AsDouble() const; double AsDouble(Errors & state) const;
double AsDoubleUnchecked() const; double AsDoubleUnchecked() const;
bool IsString() const { return *typeTagPtr_ == STRING_TYPE_TAG; } bool IsString() const { return *typeTagPtr_ == STRING_TYPE_TAG; }
const char* AsString() const; const char* AsString(Errors & state) const;
const char* AsStringUnchecked() const { return argumentPtr_; } const char* AsStringUnchecked() const { return argumentPtr_; }
bool IsSymbol() const { return *typeTagPtr_ == SYMBOL_TYPE_TAG; } bool IsSymbol() const { return *typeTagPtr_ == SYMBOL_TYPE_TAG; }
const char* AsSymbol() const; const char* AsSymbol(Errors & state) const;
const char* AsSymbolUnchecked() const { return argumentPtr_; } const char* AsSymbolUnchecked() const { return argumentPtr_; }
bool IsBlob() const { return *typeTagPtr_ == BLOB_TYPE_TAG; } bool IsBlob() const { return *typeTagPtr_ == BLOB_TYPE_TAG; }
void AsBlob( 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 ) 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 IsArrayBegin() const { return *typeTagPtr_ == ARRAY_BEGIN_TYPE_TAG; }
bool IsArrayEnd() const { return *typeTagPtr_ == ARRAY_END_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. // 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. // 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: private:
const char *typeTagPtr_; const char *typeTagPtr_;
@@ -338,21 +312,29 @@ class ReceivedMessageArgumentStream{
ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin, ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin,
const ReceivedMessageArgumentIterator& end ) const ReceivedMessageArgumentIterator& end )
: p_( begin ) : p_( begin )
, end_( end ) {} , end_( end )
, state_( SUCCESS ) {}
ReceivedMessageArgumentIterator p_, end_; ReceivedMessageArgumentIterator p_, end_;
Errors state_;
public: public:
Errors State() const { return state_; }
// end of stream // end of stream
bool Eos() const { return p_ == end_; } bool Eos() const { return p_ == end_; }
ReceivedMessageArgumentStream& operator>>( bool& rhs ) ReceivedMessageArgumentStream& operator>>( bool& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
rhs = (*p_++).AsBool(); }
else
{
rhs = (*p_++).AsBool(state_);
}
return *this; return *this;
} }
@@ -363,99 +345,143 @@ public:
ReceivedMessageArgumentStream& operator>>( int32& rhs ) ReceivedMessageArgumentStream& operator>>( int32& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
rhs = (*p_++).AsInt32(); }
else
{
rhs = (*p_++).AsInt32(state_);
}
return *this; return *this;
} }
ReceivedMessageArgumentStream& operator>>( float& rhs ) ReceivedMessageArgumentStream& operator>>( float& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
rhs = (*p_++).AsFloat(); }
else
{
rhs = (*p_++).AsFloat(state_);
}
return *this; return *this;
} }
ReceivedMessageArgumentStream& operator>>( char& rhs ) ReceivedMessageArgumentStream& operator>>( char& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
rhs = (*p_++).AsChar(); }
else
{
rhs = (*p_++).AsChar(state_);
}
return *this; return *this;
} }
ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs ) ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
rhs.value = (*p_++).AsRgbaColor(); }
else
{
rhs.value = (*p_++).AsRgbaColor(state_);
}
return *this; return *this;
} }
ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs ) ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
rhs.value = (*p_++).AsMidiMessage(); }
else
{
rhs.value = (*p_++).AsMidiMessage(state_);
}
return *this; return *this;
} }
ReceivedMessageArgumentStream& operator>>( int64& rhs ) ReceivedMessageArgumentStream& operator>>( int64& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
rhs = (*p_++).AsInt64(); }
else
{
rhs = (*p_++).AsInt64(state_);
}
return *this; return *this;
} }
ReceivedMessageArgumentStream& operator>>( TimeTag& rhs ) ReceivedMessageArgumentStream& operator>>( TimeTag& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
rhs.value = (*p_++).AsTimeTag(); }
else
{
rhs.value = (*p_++).AsTimeTag(state_);
}
return *this; return *this;
} }
ReceivedMessageArgumentStream& operator>>( double& rhs ) ReceivedMessageArgumentStream& operator>>( double& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
rhs = (*p_++).AsDouble(); }
else
{
rhs = (*p_++).AsDouble(state_);
}
return *this; return *this;
} }
ReceivedMessageArgumentStream& operator>>( Blob& rhs ) ReceivedMessageArgumentStream& operator>>( Blob& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
(*p_++).AsBlob( rhs.data, rhs.size ); }
else
{
(*p_++).AsBlob( rhs.data, rhs.size, state_ );
}
return *this; return *this;
} }
ReceivedMessageArgumentStream& operator>>( const char*& rhs ) ReceivedMessageArgumentStream& operator>>( const char*& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
rhs = (*p_++).AsString(); }
else
{
rhs = (*p_++).AsString(state_);
}
return *this; return *this;
} }
ReceivedMessageArgumentStream& operator>>( Symbol& rhs ) ReceivedMessageArgumentStream& operator>>( Symbol& rhs )
{ {
if( Eos() ) if( Eos() )
throw MissingArgumentException(); {
state_ = MISSING_ARGUMENT_ERROR;
rhs.value = (*p_++).AsSymbol(); }
else
{
rhs.value = (*p_++).AsSymbol(state_);
}
return *this; return *this;
} }
@@ -463,9 +489,10 @@ public:
{ {
(void) rhs; // suppress unused parameter warning (void) rhs; // suppress unused parameter warning
if( !Eos() ) if( Eos() )
throw ExcessArgumentException(); {
state_ = EXCESS_ARGUMENT_ERROR;
}
return *this; return *this;
} }
}; };
@@ -477,6 +504,8 @@ public:
explicit ReceivedMessage( const ReceivedPacket& packet ); explicit ReceivedMessage( const ReceivedPacket& packet );
explicit ReceivedMessage( const ReceivedBundleElement& bundleElement ); explicit ReceivedMessage( const ReceivedBundleElement& bundleElement );
Errors State() const { return state_; }
const char *AddressPattern() const { return addressPattern_; } const char *AddressPattern() const { return addressPattern_; }
// Support for non-standard SuperCollider integer address patterns: // Support for non-standard SuperCollider integer address patterns:
@@ -510,6 +539,7 @@ private:
const char *typeTagsBegin_; const char *typeTagsBegin_;
const char *typeTagsEnd_; const char *typeTagsEnd_;
const char *arguments_; const char *arguments_;
Errors state_;
}; };
@@ -519,6 +549,8 @@ public:
explicit ReceivedBundle( const ReceivedPacket& packet ); explicit ReceivedBundle( const ReceivedPacket& packet );
explicit ReceivedBundle( const ReceivedBundleElement& bundleElement ); explicit ReceivedBundle( const ReceivedBundleElement& bundleElement );
Errors State() const { return state_; }
uint64 TimeTag() const; uint64 TimeTag() const;
uint32 ElementCount() const { return elementCount_; } uint32 ElementCount() const { return elementCount_; }
@@ -539,6 +571,7 @@ private:
const char *timeTag_; const char *timeTag_;
const char *end_; const char *end_;
uint32 elementCount_; uint32 elementCount_;
Errors state_;
}; };
@@ -52,4 +52,52 @@ InfinitumType Infinitum;
ArrayInitiator BeginArray; ArrayInitiator BeginArray;
ArrayTerminator EndArray; 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 } // namespace osc
@@ -234,6 +234,48 @@ struct ArrayTerminator{
extern ArrayTerminator EndArray; 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 } // namespace osc
@@ -87,6 +87,11 @@ void UOscDispatcher::UnregisterReceiver(IOscReceiverInterface * receiver)
static void SendMessage(TCircularQueue<std::pair<FName, TArray<FOscDataElemStruct>>> & _pendingMessages, const osc::ReceivedMessage & message) static void SendMessage(TCircularQueue<std::pair<FName, TArray<FOscDataElemStruct>>> & _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()); const FName address(message.AddressPattern());
TArray<FOscDataElemStruct> data; TArray<FOscDataElemStruct> data;
@@ -114,7 +119,9 @@ static void SendMessage(TCircularQueue<std::pair<FName, TArray<FOscDataElemStruc
} }
else if(it->IsBool()) else if(it->IsBool())
{ {
elem.SetBool(it->AsBoolUnchecked()); osc::Errors error = osc::SUCCESS;
elem.SetBool(it->AsBoolUnchecked(error));
check(error == osc::SUCCESS);
} }
else if(it->IsString()) else if(it->IsString())
{ {
@@ -135,6 +142,12 @@ static void SendMessage(TCircularQueue<std::pair<FName, TArray<FOscDataElemStruc
static void SendBundle(TCircularQueue<std::pair<FName, TArray<FOscDataElemStruct>>> & _pendingMessages, const osc::ReceivedBundle & bundle) static void SendBundle(TCircularQueue<std::pair<FName, TArray<FOscDataElemStruct>>> & _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 begin = bundle.ElementsBegin();
const auto end = bundle.ElementsEnd(); const auto end = bundle.ElementsEnd();
for(auto it = begin; it != end; ++it) for(auto it = begin; it != end; ++it)
@@ -153,26 +166,23 @@ static void SendBundle(TCircularQueue<std::pair<FName, TArray<FOscDataElemStruct
void UOscDispatcher::Callback(const FArrayReaderPtr& data, const FIPv4Endpoint&) void UOscDispatcher::Callback(const FArrayReaderPtr& data, const FIPv4Endpoint&)
{ {
const auto wasEmpty = _pendingMessages.IsEmpty(); const auto wasEmpty = _pendingMessages.IsEmpty();
try
const osc::ReceivedPacket packet((const char *)data->GetData(), data->Num());
if(packet.State() != osc::SUCCESS)
{ {
const osc::ReceivedPacket packet((const char *)data->GetData(), data->Num()); UE_LOG(LogOSC, Warning, TEXT("OSC Received Packet Error: %s"), osc::errorString(packet.State()));
if(packet.IsBundle()) return;
{
SendBundle(_pendingMessages, osc::ReceivedBundle(packet));
}
else
{
SendMessage(_pendingMessages, osc::ReceivedMessage(packet));
}
} }
catch(osc::Exception &e)
if(packet.IsBundle())
{ {
// Exceptions are disabled by default, so destructors are not called. SendBundle(_pendingMessages, osc::ReceivedBundle(packet));
// 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);
} }
else
{
SendMessage(_pendingMessages, osc::ReceivedMessage(packet));
}
// Set a single callback in the main thread per frame. // Set a single callback in the main thread per frame.
if(wasEmpty && !_pendingMessages.IsEmpty()) if(wasEmpty && !_pendingMessages.IsEmpty())
{ {