annotate external/oscpack/osc/OscReceivedElements.cpp @ 648:1c2a5868f23a

Fix memory leak in CARFAC. Also get rid of most uses of auto, which tend to hurt readability unless the type name is particularly long, especially when it masks pointers.
author ronw@google.com
date Tue, 11 Jun 2013 21:41:53 +0000
parents 0284d2152e17
children
rev   line source
tomwalters@509 1 /*
tomwalters@509 2 oscpack -- Open Sound Control packet manipulation library
tomwalters@509 3 http://www.audiomulch.com/~rossb/oscpack
tomwalters@509 4
tomwalters@509 5 Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>
tomwalters@509 6
tomwalters@509 7 Permission is hereby granted, free of charge, to any person obtaining
tomwalters@509 8 a copy of this software and associated documentation files
tomwalters@509 9 (the "Software"), to deal in the Software without restriction,
tomwalters@509 10 including without limitation the rights to use, copy, modify, merge,
tomwalters@509 11 publish, distribute, sublicense, and/or sell copies of the Software,
tomwalters@509 12 and to permit persons to whom the Software is furnished to do so,
tomwalters@509 13 subject to the following conditions:
tomwalters@509 14
tomwalters@509 15 The above copyright notice and this permission notice shall be
tomwalters@509 16 included in all copies or substantial portions of the Software.
tomwalters@509 17
tomwalters@509 18 Any person wishing to distribute modifications to the Software is
tomwalters@509 19 requested to send the modifications to the original developer so that
tomwalters@509 20 they can be incorporated into the canonical version.
tomwalters@509 21
tomwalters@509 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
tomwalters@509 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
tomwalters@509 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
tomwalters@509 25 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
tomwalters@509 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
tomwalters@509 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
tomwalters@509 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
tomwalters@509 29 */
tomwalters@509 30 #include "OscReceivedElements.h"
tomwalters@509 31
tomwalters@509 32 #include <cassert>
tomwalters@509 33
tomwalters@509 34 #include "OscHostEndianness.h"
tomwalters@509 35
tomwalters@509 36
tomwalters@509 37 namespace osc{
tomwalters@509 38
tomwalters@509 39
tomwalters@509 40 // return the first 4 byte boundary after the end of a str4
tomwalters@509 41 // be careful about calling this version if you don't know whether
tomwalters@509 42 // the string is terminated correctly.
tomwalters@509 43 static inline const char* FindStr4End( const char *p )
tomwalters@509 44 {
tomwalters@509 45 if( p[0] == '\0' ) // special case for SuperCollider integer address pattern
tomwalters@509 46 return p + 4;
tomwalters@509 47
tomwalters@509 48 p += 3;
tomwalters@509 49
tomwalters@509 50 while( *p )
tomwalters@509 51 p += 4;
tomwalters@509 52
tomwalters@509 53 return p + 1;
tomwalters@509 54 }
tomwalters@509 55
tomwalters@509 56
tomwalters@509 57 // return the first 4 byte boundary after the end of a str4
tomwalters@509 58 // returns 0 if p == end or if the string is unterminated
tomwalters@509 59 static inline const char* FindStr4End( const char *p, const char *end )
tomwalters@509 60 {
tomwalters@509 61 if( p >= end )
tomwalters@509 62 return 0;
tomwalters@509 63
tomwalters@509 64 if( p[0] == '\0' ) // special case for SuperCollider integer address pattern
tomwalters@509 65 return p + 4;
tomwalters@509 66
tomwalters@509 67 p += 3;
tomwalters@509 68 end -= 1;
tomwalters@509 69
tomwalters@509 70 while( p < end && *p )
tomwalters@509 71 p += 4;
tomwalters@509 72
tomwalters@509 73 if( *p )
tomwalters@509 74 return 0;
tomwalters@509 75 else
tomwalters@509 76 return p + 1;
tomwalters@509 77 }
tomwalters@509 78
tomwalters@509 79
tomwalters@509 80 static inline unsigned long RoundUp4( unsigned long x )
tomwalters@509 81 {
tomwalters@509 82 unsigned long remainder = x & 0x3UL;
tomwalters@509 83 if( remainder )
tomwalters@509 84 return x + (4 - remainder);
tomwalters@509 85 else
tomwalters@509 86 return x;
tomwalters@509 87 }
tomwalters@509 88
tomwalters@509 89
tomwalters@509 90 static inline int32 ToInt32( const char *p )
tomwalters@509 91 {
tomwalters@509 92 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 93 union{
tomwalters@509 94 osc::int32 i;
tomwalters@509 95 char c[4];
tomwalters@509 96 } u;
tomwalters@509 97
tomwalters@509 98 u.c[0] = p[3];
tomwalters@509 99 u.c[1] = p[2];
tomwalters@509 100 u.c[2] = p[1];
tomwalters@509 101 u.c[3] = p[0];
tomwalters@509 102
tomwalters@509 103 return u.i;
tomwalters@509 104 #else
tomwalters@509 105 return *(int32*)p;
tomwalters@509 106 #endif
tomwalters@509 107 }
tomwalters@509 108
tomwalters@509 109
tomwalters@509 110 static inline uint32 ToUInt32( const char *p )
tomwalters@509 111 {
tomwalters@509 112 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 113 union{
tomwalters@509 114 osc::uint32 i;
tomwalters@509 115 char c[4];
tomwalters@509 116 } u;
tomwalters@509 117
tomwalters@509 118 u.c[0] = p[3];
tomwalters@509 119 u.c[1] = p[2];
tomwalters@509 120 u.c[2] = p[1];
tomwalters@509 121 u.c[3] = p[0];
tomwalters@509 122
tomwalters@509 123 return u.i;
tomwalters@509 124 #else
tomwalters@509 125 return *(uint32*)p;
tomwalters@509 126 #endif
tomwalters@509 127 }
tomwalters@509 128
tomwalters@509 129
tomwalters@509 130 int64 ToInt64( const char *p )
tomwalters@509 131 {
tomwalters@509 132 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 133 union{
tomwalters@509 134 osc::int64 i;
tomwalters@509 135 char c[4];
tomwalters@509 136 } u;
tomwalters@509 137
tomwalters@509 138 u.c[0] = p[7];
tomwalters@509 139 u.c[1] = p[6];
tomwalters@509 140 u.c[2] = p[5];
tomwalters@509 141 u.c[3] = p[4];
tomwalters@509 142 u.c[4] = p[3];
tomwalters@509 143 u.c[5] = p[2];
tomwalters@509 144 u.c[6] = p[1];
tomwalters@509 145 u.c[7] = p[0];
tomwalters@509 146
tomwalters@509 147 return u.i;
tomwalters@509 148 #else
tomwalters@509 149 return *(int64*)p;
tomwalters@509 150 #endif
tomwalters@509 151 }
tomwalters@509 152
tomwalters@509 153
tomwalters@509 154 uint64 ToUInt64( const char *p )
tomwalters@509 155 {
tomwalters@509 156 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 157 union{
tomwalters@509 158 osc::uint64 i;
tomwalters@509 159 char c[4];
tomwalters@509 160 } u;
tomwalters@509 161
tomwalters@509 162 u.c[0] = p[7];
tomwalters@509 163 u.c[1] = p[6];
tomwalters@509 164 u.c[2] = p[5];
tomwalters@509 165 u.c[3] = p[4];
tomwalters@509 166 u.c[4] = p[3];
tomwalters@509 167 u.c[5] = p[2];
tomwalters@509 168 u.c[6] = p[1];
tomwalters@509 169 u.c[7] = p[0];
tomwalters@509 170
tomwalters@509 171 return u.i;
tomwalters@509 172 #else
tomwalters@509 173 return *(uint64*)p;
tomwalters@509 174 #endif
tomwalters@509 175 }
tomwalters@509 176
tomwalters@509 177 //------------------------------------------------------------------------------
tomwalters@509 178
tomwalters@509 179 bool ReceivedPacket::IsBundle() const
tomwalters@509 180 {
tomwalters@509 181 return (Size() > 0 && Contents()[0] == '#');
tomwalters@509 182 }
tomwalters@509 183
tomwalters@509 184 //------------------------------------------------------------------------------
tomwalters@509 185
tomwalters@509 186 bool ReceivedBundleElement::IsBundle() const
tomwalters@509 187 {
tomwalters@509 188 return (Size() > 0 && Contents()[0] == '#');
tomwalters@509 189 }
tomwalters@509 190
tomwalters@509 191
tomwalters@509 192 int32 ReceivedBundleElement::Size() const
tomwalters@509 193 {
tomwalters@509 194 return ToUInt32( size_ );
tomwalters@509 195 }
tomwalters@509 196
tomwalters@509 197 //------------------------------------------------------------------------------
tomwalters@509 198
tomwalters@509 199 bool ReceivedMessageArgument::AsBool() const
tomwalters@509 200 {
tomwalters@509 201 if( !typeTag_ )
tomwalters@509 202 throw MissingArgumentException();
tomwalters@509 203 else if( *typeTag_ == TRUE_TYPE_TAG )
tomwalters@509 204 return true;
tomwalters@509 205 else if( *typeTag_ == FALSE_TYPE_TAG )
tomwalters@509 206 return false;
tomwalters@509 207 else
tomwalters@509 208 throw WrongArgumentTypeException();
tomwalters@509 209 }
tomwalters@509 210
tomwalters@509 211
tomwalters@509 212 bool ReceivedMessageArgument::AsBoolUnchecked() const
tomwalters@509 213 {
tomwalters@509 214 if( !typeTag_ )
tomwalters@509 215 throw MissingArgumentException();
tomwalters@509 216 else if( *typeTag_ == TRUE_TYPE_TAG )
tomwalters@509 217 return true;
tomwalters@509 218 else
tomwalters@509 219 return false;
tomwalters@509 220 }
tomwalters@509 221
tomwalters@509 222
tomwalters@509 223 int32 ReceivedMessageArgument::AsInt32() const
tomwalters@509 224 {
tomwalters@509 225 if( !typeTag_ )
tomwalters@509 226 throw MissingArgumentException();
tomwalters@509 227 else if( *typeTag_ == INT32_TYPE_TAG )
tomwalters@509 228 return AsInt32Unchecked();
tomwalters@509 229 else
tomwalters@509 230 throw WrongArgumentTypeException();
tomwalters@509 231 }
tomwalters@509 232
tomwalters@509 233
tomwalters@509 234 int32 ReceivedMessageArgument::AsInt32Unchecked() const
tomwalters@509 235 {
tomwalters@509 236 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 237 union{
tomwalters@509 238 osc::int32 i;
tomwalters@509 239 char c[4];
tomwalters@509 240 } u;
tomwalters@509 241
tomwalters@509 242 u.c[0] = argument_[3];
tomwalters@509 243 u.c[1] = argument_[2];
tomwalters@509 244 u.c[2] = argument_[1];
tomwalters@509 245 u.c[3] = argument_[0];
tomwalters@509 246
tomwalters@509 247 return u.i;
tomwalters@509 248 #else
tomwalters@509 249 return *(int32*)argument_;
tomwalters@509 250 #endif
tomwalters@509 251 }
tomwalters@509 252
tomwalters@509 253
tomwalters@509 254 float ReceivedMessageArgument::AsFloat() const
tomwalters@509 255 {
tomwalters@509 256 if( !typeTag_ )
tomwalters@509 257 throw MissingArgumentException();
tomwalters@509 258 else if( *typeTag_ == FLOAT_TYPE_TAG )
tomwalters@509 259 return AsFloatUnchecked();
tomwalters@509 260 else
tomwalters@509 261 throw WrongArgumentTypeException();
tomwalters@509 262 }
tomwalters@509 263
tomwalters@509 264
tomwalters@509 265 float ReceivedMessageArgument::AsFloatUnchecked() const
tomwalters@509 266 {
tomwalters@509 267 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 268 union{
tomwalters@509 269 float f;
tomwalters@509 270 char c[4];
tomwalters@509 271 } u;
tomwalters@509 272
tomwalters@509 273 u.c[0] = argument_[3];
tomwalters@509 274 u.c[1] = argument_[2];
tomwalters@509 275 u.c[2] = argument_[1];
tomwalters@509 276 u.c[3] = argument_[0];
tomwalters@509 277
tomwalters@509 278 return u.f;
tomwalters@509 279 #else
tomwalters@509 280 return *(float*)argument_;
tomwalters@509 281 #endif
tomwalters@509 282 }
tomwalters@509 283
tomwalters@509 284
tomwalters@509 285 char ReceivedMessageArgument::AsChar() const
tomwalters@509 286 {
tomwalters@509 287 if( !typeTag_ )
tomwalters@509 288 throw MissingArgumentException();
tomwalters@509 289 else if( *typeTag_ == CHAR_TYPE_TAG )
tomwalters@509 290 return AsCharUnchecked();
tomwalters@509 291 else
tomwalters@509 292 throw WrongArgumentTypeException();
tomwalters@509 293 }
tomwalters@509 294
tomwalters@509 295
tomwalters@509 296 char ReceivedMessageArgument::AsCharUnchecked() const
tomwalters@509 297 {
tomwalters@509 298 return (char)ToInt32( argument_ );
tomwalters@509 299 }
tomwalters@509 300
tomwalters@509 301
tomwalters@509 302 uint32 ReceivedMessageArgument::AsRgbaColor() const
tomwalters@509 303 {
tomwalters@509 304 if( !typeTag_ )
tomwalters@509 305 throw MissingArgumentException();
tomwalters@509 306 else if( *typeTag_ == RGBA_COLOR_TYPE_TAG )
tomwalters@509 307 return AsRgbaColorUnchecked();
tomwalters@509 308 else
tomwalters@509 309 throw WrongArgumentTypeException();
tomwalters@509 310 }
tomwalters@509 311
tomwalters@509 312
tomwalters@509 313 uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const
tomwalters@509 314 {
tomwalters@509 315 return ToUInt32( argument_ );
tomwalters@509 316 }
tomwalters@509 317
tomwalters@509 318
tomwalters@509 319 uint32 ReceivedMessageArgument::AsMidiMessage() const
tomwalters@509 320 {
tomwalters@509 321 if( !typeTag_ )
tomwalters@509 322 throw MissingArgumentException();
tomwalters@509 323 else if( *typeTag_ == MIDI_MESSAGE_TYPE_TAG )
tomwalters@509 324 return AsMidiMessageUnchecked();
tomwalters@509 325 else
tomwalters@509 326 throw WrongArgumentTypeException();
tomwalters@509 327 }
tomwalters@509 328
tomwalters@509 329
tomwalters@509 330 uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const
tomwalters@509 331 {
tomwalters@509 332 return ToUInt32( argument_ );
tomwalters@509 333 }
tomwalters@509 334
tomwalters@509 335
tomwalters@509 336 int64 ReceivedMessageArgument::AsInt64() const
tomwalters@509 337 {
tomwalters@509 338 if( !typeTag_ )
tomwalters@509 339 throw MissingArgumentException();
tomwalters@509 340 else if( *typeTag_ == INT64_TYPE_TAG )
tomwalters@509 341 return AsInt64Unchecked();
tomwalters@509 342 else
tomwalters@509 343 throw WrongArgumentTypeException();
tomwalters@509 344 }
tomwalters@509 345
tomwalters@509 346
tomwalters@509 347 int64 ReceivedMessageArgument::AsInt64Unchecked() const
tomwalters@509 348 {
tomwalters@509 349 return ToInt64( argument_ );
tomwalters@509 350 }
tomwalters@509 351
tomwalters@509 352
tomwalters@509 353 uint64 ReceivedMessageArgument::AsTimeTag() const
tomwalters@509 354 {
tomwalters@509 355 if( !typeTag_ )
tomwalters@509 356 throw MissingArgumentException();
tomwalters@509 357 else if( *typeTag_ == TIME_TAG_TYPE_TAG )
tomwalters@509 358 return AsTimeTagUnchecked();
tomwalters@509 359 else
tomwalters@509 360 throw WrongArgumentTypeException();
tomwalters@509 361 }
tomwalters@509 362
tomwalters@509 363
tomwalters@509 364 uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const
tomwalters@509 365 {
tomwalters@509 366 return ToUInt64( argument_ );
tomwalters@509 367 }
tomwalters@509 368
tomwalters@509 369
tomwalters@509 370 double ReceivedMessageArgument::AsDouble() const
tomwalters@509 371 {
tomwalters@509 372 if( !typeTag_ )
tomwalters@509 373 throw MissingArgumentException();
tomwalters@509 374 else if( *typeTag_ == DOUBLE_TYPE_TAG )
tomwalters@509 375 return AsDoubleUnchecked();
tomwalters@509 376 else
tomwalters@509 377 throw WrongArgumentTypeException();
tomwalters@509 378 }
tomwalters@509 379
tomwalters@509 380
tomwalters@509 381 double ReceivedMessageArgument::AsDoubleUnchecked() const
tomwalters@509 382 {
tomwalters@509 383 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 384 union{
tomwalters@509 385 double d;
tomwalters@509 386 char c[8];
tomwalters@509 387 } u;
tomwalters@509 388
tomwalters@509 389 u.c[0] = argument_[7];
tomwalters@509 390 u.c[1] = argument_[6];
tomwalters@509 391 u.c[2] = argument_[5];
tomwalters@509 392 u.c[3] = argument_[4];
tomwalters@509 393 u.c[4] = argument_[3];
tomwalters@509 394 u.c[5] = argument_[2];
tomwalters@509 395 u.c[6] = argument_[1];
tomwalters@509 396 u.c[7] = argument_[0];
tomwalters@509 397
tomwalters@509 398 return u.d;
tomwalters@509 399 #else
tomwalters@509 400 return *(double*)argument_;
tomwalters@509 401 #endif
tomwalters@509 402 }
tomwalters@509 403
tomwalters@509 404
tomwalters@509 405 const char* ReceivedMessageArgument::AsString() const
tomwalters@509 406 {
tomwalters@509 407 if( !typeTag_ )
tomwalters@509 408 throw MissingArgumentException();
tomwalters@509 409 else if( *typeTag_ == STRING_TYPE_TAG )
tomwalters@509 410 return argument_;
tomwalters@509 411 else
tomwalters@509 412 throw WrongArgumentTypeException();
tomwalters@509 413 }
tomwalters@509 414
tomwalters@509 415
tomwalters@509 416 const char* ReceivedMessageArgument::AsSymbol() const
tomwalters@509 417 {
tomwalters@509 418 if( !typeTag_ )
tomwalters@509 419 throw MissingArgumentException();
tomwalters@509 420 else if( *typeTag_ == SYMBOL_TYPE_TAG )
tomwalters@509 421 return argument_;
tomwalters@509 422 else
tomwalters@509 423 throw WrongArgumentTypeException();
tomwalters@509 424 }
tomwalters@509 425
tomwalters@509 426
tomwalters@509 427 void ReceivedMessageArgument::AsBlob( const void*& data, unsigned long& size ) const
tomwalters@509 428 {
tomwalters@509 429 if( !typeTag_ )
tomwalters@509 430 throw MissingArgumentException();
tomwalters@509 431 else if( *typeTag_ == BLOB_TYPE_TAG )
tomwalters@509 432 AsBlobUnchecked( data, size );
tomwalters@509 433 else
tomwalters@509 434 throw WrongArgumentTypeException();
tomwalters@509 435 }
tomwalters@509 436
tomwalters@509 437
tomwalters@509 438 void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, unsigned long& size ) const
tomwalters@509 439 {
tomwalters@509 440 size = ToUInt32( argument_ );
tomwalters@509 441 data = (void*)(argument_+4);
tomwalters@509 442 }
tomwalters@509 443
tomwalters@509 444 //------------------------------------------------------------------------------
tomwalters@509 445
tomwalters@509 446 void ReceivedMessageArgumentIterator::Advance()
tomwalters@509 447 {
tomwalters@509 448 if( !value_.typeTag_ )
tomwalters@509 449 return;
tomwalters@509 450
tomwalters@509 451 switch( *value_.typeTag_++ ){
tomwalters@509 452 case '\0':
tomwalters@509 453 // don't advance past end
tomwalters@509 454 --value_.typeTag_;
tomwalters@509 455 break;
tomwalters@509 456
tomwalters@509 457 case TRUE_TYPE_TAG:
tomwalters@509 458 case FALSE_TYPE_TAG:
tomwalters@509 459 case NIL_TYPE_TAG:
tomwalters@509 460 case INFINITUM_TYPE_TAG:
tomwalters@509 461
tomwalters@509 462 // zero length
tomwalters@509 463 break;
tomwalters@509 464
tomwalters@509 465 case INT32_TYPE_TAG:
tomwalters@509 466 case FLOAT_TYPE_TAG:
tomwalters@509 467 case CHAR_TYPE_TAG:
tomwalters@509 468 case RGBA_COLOR_TYPE_TAG:
tomwalters@509 469 case MIDI_MESSAGE_TYPE_TAG:
tomwalters@509 470
tomwalters@509 471 value_.argument_ += 4;
tomwalters@509 472 break;
tomwalters@509 473
tomwalters@509 474 case INT64_TYPE_TAG:
tomwalters@509 475 case TIME_TAG_TYPE_TAG:
tomwalters@509 476 case DOUBLE_TYPE_TAG:
tomwalters@509 477
tomwalters@509 478 value_.argument_ += 8;
tomwalters@509 479 break;
tomwalters@509 480
tomwalters@509 481 case STRING_TYPE_TAG:
tomwalters@509 482 case SYMBOL_TYPE_TAG:
tomwalters@509 483
tomwalters@509 484 // we use the unsafe function FindStr4End(char*) here because all of
tomwalters@509 485 // the arguments have already been validated in
tomwalters@509 486 // ReceivedMessage::Init() below.
tomwalters@509 487
tomwalters@509 488 value_.argument_ = FindStr4End( value_.argument_ );
tomwalters@509 489 break;
tomwalters@509 490
tomwalters@509 491 case BLOB_TYPE_TAG:
tomwalters@509 492 {
tomwalters@509 493 uint32 blobSize = ToUInt32( value_.argument_ );
tomwalters@509 494 value_.argument_ = value_.argument_ + 4 + RoundUp4( blobSize );
tomwalters@509 495 }
tomwalters@509 496 break;
tomwalters@509 497
tomwalters@509 498 default: // unknown type tag
tomwalters@509 499 // don't advance
tomwalters@509 500 --value_.typeTag_;
tomwalters@509 501 break;
tomwalters@509 502
tomwalters@509 503
tomwalters@509 504 // not handled:
tomwalters@509 505 // [ Indicates the beginning of an array. The tags following are for
tomwalters@509 506 // data in the Array until a close brace tag is reached.
tomwalters@509 507 // ] Indicates the end of an array.
tomwalters@509 508 }
tomwalters@509 509 }
tomwalters@509 510
tomwalters@509 511 //------------------------------------------------------------------------------
tomwalters@509 512
tomwalters@509 513 ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet )
tomwalters@509 514 : addressPattern_( packet.Contents() )
tomwalters@509 515 {
tomwalters@509 516 Init( packet.Contents(), packet.Size() );
tomwalters@509 517 }
tomwalters@509 518
tomwalters@509 519
tomwalters@509 520 ReceivedMessage::ReceivedMessage( const ReceivedBundleElement& bundleElement )
tomwalters@509 521 : addressPattern_( bundleElement.Contents() )
tomwalters@509 522 {
tomwalters@509 523 Init( bundleElement.Contents(), bundleElement.Size() );
tomwalters@509 524 }
tomwalters@509 525
tomwalters@509 526
tomwalters@509 527 bool ReceivedMessage::AddressPatternIsUInt32() const
tomwalters@509 528 {
tomwalters@509 529 return (addressPattern_[0] == '\0');
tomwalters@509 530 }
tomwalters@509 531
tomwalters@509 532
tomwalters@509 533 uint32 ReceivedMessage::AddressPatternAsUInt32() const
tomwalters@509 534 {
tomwalters@509 535 return ToUInt32( addressPattern_ );
tomwalters@509 536 }
tomwalters@509 537
tomwalters@509 538
tomwalters@509 539 void ReceivedMessage::Init( const char *message, unsigned long size )
tomwalters@509 540 {
tomwalters@509 541 if( size == 0 )
tomwalters@509 542 throw MalformedMessageException( "zero length messages not permitted" );
tomwalters@509 543
tomwalters@509 544 if( (size & 0x03L) != 0 )
tomwalters@509 545 throw MalformedMessageException( "message size must be multiple of four" );
tomwalters@509 546
tomwalters@509 547 const char *end = message + size;
tomwalters@509 548
tomwalters@509 549 typeTagsBegin_ = FindStr4End( addressPattern_, end );
tomwalters@509 550 if( typeTagsBegin_ == 0 ){
tomwalters@509 551 // address pattern was not terminated before end
tomwalters@509 552 throw MalformedMessageException( "unterminated address pattern" );
tomwalters@509 553 }
tomwalters@509 554
tomwalters@509 555 if( typeTagsBegin_ == end ){
tomwalters@509 556 // message consists of only the address pattern - no arguments or type tags.
tomwalters@509 557 typeTagsBegin_ = 0;
tomwalters@509 558 typeTagsEnd_ = 0;
tomwalters@509 559 arguments_ = 0;
tomwalters@509 560
tomwalters@509 561 }else{
tomwalters@509 562 if( *typeTagsBegin_ != ',' )
tomwalters@509 563 throw MalformedMessageException( "type tags not present" );
tomwalters@509 564
tomwalters@509 565 if( *(typeTagsBegin_ + 1) == '\0' ){
tomwalters@509 566 // zero length type tags
tomwalters@509 567 typeTagsBegin_ = 0;
tomwalters@509 568 typeTagsEnd_ = 0;
tomwalters@509 569 arguments_ = 0;
tomwalters@509 570
tomwalters@509 571 }else{
tomwalters@509 572 // check that all arguments are present and well formed
tomwalters@509 573
tomwalters@509 574 arguments_ = FindStr4End( typeTagsBegin_, end );
tomwalters@509 575 if( arguments_ == 0 ){
tomwalters@509 576 throw MalformedMessageException( "type tags were not terminated before end of message" );
tomwalters@509 577 }
tomwalters@509 578
tomwalters@509 579 ++typeTagsBegin_; // advance past initial ','
tomwalters@509 580
tomwalters@509 581 const char *typeTag = typeTagsBegin_;
tomwalters@509 582 const char *argument = arguments_;
tomwalters@509 583
tomwalters@509 584 do{
tomwalters@509 585 switch( *typeTag ){
tomwalters@509 586 case TRUE_TYPE_TAG:
tomwalters@509 587 case FALSE_TYPE_TAG:
tomwalters@509 588 case NIL_TYPE_TAG:
tomwalters@509 589 case INFINITUM_TYPE_TAG:
tomwalters@509 590
tomwalters@509 591 // zero length
tomwalters@509 592 break;
tomwalters@509 593
tomwalters@509 594 case INT32_TYPE_TAG:
tomwalters@509 595 case FLOAT_TYPE_TAG:
tomwalters@509 596 case CHAR_TYPE_TAG:
tomwalters@509 597 case RGBA_COLOR_TYPE_TAG:
tomwalters@509 598 case MIDI_MESSAGE_TYPE_TAG:
tomwalters@509 599
tomwalters@509 600 if( argument == end )
tomwalters@509 601 throw MalformedMessageException( "arguments exceed message size" );
tomwalters@509 602 argument += 4;
tomwalters@509 603 if( argument > end )
tomwalters@509 604 throw MalformedMessageException( "arguments exceed message size" );
tomwalters@509 605 break;
tomwalters@509 606
tomwalters@509 607 case INT64_TYPE_TAG:
tomwalters@509 608 case TIME_TAG_TYPE_TAG:
tomwalters@509 609 case DOUBLE_TYPE_TAG:
tomwalters@509 610
tomwalters@509 611 if( argument == end )
tomwalters@509 612 throw MalformedMessageException( "arguments exceed message size" );
tomwalters@509 613 argument += 8;
tomwalters@509 614 if( argument > end )
tomwalters@509 615 throw MalformedMessageException( "arguments exceed message size" );
tomwalters@509 616 break;
tomwalters@509 617
tomwalters@509 618 case STRING_TYPE_TAG:
tomwalters@509 619 case SYMBOL_TYPE_TAG:
tomwalters@509 620
tomwalters@509 621 if( argument == end )
tomwalters@509 622 throw MalformedMessageException( "arguments exceed message size" );
tomwalters@509 623 argument = FindStr4End( argument, end );
tomwalters@509 624 if( argument == 0 )
tomwalters@509 625 throw MalformedMessageException( "unterminated string argument" );
tomwalters@509 626 break;
tomwalters@509 627
tomwalters@509 628 case BLOB_TYPE_TAG:
tomwalters@509 629 {
tomwalters@509 630 if( argument + 4 > end )
tomwalters@509 631 MalformedMessageException( "arguments exceed message size" );
tomwalters@509 632
tomwalters@509 633 uint32 blobSize = ToUInt32( argument );
tomwalters@509 634 argument = argument + 4 + RoundUp4( blobSize );
tomwalters@509 635 if( argument > end )
tomwalters@509 636 MalformedMessageException( "arguments exceed message size" );
tomwalters@509 637 }
tomwalters@509 638 break;
tomwalters@509 639
tomwalters@509 640 default:
tomwalters@509 641 throw MalformedMessageException( "unknown type tag" );
tomwalters@509 642
tomwalters@509 643 // not handled:
tomwalters@509 644 // [ Indicates the beginning of an array. The tags following are for
tomwalters@509 645 // data in the Array until a close brace tag is reached.
tomwalters@509 646 // ] Indicates the end of an array.
tomwalters@509 647 }
tomwalters@509 648
tomwalters@509 649 }while( *++typeTag != '\0' );
tomwalters@509 650 typeTagsEnd_ = typeTag;
tomwalters@509 651 }
tomwalters@509 652 }
tomwalters@509 653 }
tomwalters@509 654
tomwalters@509 655 //------------------------------------------------------------------------------
tomwalters@509 656
tomwalters@509 657 ReceivedBundle::ReceivedBundle( const ReceivedPacket& packet )
tomwalters@509 658 : elementCount_( 0 )
tomwalters@509 659 {
tomwalters@509 660 Init( packet.Contents(), packet.Size() );
tomwalters@509 661 }
tomwalters@509 662
tomwalters@509 663
tomwalters@509 664 ReceivedBundle::ReceivedBundle( const ReceivedBundleElement& bundleElement )
tomwalters@509 665 : elementCount_( 0 )
tomwalters@509 666 {
tomwalters@509 667 Init( bundleElement.Contents(), bundleElement.Size() );
tomwalters@509 668 }
tomwalters@509 669
tomwalters@509 670
tomwalters@509 671 void ReceivedBundle::Init( const char *bundle, unsigned long size )
tomwalters@509 672 {
tomwalters@509 673 if( size < 16 )
tomwalters@509 674 throw MalformedBundleException( "packet too short for bundle" );
tomwalters@509 675
tomwalters@509 676 if( (size & 0x03L) != 0 )
tomwalters@509 677 throw MalformedBundleException( "bundle size must be multiple of four" );
tomwalters@509 678
tomwalters@509 679 if( bundle[0] != '#'
tomwalters@509 680 || bundle[1] != 'b'
tomwalters@509 681 || bundle[2] != 'u'
tomwalters@509 682 || bundle[3] != 'n'
tomwalters@509 683 || bundle[4] != 'd'
tomwalters@509 684 || bundle[5] != 'l'
tomwalters@509 685 || bundle[6] != 'e'
tomwalters@509 686 || bundle[7] != '\0' )
tomwalters@509 687 throw MalformedBundleException( "bad bundle address pattern" );
tomwalters@509 688
tomwalters@509 689 end_ = bundle + size;
tomwalters@509 690
tomwalters@509 691 timeTag_ = bundle + 8;
tomwalters@509 692
tomwalters@509 693 const char *p = timeTag_ + 8;
tomwalters@509 694
tomwalters@509 695 while( p < end_ ){
tomwalters@509 696 if( p + 4 > end_ )
tomwalters@509 697 throw MalformedBundleException( "packet too short for elementSize" );
tomwalters@509 698
tomwalters@509 699 uint32 elementSize = ToUInt32( p );
tomwalters@509 700 if( (elementSize & 0x03L) != 0 )
tomwalters@509 701 throw MalformedBundleException( "bundle element size must be multiple of four" );
tomwalters@509 702
tomwalters@509 703 p += 4 + elementSize;
tomwalters@509 704 if( p > end_ )
tomwalters@509 705 throw MalformedBundleException( "packet too short for bundle element" );
tomwalters@509 706
tomwalters@509 707 ++elementCount_;
tomwalters@509 708 }
tomwalters@509 709
tomwalters@509 710 if( p != end_ )
tomwalters@509 711 throw MalformedBundleException( "bundle contents " );
tomwalters@509 712 }
tomwalters@509 713
tomwalters@509 714
tomwalters@509 715 uint64 ReceivedBundle::TimeTag() const
tomwalters@509 716 {
tomwalters@509 717 return ToUInt64( timeTag_ );
tomwalters@509 718 }
tomwalters@509 719
tomwalters@509 720
tomwalters@509 721 } // namespace osc
tomwalters@509 722