37 #include "OscReceivedElements.h"
39 #include "OscHostEndianness.h"
49 static inline const char* FindStr4End(
const char *p )
65 static inline const char* FindStr4End(
const char *p,
const char *end )
76 while( p < end && *p )
87 static inline uint32 RoundUp4( uint32 x )
89 return (x + 3) & ~((uint32)0x03);
93 static inline int32 ToInt32(
const char *p )
95 #ifdef OSC_HOST_LITTLE_ENDIAN
113 static inline uint32 ToUInt32(
const char *p )
115 #ifdef OSC_HOST_LITTLE_ENDIAN
133 static inline int64 ToInt64(
const char *p )
135 #ifdef OSC_HOST_LITTLE_ENDIAN
157 static inline uint64 ToUInt64(
const char *p )
159 #ifdef OSC_HOST_LITTLE_ENDIAN
182 bool ReceivedPacket::IsBundle()
const
184 return (Size() > 0 && Contents()[0] ==
'#');
189 bool ReceivedBundleElement::IsBundle()
const
191 return (Size() > 0 && Contents()[0] ==
'#');
195 osc_bundle_element_size_t ReceivedBundleElement::Size()
const
197 return ToInt32( sizePtr_ );
202 bool ReceivedMessageArgument::AsBool()
const
205 throw MissingArgumentException();
206 else if( *typeTagPtr_ == TRUE_TYPE_TAG )
208 else if( *typeTagPtr_ == FALSE_TYPE_TAG )
211 throw WrongArgumentTypeException();
215 bool ReceivedMessageArgument::AsBoolUnchecked()
const
218 throw MissingArgumentException();
219 else if( *typeTagPtr_ == TRUE_TYPE_TAG )
226 int32 ReceivedMessageArgument::AsInt32()
const
229 throw MissingArgumentException();
230 else if( *typeTagPtr_ == INT32_TYPE_TAG )
231 return AsInt32Unchecked();
233 throw WrongArgumentTypeException();
237 int32 ReceivedMessageArgument::AsInt32Unchecked()
const
239 #ifdef OSC_HOST_LITTLE_ENDIAN
245 u.c[0] = argumentPtr_[3];
246 u.c[1] = argumentPtr_[2];
247 u.c[2] = argumentPtr_[1];
248 u.c[3] = argumentPtr_[0];
252 return *(int32*)argument_;
257 float ReceivedMessageArgument::AsFloat()
const
260 throw MissingArgumentException();
261 else if( *typeTagPtr_ == FLOAT_TYPE_TAG )
262 return AsFloatUnchecked();
264 throw WrongArgumentTypeException();
268 float ReceivedMessageArgument::AsFloatUnchecked()
const
270 #ifdef OSC_HOST_LITTLE_ENDIAN
276 u.c[0] = argumentPtr_[3];
277 u.c[1] = argumentPtr_[2];
278 u.c[2] = argumentPtr_[1];
279 u.c[3] = argumentPtr_[0];
283 return *(
float*)argument_;
288 char ReceivedMessageArgument::AsChar()
const
291 throw MissingArgumentException();
292 else if( *typeTagPtr_ == CHAR_TYPE_TAG )
293 return AsCharUnchecked();
295 throw WrongArgumentTypeException();
299 char ReceivedMessageArgument::AsCharUnchecked()
const
301 return (
char)ToInt32( argumentPtr_ );
305 uint32 ReceivedMessageArgument::AsRgbaColor()
const
308 throw MissingArgumentException();
309 else if( *typeTagPtr_ == RGBA_COLOR_TYPE_TAG )
310 return AsRgbaColorUnchecked();
312 throw WrongArgumentTypeException();
316 uint32 ReceivedMessageArgument::AsRgbaColorUnchecked()
const
318 return ToUInt32( argumentPtr_ );
322 uint32 ReceivedMessageArgument::AsMidiMessage()
const
325 throw MissingArgumentException();
326 else if( *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG )
327 return AsMidiMessageUnchecked();
329 throw WrongArgumentTypeException();
333 uint32 ReceivedMessageArgument::AsMidiMessageUnchecked()
const
335 return ToUInt32( argumentPtr_ );
339 int64 ReceivedMessageArgument::AsInt64()
const
342 throw MissingArgumentException();
343 else if( *typeTagPtr_ == INT64_TYPE_TAG )
344 return AsInt64Unchecked();
346 throw WrongArgumentTypeException();
350 int64 ReceivedMessageArgument::AsInt64Unchecked()
const
352 return ToInt64( argumentPtr_ );
356 uint64 ReceivedMessageArgument::AsTimeTag()
const
359 throw MissingArgumentException();
360 else if( *typeTagPtr_ == TIME_TAG_TYPE_TAG )
361 return AsTimeTagUnchecked();
363 throw WrongArgumentTypeException();
367 uint64 ReceivedMessageArgument::AsTimeTagUnchecked()
const
369 return ToUInt64( argumentPtr_ );
373 double ReceivedMessageArgument::AsDouble()
const
376 throw MissingArgumentException();
377 else if( *typeTagPtr_ == DOUBLE_TYPE_TAG )
378 return AsDoubleUnchecked();
380 throw WrongArgumentTypeException();
384 double ReceivedMessageArgument::AsDoubleUnchecked()
const
386 #ifdef OSC_HOST_LITTLE_ENDIAN
392 u.c[0] = argumentPtr_[7];
393 u.c[1] = argumentPtr_[6];
394 u.c[2] = argumentPtr_[5];
395 u.c[3] = argumentPtr_[4];
396 u.c[4] = argumentPtr_[3];
397 u.c[5] = argumentPtr_[2];
398 u.c[6] = argumentPtr_[1];
399 u.c[7] = argumentPtr_[0];
403 return *(
double*)argument_;
408 const char* ReceivedMessageArgument::AsString()
const
411 throw MissingArgumentException();
412 else if( *typeTagPtr_ == STRING_TYPE_TAG )
415 throw WrongArgumentTypeException();
419 const char* ReceivedMessageArgument::AsSymbol()
const
422 throw MissingArgumentException();
423 else if( *typeTagPtr_ == SYMBOL_TYPE_TAG )
426 throw WrongArgumentTypeException();
430 void ReceivedMessageArgument::AsBlob(
const void*& data, osc_bundle_element_size_t& size )
const
433 throw MissingArgumentException();
434 else if( *typeTagPtr_ == BLOB_TYPE_TAG )
435 AsBlobUnchecked( data, size );
437 throw WrongArgumentTypeException();
441 void ReceivedMessageArgument::AsBlobUnchecked(
const void*& data, osc_bundle_element_size_t& size )
const
444 osc_bundle_element_size_t sizeResult = (osc_bundle_element_size_t)ToUInt32( argumentPtr_ );
445 if( !IsValidElementSizeValue(sizeResult) )
446 throw MalformedMessageException(
"invalid blob size");
449 data = (
void*)(argumentPtr_+ osc::OSC_SIZEOF_INT32);
452 std::size_t ReceivedMessageArgument::ComputeArrayItemCount()
const
455 if( !IsArrayBegin() )
456 throw WrongArgumentTypeException();
458 std::size_t result = 0;
459 unsigned int level = 0;
460 const char *typeTag = typeTagPtr_ + 1;
465 switch( *typeTag++ ) {
466 case ARRAY_BEGIN_TYPE_TAG:
470 case ARRAY_END_TYPE_TAG:
487 void ReceivedMessageArgumentIterator::Advance()
489 if( !value_.typeTagPtr_ )
492 switch( *value_.typeTagPtr_++ ){
495 --value_.typeTagPtr_;
501 case INFINITUM_TYPE_TAG:
509 case RGBA_COLOR_TYPE_TAG:
510 case MIDI_MESSAGE_TYPE_TAG:
512 value_.argumentPtr_ += 4;
516 case TIME_TAG_TYPE_TAG:
517 case DOUBLE_TYPE_TAG:
519 value_.argumentPtr_ += 8;
522 case STRING_TYPE_TAG:
523 case SYMBOL_TYPE_TAG:
529 value_.argumentPtr_ = FindStr4End( value_.argumentPtr_ );
535 uint32 blobSize = ToUInt32( value_.argumentPtr_ );
536 value_.argumentPtr_ = value_.argumentPtr_ + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize );
540 case ARRAY_BEGIN_TYPE_TAG:
541 case ARRAY_END_TYPE_TAG:
552 --value_.typeTagPtr_;
559 ReceivedMessage::ReceivedMessage(
const ReceivedPacket& packet )
560 : addressPattern_( packet.Contents() )
562 Init( packet.Contents(), packet.Size() );
566 ReceivedMessage::ReceivedMessage(
const ReceivedBundleElement& bundleElement )
567 : addressPattern_( bundleElement.Contents() )
569 Init( bundleElement.Contents(), bundleElement.Size() );
573 bool ReceivedMessage::AddressPatternIsUInt32()
const
575 return (addressPattern_[0] ==
'\0');
579 uint32 ReceivedMessage::AddressPatternAsUInt32()
const
581 return ToUInt32( addressPattern_ );
585 void ReceivedMessage::Init(
const char *message, osc_bundle_element_size_t size )
587 if( !IsValidElementSizeValue(size) )
588 throw MalformedMessageException(
"invalid message size" );
591 throw MalformedMessageException(
"zero length messages not permitted" );
593 if( !IsMultipleOf4(size) )
594 throw MalformedMessageException(
"message size must be multiple of four" );
596 const char *end = message + size;
598 typeTagsBegin_ = FindStr4End( addressPattern_, end );
599 if( typeTagsBegin_ == 0 ){
601 throw MalformedMessageException(
"unterminated address pattern" );
604 if( typeTagsBegin_ == end ){
611 if( *typeTagsBegin_ !=
',' )
612 throw MalformedMessageException(
"type tags not present" );
614 if( *(typeTagsBegin_ + 1) ==
'\0' ){
623 arguments_ = FindStr4End( typeTagsBegin_, end );
624 if( arguments_ == 0 ){
625 throw MalformedMessageException(
"type tags were not terminated before end of message" );
630 const char *typeTag = typeTagsBegin_;
631 const char *argument = arguments_;
632 unsigned int arrayLevel = 0;
639 case INFINITUM_TYPE_TAG:
646 case ARRAY_BEGIN_TYPE_TAG:
651 case ARRAY_END_TYPE_TAG:
659 case RGBA_COLOR_TYPE_TAG:
660 case MIDI_MESSAGE_TYPE_TAG:
662 if( argument == end )
663 throw MalformedMessageException(
"arguments exceed message size" );
666 throw MalformedMessageException(
"arguments exceed message size" );
670 case TIME_TAG_TYPE_TAG:
671 case DOUBLE_TYPE_TAG:
673 if( argument == end )
674 throw MalformedMessageException(
"arguments exceed message size" );
677 throw MalformedMessageException(
"arguments exceed message size" );
680 case STRING_TYPE_TAG:
681 case SYMBOL_TYPE_TAG:
683 if( argument == end )
684 throw MalformedMessageException(
"arguments exceed message size" );
685 argument = FindStr4End( argument, end );
687 throw MalformedMessageException(
"unterminated string argument" );
692 if( argument + osc::OSC_SIZEOF_INT32 > end )
693 MalformedMessageException(
"arguments exceed message size" );
696 uint32 blobSize = ToUInt32( argument );
697 argument = argument + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize );
699 MalformedMessageException(
"arguments exceed message size" );
704 throw MalformedMessageException(
"unknown type tag" );
707 }
while( *++typeTag !=
'\0' );
708 typeTagsEnd_ = typeTag;
710 if( arrayLevel != 0 )
711 throw MalformedMessageException(
"array was not terminated before end of message (expected ']' end of array tag)" );
717 std::ptrdiff_t argumentCount = typeTagsEnd_ - typeTagsBegin_;
718 assert( argumentCount >= 0 );
719 assert( argumentCount <= OSC_INT32_MAX );
726 ReceivedBundle::ReceivedBundle(
const ReceivedPacket& packet )
729 Init( packet.Contents(), packet.Size() );
733 ReceivedBundle::ReceivedBundle(
const ReceivedBundleElement& bundleElement )
736 Init( bundleElement.Contents(), bundleElement.Size() );
740 void ReceivedBundle::Init(
const char *bundle, osc_bundle_element_size_t size )
743 if( !IsValidElementSizeValue(size) )
744 throw MalformedBundleException(
"invalid bundle size" );
747 throw MalformedBundleException(
"packet too short for bundle" );
749 if( !IsMultipleOf4(size) )
750 throw MalformedBundleException(
"bundle size must be multiple of four" );
759 || bundle[7] !=
'\0' )
760 throw MalformedBundleException(
"bad bundle address pattern" );
762 end_ = bundle + size;
764 timeTag_ = bundle + 8;
766 const char *p = timeTag_ + 8;
769 if( p + osc::OSC_SIZEOF_INT32 > end_ )
770 throw MalformedBundleException(
"packet too short for elementSize" );
773 uint32 elementSize = ToUInt32( p );
774 if( (elementSize & ((uint32)0x03)) != 0 )
775 throw MalformedBundleException(
"bundle element size must be multiple of four" );
777 p += osc::OSC_SIZEOF_INT32 + elementSize;
779 throw MalformedBundleException(
"packet too short for bundle element" );
785 throw MalformedBundleException(
"bundle contents " );
789 uint64 ReceivedBundle::TimeTag()
const
791 return ToUInt64( timeTag_ );