| 
							- /*
 - 	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.
 - */
 - #include "OscReceivedElements.h"
 - 
 - #include "OscHostEndianness.h"
 - 
 - #include <cstddef> // ptrdiff_t
 - 
 - namespace osc{
 - 
 - 
 - // return the first 4 byte boundary after the end of a str4
 - // be careful about calling this version if you don't know whether
 - // the string is terminated correctly.
 - static inline const char* FindStr4End( const char *p )
 - {
 - 	if( p[0] == '\0' )    // special case for SuperCollider integer address pattern
 - 		return p + 4;
 - 
 -     p += 3;
 - 
 -     while( *p )
 -         p += 4;
 - 
 -     return p + 1;
 - }
 - 
 - 
 - // return the first 4 byte boundary after the end of a str4
 - // returns 0 if p == end or if the string is unterminated
 - static inline const char* FindStr4End( const char *p, const char *end )
 - {
 -     if( p >= end )
 -         return 0;
 - 
 - 	if( p[0] == '\0' )    // special case for SuperCollider integer address pattern
 - 		return p + 4;
 - 
 -     p += 3;
 -     end -= 1;
 - 
 -     while( p < end && *p )
 -         p += 4;
 - 
 -     if( *p )
 -         return 0;
 -     else
 -         return p + 1;
 - }
 - 
 - 
 - // round up to the next highest multiple of 4. unless x is already a multiple of 4
 - static inline uint32 RoundUp4( uint32 x ) 
 - {
 -     return (x + 3) & ~((uint32)0x03);
 - }
 - 
 - 
 - static inline int32 ToInt32( const char *p )
 - {
 - #ifdef OSC_HOST_LITTLE_ENDIAN
 -     union{
 -         osc::int32 i;
 -         char c[4];
 -     } u;
 - 
 -     u.c[0] = p[3];
 -     u.c[1] = p[2];
 -     u.c[2] = p[1];
 -     u.c[3] = p[0];
 - 
 -     return u.i;
 - #else
 - 	return *(int32*)p;
 - #endif
 - }
 - 
 - 
 - static inline uint32 ToUInt32( const char *p )
 - {
 - #ifdef OSC_HOST_LITTLE_ENDIAN
 -     union{
 -         osc::uint32 i;
 -         char c[4];
 -     } u;
 - 
 -     u.c[0] = p[3];
 -     u.c[1] = p[2];
 -     u.c[2] = p[1];
 -     u.c[3] = p[0];
 - 
 -     return u.i;
 - #else
 - 	return *(uint32*)p;
 - #endif
 - }
 - 
 - 
 - static inline int64 ToInt64( const char *p )
 - {
 - #ifdef OSC_HOST_LITTLE_ENDIAN
 -     union{
 -         osc::int64 i;
 -         char c[8];
 -     } u;
 - 
 -     u.c[0] = p[7];
 -     u.c[1] = p[6];
 -     u.c[2] = p[5];
 -     u.c[3] = p[4];
 -     u.c[4] = p[3];
 -     u.c[5] = p[2];
 -     u.c[6] = p[1];
 -     u.c[7] = p[0];
 - 
 -     return u.i;
 - #else
 - 	return *(int64*)p;
 - #endif
 - }
 - 
 - 
 - static inline uint64 ToUInt64( const char *p )
 - {
 - #ifdef OSC_HOST_LITTLE_ENDIAN
 -     union{
 -         osc::uint64 i;
 -         char c[8];
 -     } u;
 - 
 -     u.c[0] = p[7];
 -     u.c[1] = p[6];
 -     u.c[2] = p[5];
 -     u.c[3] = p[4];
 -     u.c[4] = p[3];
 -     u.c[5] = p[2];
 -     u.c[6] = p[1];
 -     u.c[7] = p[0];
 - 
 -     return u.i;
 - #else
 - 	return *(uint64*)p;
 - #endif
 - }
 - 
 - //------------------------------------------------------------------------------
 - 
 - bool ReceivedPacket::IsBundle() const
 - {
 -     return (Size() > 0 && Contents()[0] == '#');
 - }
 - 
 - //------------------------------------------------------------------------------
 - 
 - bool ReceivedBundleElement::IsBundle() const
 - {
 -     return (Size() > 0 && Contents()[0] == '#');
 - }
 - 
 - 
 - osc_bundle_element_size_t ReceivedBundleElement::Size() const
 - {
 -     return ToInt32( sizePtr_ );
 - }
 - 
 - //------------------------------------------------------------------------------
 - 
 - bool ReceivedMessageArgument::AsBool() const
 - {
 -     if( !typeTagPtr_ )
 -         throw MissingArgumentException();
 - 	else if( *typeTagPtr_ == TRUE_TYPE_TAG )
 - 		return true;
 - 	else if( *typeTagPtr_ == FALSE_TYPE_TAG )
 - 		return false;
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - bool ReceivedMessageArgument::AsBoolUnchecked() const
 - {
 -     if( !typeTagPtr_ )
 -         throw MissingArgumentException();
 - 	else if( *typeTagPtr_ == TRUE_TYPE_TAG )
 - 		return true;
 - 	else if (*typeTagPtr_ == osc::TypeTagValues::FLOAT_TYPE_TAG) // Do conversion for touchOSC's limited values
 - 		return AsFloatUnchecked() > 0;
 -     else
 - 	    return false;
 - }
 - 
 - 
 - int32 ReceivedMessageArgument::AsInt32() const
 - {
 - 	if (!typeTagPtr_)
 - 		throw MissingArgumentException();
 - 	else if (*typeTagPtr_ == INT32_TYPE_TAG)
 - 		return AsInt32Unchecked();
 - 	else if (*typeTagPtr_ == osc::TypeTagValues::FLOAT_TYPE_TAG) // Do conversion for touchOSC's limited values
 - 		return static_cast<osc::int32>(AsFloatUnchecked());
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - int32 ReceivedMessageArgument::AsInt32Unchecked() const
 - {
 - #ifdef OSC_HOST_LITTLE_ENDIAN
 -     union{
 -         osc::int32 i;
 -         char c[4];
 -     } u;
 - 
 -     u.c[0] = argumentPtr_[3];
 -     u.c[1] = argumentPtr_[2];
 -     u.c[2] = argumentPtr_[1];
 -     u.c[3] = argumentPtr_[0];
 - 
 -     return u.i;
 - #else
 - 	return *(int32*)argument_;
 - #endif
 - }
 - 
 - 
 - float ReceivedMessageArgument::AsFloat() const
 - {
 - 	if (!typeTagPtr_)
 - 		throw MissingArgumentException();
 - 	else if (*typeTagPtr_ == FLOAT_TYPE_TAG)
 - 		return AsFloatUnchecked();
 - 	else if (*typeTagPtr_ == TRUE_TYPE_TAG) // Allow conversion to other types
 - 		return 1.0f;
 - 	else if (*typeTagPtr_ == FALSE_TYPE_TAG)
 - 		return 0.0f;
 - 	else if (*typeTagPtr_ == INT32_TYPE_TAG)
 - 		return static_cast<float>(AsInt32Unchecked());
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - float ReceivedMessageArgument::AsFloatUnchecked() const
 - {
 - #ifdef OSC_HOST_LITTLE_ENDIAN
 -     union{
 -         float f;
 -         char c[4];
 -     } u;
 - 
 -     u.c[0] = argumentPtr_[3];
 -     u.c[1] = argumentPtr_[2];
 -     u.c[2] = argumentPtr_[1];
 -     u.c[3] = argumentPtr_[0];
 - 
 -     return u.f;
 - #else
 - 	return *(float*)argument_;
 - #endif
 - }
 - 
 - 
 - char ReceivedMessageArgument::AsChar() const
 - {
 -     if( !typeTagPtr_ )
 -         throw MissingArgumentException();
 - 	else if( *typeTagPtr_ == CHAR_TYPE_TAG )
 - 		return AsCharUnchecked();
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - char ReceivedMessageArgument::AsCharUnchecked() const
 - {
 -     return (char)ToInt32( argumentPtr_ );
 - }
 - 
 - 
 - uint32 ReceivedMessageArgument::AsRgbaColor() const
 - {
 -     if( !typeTagPtr_ )
 -         throw MissingArgumentException();
 - 	else if( *typeTagPtr_ == RGBA_COLOR_TYPE_TAG )
 - 		return AsRgbaColorUnchecked();
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const
 - {
 - 	return ToUInt32( argumentPtr_ );
 - }
 - 
 - 
 - uint32 ReceivedMessageArgument::AsMidiMessage() const
 - {
 -     if( !typeTagPtr_ )
 -         throw MissingArgumentException();
 - 	else if( *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG )
 - 		return AsMidiMessageUnchecked();
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const
 - {
 - 	return ToUInt32( argumentPtr_ );
 - }
 - 
 - 
 - int64 ReceivedMessageArgument::AsInt64() const
 - {
 -     if( !typeTagPtr_ )
 -         throw MissingArgumentException();
 - 	else if( *typeTagPtr_ == INT64_TYPE_TAG )
 - 		return AsInt64Unchecked();
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - int64 ReceivedMessageArgument::AsInt64Unchecked() const
 - {
 -     return ToInt64( argumentPtr_ );
 - }
 - 
 - 
 - uint64 ReceivedMessageArgument::AsTimeTag() const
 - {
 -     if( !typeTagPtr_ )
 -         throw MissingArgumentException();
 - 	else if( *typeTagPtr_ == TIME_TAG_TYPE_TAG )
 - 		return AsTimeTagUnchecked();
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const
 - {
 -     return ToUInt64( argumentPtr_ );
 - }
 - 
 - 
 - double ReceivedMessageArgument::AsDouble() const
 - {
 -     if( !typeTagPtr_ )
 -         throw MissingArgumentException();
 - 	else if( *typeTagPtr_ == DOUBLE_TYPE_TAG )
 - 		return AsDoubleUnchecked();
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - double ReceivedMessageArgument::AsDoubleUnchecked() const
 - {
 - #ifdef OSC_HOST_LITTLE_ENDIAN
 -     union{
 -         double d;
 -         char c[8];
 -     } u;
 - 
 -     u.c[0] = argumentPtr_[7];
 -     u.c[1] = argumentPtr_[6];
 -     u.c[2] = argumentPtr_[5];
 -     u.c[3] = argumentPtr_[4];
 -     u.c[4] = argumentPtr_[3];
 -     u.c[5] = argumentPtr_[2];
 -     u.c[6] = argumentPtr_[1];
 -     u.c[7] = argumentPtr_[0];
 - 
 -     return u.d;
 - #else
 - 	return *(double*)argument_;
 - #endif
 - }
 - 
 - 
 - const char* ReceivedMessageArgument::AsString() const
 - {
 -     if( !typeTagPtr_ )
 -         throw MissingArgumentException();
 - 	else if( *typeTagPtr_ == STRING_TYPE_TAG )
 - 		return argumentPtr_;
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - const char* ReceivedMessageArgument::AsSymbol() const
 - {
 -     if( !typeTagPtr_ )
 -         throw MissingArgumentException();
 - 	else if( *typeTagPtr_ == SYMBOL_TYPE_TAG )
 - 		return argumentPtr_;
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - void ReceivedMessageArgument::AsBlob( const void*& data, osc_bundle_element_size_t& size ) const
 - {
 -     if( !typeTagPtr_ )
 -         throw MissingArgumentException();
 - 	else if( *typeTagPtr_ == BLOB_TYPE_TAG )
 - 		AsBlobUnchecked( data, size );
 - 	else
 - 		throw WrongArgumentTypeException();
 - }
 - 
 - 
 - void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) 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);
 - }
 - 
 - std::size_t ReceivedMessageArgument::ComputeArrayItemCount() const
 - {
 -     // it is only valid to call ComputeArrayItemCount when the argument is the array start marker
 -     if( !IsArrayBegin() )
 -         throw WrongArgumentTypeException();
 - 
 -     std::size_t result = 0;
 -     unsigned int level = 0;
 -     const char *typeTag = typeTagPtr_ + 1;
 - 
 -     // iterate through all type tags. note that ReceivedMessage::Init
 -     // has already checked that the message is well formed.
 -     while( *typeTag ) {
 -         switch( *typeTag++ ) {
 -             case ARRAY_BEGIN_TYPE_TAG:
 -                 level += 1;
 -                 break;
 - 
 -             case ARRAY_END_TYPE_TAG:
 -                 if(level == 0)
 -                     return result;
 -                 level -= 1;
 -                 break;
 - 
 -             default:
 -                 if( level == 0 ) // only count items at level 0
 -                     ++result;
 -         }
 -     }
 - 
 -     return result;
 - }
 - 
 - //------------------------------------------------------------------------------
 - 
 - void ReceivedMessageArgumentIterator::Advance()
 - {
 -     if( !value_.typeTagPtr_ )
 -         return;
 -         
 -     switch( *value_.typeTagPtr_++ ){
 -         case '\0':
 -             // don't advance past end
 -             --value_.typeTagPtr_;
 -             break;
 -             
 -         case TRUE_TYPE_TAG:
 -         case FALSE_TYPE_TAG:
 -         case NIL_TYPE_TAG:
 -         case INFINITUM_TYPE_TAG:
 -         
 -             // zero length
 -             break;
 - 
 -         case INT32_TYPE_TAG:
 -         case FLOAT_TYPE_TAG: 					
 -         case CHAR_TYPE_TAG:
 -         case RGBA_COLOR_TYPE_TAG:
 -         case MIDI_MESSAGE_TYPE_TAG:
 - 
 -             value_.argumentPtr_ += 4;
 -             break;
 - 
 -         case INT64_TYPE_TAG:
 -         case TIME_TAG_TYPE_TAG:
 -         case DOUBLE_TYPE_TAG:
 - 				
 -             value_.argumentPtr_ += 8;
 -             break;
 - 
 -         case STRING_TYPE_TAG: 
 -         case SYMBOL_TYPE_TAG:
 - 
 -             // we use the unsafe function FindStr4End(char*) here because all of
 -             // the arguments have already been validated in
 -             // ReceivedMessage::Init() below.
 -             
 -             value_.argumentPtr_ = FindStr4End( value_.argumentPtr_ );
 -             break;
 - 
 -         case BLOB_TYPE_TAG:
 -             {
 -                 // treat blob size as an unsigned int for the purposes of this calculation
 -                 uint32 blobSize = ToUInt32( value_.argumentPtr_ );
 -                 value_.argumentPtr_ = value_.argumentPtr_ + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize );
 -             }
 -             break;
 - 
 -         case ARRAY_BEGIN_TYPE_TAG:
 -         case ARRAY_END_TYPE_TAG: 
 - 
 -             //    [ Indicates the beginning of an array. The tags following are for
 -             //        data in the Array until a close brace tag is reached.
 -             //    ] Indicates the end of an array.
 - 
 -             // zero length, don't advance argument ptr
 -             break;
 - 
 -         default:    // unknown type tag
 -             // don't advance
 -             --value_.typeTagPtr_;
 -             break;
 -     }
 - }
 - 
 - //------------------------------------------------------------------------------
 - 
 - ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet )
 -     : addressPattern_( packet.Contents() )
 - {
 -     Init( packet.Contents(), packet.Size() );
 - }
 - 
 - 
 - ReceivedMessage::ReceivedMessage( const ReceivedBundleElement& bundleElement )
 -     : addressPattern_( bundleElement.Contents() )
 - {
 -     Init( bundleElement.Contents(), bundleElement.Size() );
 - }
 - 
 - 
 - bool ReceivedMessage::AddressPatternIsUInt32() const
 - {
 - 	return (addressPattern_[0] == '\0');
 - }
 - 
 - 
 - uint32 ReceivedMessage::AddressPatternAsUInt32() const
 - {
 -     return ToUInt32( addressPattern_ );
 - }
 - 
 - 
 - void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size )
 - {
 -     if( !IsValidElementSizeValue(size) )
 -         throw MalformedMessageException( "invalid message size" );
 - 
 -     if( size == 0 )
 -         throw MalformedMessageException( "zero length messages not permitted" );
 - 
 -     if( !IsMultipleOf4(size) )
 -         throw MalformedMessageException( "message size must be multiple of four" );
 - 
 -     const char *end = message + size;
 - 
 -     typeTagsBegin_ = FindStr4End( addressPattern_, end );
 -     if( typeTagsBegin_ == 0 ){
 -         // address pattern was not terminated before end
 -         throw MalformedMessageException( "unterminated address pattern" );
 -     }
 - 
 -     if( typeTagsBegin_ == end ){
 -         // message consists of only the address pattern - no arguments or type tags.
 -         typeTagsBegin_ = 0;
 -         typeTagsEnd_ = 0;
 -         arguments_ = 0;
 -             
 -     }else{
 -         if( *typeTagsBegin_ != ',' )
 -             throw MalformedMessageException( "type tags not present" );
 - 
 -         if( *(typeTagsBegin_ + 1) == '\0' ){
 -             // zero length type tags
 -             typeTagsBegin_ = 0;
 -             typeTagsEnd_ = 0;
 -             arguments_ = 0;
 - 
 -         }else{
 -             // 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" );
 -             }
 - 
 -             ++typeTagsBegin_; // advance past initial ','
 -             
 -             const char *typeTag = typeTagsBegin_;
 -             const char *argument = arguments_;
 -             unsigned int arrayLevel = 0;
 -                         
 -             do{
 -                 switch( *typeTag ){
 -                     case TRUE_TYPE_TAG:
 -                     case FALSE_TYPE_TAG:
 -                     case NIL_TYPE_TAG:
 -                     case INFINITUM_TYPE_TAG:
 -                         // zero length
 -                         break;
 - 
 -                     //    [ Indicates the beginning of an array. The tags following are for
 -                     //        data in the Array until a close brace tag is reached.
 -                     //    ] Indicates the end of an array.
 -                     case ARRAY_BEGIN_TYPE_TAG:
 -                         ++arrayLevel;
 -                         // (zero length argument data)
 -                         break;
 - 
 -                     case ARRAY_END_TYPE_TAG:
 -                         --arrayLevel;
 -                         // (zero length argument data)
 -                         break;
 - 
 -                     case INT32_TYPE_TAG:
 -                     case FLOAT_TYPE_TAG:
 -                     case CHAR_TYPE_TAG:
 -                     case RGBA_COLOR_TYPE_TAG:
 -                     case MIDI_MESSAGE_TYPE_TAG:
 - 
 -                         if( argument == end )
 -                             throw MalformedMessageException( "arguments exceed message size" );
 -                         argument += 4;
 -                         if( argument > end )
 -                             throw MalformedMessageException( "arguments exceed message size" );
 -                         break;
 - 
 -                     case INT64_TYPE_TAG:
 -                     case TIME_TAG_TYPE_TAG:
 -                     case DOUBLE_TYPE_TAG:
 - 
 -                         if( argument == end )
 -                             throw MalformedMessageException( "arguments exceed message size" );
 -                         argument += 8;
 -                         if( argument > end )
 -                             throw MalformedMessageException( "arguments exceed message size" );
 -                         break;
 - 
 -                     case STRING_TYPE_TAG: 
 -                     case SYMBOL_TYPE_TAG:
 -                     
 -                         if( argument == end )
 -                             throw MalformedMessageException( "arguments exceed message size" );
 -                         argument = FindStr4End( argument, end );
 -                         if( argument == 0 )
 -                             throw MalformedMessageException( "unterminated string argument" );
 -                         break;
 - 
 -                     case BLOB_TYPE_TAG:
 -                         {
 -                             if( argument + osc::OSC_SIZEOF_INT32 > end )
 -                                 MalformedMessageException( "arguments exceed message size" );
 -                                 
 -                             // 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" );
 -                         }
 -                         break;
 -                         
 -                     default:
 -                         throw MalformedMessageException( "unknown type tag" );
 -                 }
 - 
 -             }while( *++typeTag != '\0' );
 -             typeTagsEnd_ = typeTag;
 - 
 -             if( arrayLevel !=  0 )
 -                 throw MalformedMessageException( "array was not terminated before end of message (expected ']' end of array tag)" );
 -         }
 - 
 -         // These invariants should be guaranteed by the above code.
 -         // we depend on them in the implementation of ArgumentCount()
 - #ifndef NDEBUG
 -         std::ptrdiff_t argumentCount = typeTagsEnd_ - typeTagsBegin_;
 -         assert( argumentCount >= 0 );
 -         assert( argumentCount <= OSC_INT32_MAX );
 - #endif
 -     }
 - }
 - 
 - //------------------------------------------------------------------------------
 - 
 - ReceivedBundle::ReceivedBundle( const ReceivedPacket& packet )
 -     : elementCount_( 0 )
 - {
 -     Init( packet.Contents(), packet.Size() );
 - }
 - 
 - 
 - ReceivedBundle::ReceivedBundle( const ReceivedBundleElement& bundleElement )
 -     : elementCount_( 0 )
 - {
 -     Init( bundleElement.Contents(), bundleElement.Size() );
 - }
 - 
 - 
 - void ReceivedBundle::Init( const char *bundle, osc_bundle_element_size_t size )
 - {
 - 
 -     if( !IsValidElementSizeValue(size) )
 -         throw MalformedBundleException( "invalid bundle size" );
 - 
 -     if( size < 16 )
 -         throw MalformedBundleException( "packet too short for bundle" );
 - 
 -     if( !IsMultipleOf4(size) )
 -         throw MalformedBundleException( "bundle size must be multiple of four" );
 - 
 -     if( bundle[0] != '#'
 -         || bundle[1] != 'b'
 -         || bundle[2] != 'u'
 -         || bundle[3] != 'n'
 -         || bundle[4] != 'd'
 -         || bundle[5] != 'l'
 -         || bundle[6] != 'e'
 -         || bundle[7] != '\0' )
 -             throw MalformedBundleException( "bad bundle address pattern" );    
 - 
 -     end_ = bundle + size;
 - 
 -     timeTag_ = bundle + 8;
 - 
 -     const char *p = timeTag_ + 8;
 -         
 -     while( p < end_ ){
 -         if( p + osc::OSC_SIZEOF_INT32 > end_ )
 -             throw MalformedBundleException( "packet too short for elementSize" );
 - 
 -         // 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" );
 - 
 -         p += osc::OSC_SIZEOF_INT32 + elementSize;
 -         if( p > end_ )
 -             throw MalformedBundleException( "packet too short for bundle element" );
 - 
 -         ++elementCount_;
 -     }
 - 
 -     if( p != end_ )
 -         throw MalformedBundleException( "bundle contents " );
 - }
 - 
 - 
 - uint64 ReceivedBundle::TimeTag() const
 - {
 -     return ToUInt64( timeTag_ );
 - }
 - 
 - 
 - } // namespace osc
 
 
  |