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))
{
Definitions.Add("OSC_EDITOR_BUILD=1");
@@ -167,9 +167,21 @@ void UOscFunctionLibrary::SendOsc(FName Address, const TArray<FOscDataElemStruct
{
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;
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()));
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_ )
, 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<float*>(argumentCurrent_) = rhs;
*reinterpret_cast<float*>(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<double*>(argumentCurrent_) = rhs;
*reinterpret_cast<double*>(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;
}
@@ -40,44 +40,18 @@
#include <cstring> // 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
@@ -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;
}
}
@@ -42,49 +42,11 @@
#include <cstring> // 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_;
};
@@ -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
@@ -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
@@ -87,6 +87,11 @@ void UOscDispatcher::UnregisterReceiver(IOscReceiverInterface * receiver)
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());
TArray<FOscDataElemStruct> data;
@@ -114,7 +119,9 @@ static void SendMessage(TCircularQueue<std::pair<FName, TArray<FOscDataElemStruc
}
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())
{
@@ -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)
{
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(TCircularQueue<std::pair<FName, TArray<FOscDataElemStruct
void UOscDispatcher::Callback(const FArrayReaderPtr& data, const FIPv4Endpoint&)
{
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());
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())
{