mirror of
https://github.com/storytold/UE4-OSC.git
synced 2026-10-09 00:09:43 +00:00
replace exceptions with error code (mobile compilation)
This commit is contained in:
@@ -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())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user