annotate external/oscpack/osc/OscOutboundPacketStream.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 "OscOutboundPacketStream.h"
tomwalters@509 31
tomwalters@509 32 #include <string.h>
tomwalters@509 33 #include <stdlib.h>
tomwalters@509 34 #include <assert.h>
tomwalters@509 35
tomwalters@509 36 #if defined(__WIN32__) || defined(WIN32)
tomwalters@509 37 #include <malloc.h> // for alloca
tomwalters@509 38 #endif
tomwalters@509 39
tomwalters@509 40 #include "OscHostEndianness.h"
tomwalters@509 41
tomwalters@509 42
tomwalters@509 43 namespace osc{
tomwalters@509 44
tomwalters@509 45 static void FromInt32( char *p, int32 x )
tomwalters@509 46 {
tomwalters@509 47 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 48 union{
tomwalters@509 49 osc::int32 i;
tomwalters@509 50 char c[4];
tomwalters@509 51 } u;
tomwalters@509 52
tomwalters@509 53 u.i = x;
tomwalters@509 54
tomwalters@509 55 p[3] = u.c[0];
tomwalters@509 56 p[2] = u.c[1];
tomwalters@509 57 p[1] = u.c[2];
tomwalters@509 58 p[0] = u.c[3];
tomwalters@509 59 #else
tomwalters@509 60 *reinterpret_cast<int32*>(p) = x;
tomwalters@509 61 #endif
tomwalters@509 62 }
tomwalters@509 63
tomwalters@509 64
tomwalters@509 65 static void FromUInt32( char *p, uint32 x )
tomwalters@509 66 {
tomwalters@509 67 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 68 union{
tomwalters@509 69 osc::uint32 i;
tomwalters@509 70 char c[4];
tomwalters@509 71 } u;
tomwalters@509 72
tomwalters@509 73 u.i = x;
tomwalters@509 74
tomwalters@509 75 p[3] = u.c[0];
tomwalters@509 76 p[2] = u.c[1];
tomwalters@509 77 p[1] = u.c[2];
tomwalters@509 78 p[0] = u.c[3];
tomwalters@509 79 #else
tomwalters@509 80 *reinterpret_cast<uint32*>(p) = x;
tomwalters@509 81 #endif
tomwalters@509 82 }
tomwalters@509 83
tomwalters@509 84
tomwalters@509 85 static void FromInt64( char *p, int64 x )
tomwalters@509 86 {
tomwalters@509 87 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 88 union{
tomwalters@509 89 osc::int64 i;
tomwalters@509 90 char c[8];
tomwalters@509 91 } u;
tomwalters@509 92
tomwalters@509 93 u.i = x;
tomwalters@509 94
tomwalters@509 95 p[7] = u.c[0];
tomwalters@509 96 p[6] = u.c[1];
tomwalters@509 97 p[5] = u.c[2];
tomwalters@509 98 p[4] = u.c[3];
tomwalters@509 99 p[3] = u.c[4];
tomwalters@509 100 p[2] = u.c[5];
tomwalters@509 101 p[1] = u.c[6];
tomwalters@509 102 p[0] = u.c[7];
tomwalters@509 103 #else
tomwalters@509 104 *reinterpret_cast<int64*>(p) = x;
tomwalters@509 105 #endif
tomwalters@509 106 }
tomwalters@509 107
tomwalters@509 108
tomwalters@509 109 static void FromUInt64( char *p, uint64 x )
tomwalters@509 110 {
tomwalters@509 111 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 112 union{
tomwalters@509 113 osc::uint64 i;
tomwalters@509 114 char c[8];
tomwalters@509 115 } u;
tomwalters@509 116
tomwalters@509 117 u.i = x;
tomwalters@509 118
tomwalters@509 119 p[7] = u.c[0];
tomwalters@509 120 p[6] = u.c[1];
tomwalters@509 121 p[5] = u.c[2];
tomwalters@509 122 p[4] = u.c[3];
tomwalters@509 123 p[3] = u.c[4];
tomwalters@509 124 p[2] = u.c[5];
tomwalters@509 125 p[1] = u.c[6];
tomwalters@509 126 p[0] = u.c[7];
tomwalters@509 127 #else
tomwalters@509 128 *reinterpret_cast<uint64*>(p) = x;
tomwalters@509 129 #endif
tomwalters@509 130 }
tomwalters@509 131
tomwalters@509 132
tomwalters@509 133 static inline long RoundUp4( long x )
tomwalters@509 134 {
tomwalters@509 135 return ((x-1) & (~0x03L)) + 4;
tomwalters@509 136 }
tomwalters@509 137
tomwalters@509 138
tomwalters@509 139 OutboundPacketStream::OutboundPacketStream( char *buffer, unsigned long capacity )
tomwalters@509 140 : data_( buffer )
tomwalters@509 141 , end_( data_ + capacity )
tomwalters@509 142 , typeTagsCurrent_( end_ )
tomwalters@509 143 , messageCursor_( data_ )
tomwalters@509 144 , argumentCurrent_( data_ )
tomwalters@509 145 , elementSizePtr_( 0 )
tomwalters@509 146 , messageIsInProgress_( false )
tomwalters@509 147 {
tomwalters@509 148
tomwalters@509 149 }
tomwalters@509 150
tomwalters@509 151
tomwalters@509 152 OutboundPacketStream::~OutboundPacketStream()
tomwalters@509 153 {
tomwalters@509 154
tomwalters@509 155 }
tomwalters@509 156
tomwalters@509 157
tomwalters@509 158 char *OutboundPacketStream::BeginElement( char *beginPtr )
tomwalters@509 159 {
tomwalters@509 160 if( elementSizePtr_ == 0 ){
tomwalters@509 161
tomwalters@509 162 elementSizePtr_ = reinterpret_cast<uint32*>(data_);
tomwalters@509 163
tomwalters@509 164 return beginPtr;
tomwalters@509 165
tomwalters@509 166 }else{
tomwalters@509 167 // store an offset to the old element size ptr in the element size slot
tomwalters@509 168 // we store an offset rather than the actual pointer to be 64 bit clean.
tomwalters@509 169 *reinterpret_cast<uint32*>(beginPtr) =
tomwalters@509 170 (uint32)(reinterpret_cast<char*>(elementSizePtr_) - data_);
tomwalters@509 171
tomwalters@509 172 elementSizePtr_ = reinterpret_cast<uint32*>(beginPtr);
tomwalters@509 173
tomwalters@509 174 return beginPtr + 4;
tomwalters@509 175 }
tomwalters@509 176 }
tomwalters@509 177
tomwalters@509 178
tomwalters@509 179 void OutboundPacketStream::EndElement( char *endPtr )
tomwalters@509 180 {
tomwalters@509 181 assert( elementSizePtr_ != 0 );
tomwalters@509 182
tomwalters@509 183 if( elementSizePtr_ == reinterpret_cast<uint32*>(data_) ){
tomwalters@509 184
tomwalters@509 185 elementSizePtr_ = 0;
tomwalters@509 186
tomwalters@509 187 }else{
tomwalters@509 188 // while building an element, an offset to the containing element's
tomwalters@509 189 // size slot is stored in the elements size slot (or a ptr to data_
tomwalters@509 190 // if there is no containing element). We retrieve that here
tomwalters@509 191 uint32 *previousElementSizePtr =
tomwalters@509 192 (uint32*)(data_ + *reinterpret_cast<uint32*>(elementSizePtr_));
tomwalters@509 193
tomwalters@509 194 // then we store the element size in the slot, note that the element
tomwalters@509 195 // size does not include the size slot, hence the - 4 below.
tomwalters@509 196 uint32 elementSize =
tomwalters@509 197 (endPtr - reinterpret_cast<char*>(elementSizePtr_)) - 4;
tomwalters@509 198 FromUInt32( reinterpret_cast<char*>(elementSizePtr_), elementSize );
tomwalters@509 199
tomwalters@509 200 // finally, we reset the element size ptr to the containing element
tomwalters@509 201 elementSizePtr_ = previousElementSizePtr;
tomwalters@509 202 }
tomwalters@509 203 }
tomwalters@509 204
tomwalters@509 205
tomwalters@509 206 bool OutboundPacketStream::ElementSizeSlotRequired() const
tomwalters@509 207 {
tomwalters@509 208 return (elementSizePtr_ != 0);
tomwalters@509 209 }
tomwalters@509 210
tomwalters@509 211
tomwalters@509 212 void OutboundPacketStream::CheckForAvailableBundleSpace()
tomwalters@509 213 {
tomwalters@509 214 unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0) + 16;
tomwalters@509 215
tomwalters@509 216 if( required > Capacity() )
tomwalters@509 217 throw OutOfBufferMemoryException();
tomwalters@509 218 }
tomwalters@509 219
tomwalters@509 220
tomwalters@509 221 void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern )
tomwalters@509 222 {
tomwalters@509 223 // plus 4 for at least four bytes of type tag
tomwalters@509 224 unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0)
tomwalters@509 225 + RoundUp4(strlen(addressPattern) + 1) + 4;
tomwalters@509 226
tomwalters@509 227 if( required > Capacity() )
tomwalters@509 228 throw OutOfBufferMemoryException();
tomwalters@509 229 }
tomwalters@509 230
tomwalters@509 231
tomwalters@509 232 void OutboundPacketStream::CheckForAvailableArgumentSpace( long argumentLength )
tomwalters@509 233 {
tomwalters@509 234 // plus three for extra type tag, comma and null terminator
tomwalters@509 235 unsigned long required = (argumentCurrent_ - data_) + argumentLength
tomwalters@509 236 + RoundUp4( (end_ - typeTagsCurrent_) + 3 );
tomwalters@509 237
tomwalters@509 238 if( required > Capacity() )
tomwalters@509 239 throw OutOfBufferMemoryException();
tomwalters@509 240 }
tomwalters@509 241
tomwalters@509 242
tomwalters@509 243 void OutboundPacketStream::Clear()
tomwalters@509 244 {
tomwalters@509 245 typeTagsCurrent_ = end_;
tomwalters@509 246 messageCursor_ = data_;
tomwalters@509 247 argumentCurrent_ = data_;
tomwalters@509 248 elementSizePtr_ = 0;
tomwalters@509 249 messageIsInProgress_ = false;
tomwalters@509 250 }
tomwalters@509 251
tomwalters@509 252
tomwalters@509 253 unsigned int OutboundPacketStream::Capacity() const
tomwalters@509 254 {
tomwalters@509 255 return end_ - data_;
tomwalters@509 256 }
tomwalters@509 257
tomwalters@509 258
tomwalters@509 259 unsigned int OutboundPacketStream::Size() const
tomwalters@509 260 {
tomwalters@509 261 unsigned int result = argumentCurrent_ - data_;
tomwalters@509 262 if( IsMessageInProgress() ){
tomwalters@509 263 // account for the length of the type tag string. the total type tag
tomwalters@509 264 // includes an initial comma, plus at least one terminating \0
tomwalters@509 265 result += RoundUp4( (end_ - typeTagsCurrent_) + 2 );
tomwalters@509 266 }
tomwalters@509 267
tomwalters@509 268 return result;
tomwalters@509 269 }
tomwalters@509 270
tomwalters@509 271
tomwalters@509 272 const char *OutboundPacketStream::Data() const
tomwalters@509 273 {
tomwalters@509 274 return data_;
tomwalters@509 275 }
tomwalters@509 276
tomwalters@509 277
tomwalters@509 278 bool OutboundPacketStream::IsReady() const
tomwalters@509 279 {
tomwalters@509 280 return (!IsMessageInProgress() && !IsBundleInProgress());
tomwalters@509 281 }
tomwalters@509 282
tomwalters@509 283
tomwalters@509 284 bool OutboundPacketStream::IsMessageInProgress() const
tomwalters@509 285 {
tomwalters@509 286 return messageIsInProgress_;
tomwalters@509 287 }
tomwalters@509 288
tomwalters@509 289
tomwalters@509 290 bool OutboundPacketStream::IsBundleInProgress() const
tomwalters@509 291 {
tomwalters@509 292 return (elementSizePtr_ != 0);
tomwalters@509 293 }
tomwalters@509 294
tomwalters@509 295
tomwalters@509 296 OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs )
tomwalters@509 297 {
tomwalters@509 298 if( IsMessageInProgress() )
tomwalters@509 299 throw MessageInProgressException();
tomwalters@509 300
tomwalters@509 301 CheckForAvailableBundleSpace();
tomwalters@509 302
tomwalters@509 303 messageCursor_ = BeginElement( messageCursor_ );
tomwalters@509 304
tomwalters@509 305 memcpy( messageCursor_, "#bundle\0", 8 );
tomwalters@509 306 FromUInt64( messageCursor_ + 8, rhs.timeTag );
tomwalters@509 307
tomwalters@509 308 messageCursor_ += 16;
tomwalters@509 309 argumentCurrent_ = messageCursor_;
tomwalters@509 310
tomwalters@509 311 return *this;
tomwalters@509 312 }
tomwalters@509 313
tomwalters@509 314
tomwalters@509 315 OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator& rhs )
tomwalters@509 316 {
tomwalters@509 317 (void) rhs;
tomwalters@509 318
tomwalters@509 319 if( !IsBundleInProgress() )
tomwalters@509 320 throw BundleNotInProgressException();
tomwalters@509 321 if( IsMessageInProgress() )
tomwalters@509 322 throw MessageInProgressException();
tomwalters@509 323
tomwalters@509 324 EndElement( messageCursor_ );
tomwalters@509 325
tomwalters@509 326 return *this;
tomwalters@509 327 }
tomwalters@509 328
tomwalters@509 329
tomwalters@509 330 OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs )
tomwalters@509 331 {
tomwalters@509 332 if( IsMessageInProgress() )
tomwalters@509 333 throw MessageInProgressException();
tomwalters@509 334
tomwalters@509 335 CheckForAvailableMessageSpace( rhs.addressPattern );
tomwalters@509 336
tomwalters@509 337 messageCursor_ = BeginElement( messageCursor_ );
tomwalters@509 338
tomwalters@509 339 strcpy( messageCursor_, rhs.addressPattern );
tomwalters@509 340 unsigned long rhsLength = strlen(rhs.addressPattern);
tomwalters@509 341 messageCursor_ += rhsLength + 1;
tomwalters@509 342
tomwalters@509 343 // zero pad to 4-byte boundary
tomwalters@509 344 unsigned long i = rhsLength + 1;
tomwalters@509 345 while( i & 0x3 ){
tomwalters@509 346 *messageCursor_++ = '\0';
tomwalters@509 347 ++i;
tomwalters@509 348 }
tomwalters@509 349
tomwalters@509 350 argumentCurrent_ = messageCursor_;
tomwalters@509 351 typeTagsCurrent_ = end_;
tomwalters@509 352
tomwalters@509 353 messageIsInProgress_ = true;
tomwalters@509 354
tomwalters@509 355 return *this;
tomwalters@509 356 }
tomwalters@509 357
tomwalters@509 358
tomwalters@509 359 OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& rhs )
tomwalters@509 360 {
tomwalters@509 361 (void) rhs;
tomwalters@509 362
tomwalters@509 363 if( !IsMessageInProgress() )
tomwalters@509 364 throw MessageNotInProgressException();
tomwalters@509 365
tomwalters@509 366 int typeTagsCount = end_ - typeTagsCurrent_;
tomwalters@509 367
tomwalters@509 368 if( typeTagsCount ){
tomwalters@509 369
tomwalters@509 370 char *tempTypeTags = (char*)alloca(typeTagsCount);
tomwalters@509 371 memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount );
tomwalters@509 372
tomwalters@509 373 // slot size includes comma and null terminator
tomwalters@509 374 int typeTagSlotSize = RoundUp4( typeTagsCount + 2 );
tomwalters@509 375
tomwalters@509 376 uint32 argumentsSize = argumentCurrent_ - messageCursor_;
tomwalters@509 377
tomwalters@509 378 memmove( messageCursor_ + typeTagSlotSize, messageCursor_, argumentsSize );
tomwalters@509 379
tomwalters@509 380 messageCursor_[0] = ',';
tomwalters@509 381 // copy type tags in reverse (really forward) order
tomwalters@509 382 for( int i=0; i < typeTagsCount; ++i )
tomwalters@509 383 messageCursor_[i+1] = tempTypeTags[ (typeTagsCount-1) - i ];
tomwalters@509 384
tomwalters@509 385 char *p = messageCursor_ + 1 + typeTagsCount;
tomwalters@509 386 for( int i=0; i < (typeTagSlotSize - (typeTagsCount + 1)); ++i )
tomwalters@509 387 *p++ = '\0';
tomwalters@509 388
tomwalters@509 389 typeTagsCurrent_ = end_;
tomwalters@509 390
tomwalters@509 391 // advance messageCursor_ for next message
tomwalters@509 392 messageCursor_ += typeTagSlotSize + argumentsSize;
tomwalters@509 393
tomwalters@509 394 }else{
tomwalters@509 395 // send an empty type tags string
tomwalters@509 396 memcpy( messageCursor_, ",\0\0\0", 4 );
tomwalters@509 397
tomwalters@509 398 // advance messageCursor_ for next message
tomwalters@509 399 messageCursor_ += 4;
tomwalters@509 400 }
tomwalters@509 401
tomwalters@509 402 argumentCurrent_ = messageCursor_;
tomwalters@509 403
tomwalters@509 404 EndElement( messageCursor_ );
tomwalters@509 405
tomwalters@509 406 messageIsInProgress_ = false;
tomwalters@509 407
tomwalters@509 408 return *this;
tomwalters@509 409 }
tomwalters@509 410
tomwalters@509 411
tomwalters@509 412 OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs )
tomwalters@509 413 {
tomwalters@509 414 CheckForAvailableArgumentSpace(0);
tomwalters@509 415
tomwalters@509 416 *(--typeTagsCurrent_) = (char)((rhs) ? TRUE_TYPE_TAG : FALSE_TYPE_TAG);
tomwalters@509 417
tomwalters@509 418 return *this;
tomwalters@509 419 }
tomwalters@509 420
tomwalters@509 421
tomwalters@509 422 OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs )
tomwalters@509 423 {
tomwalters@509 424 (void) rhs;
tomwalters@509 425 CheckForAvailableArgumentSpace(0);
tomwalters@509 426
tomwalters@509 427 *(--typeTagsCurrent_) = NIL_TYPE_TAG;
tomwalters@509 428
tomwalters@509 429 return *this;
tomwalters@509 430 }
tomwalters@509 431
tomwalters@509 432
tomwalters@509 433 OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs )
tomwalters@509 434 {
tomwalters@509 435 (void) rhs;
tomwalters@509 436 CheckForAvailableArgumentSpace(0);
tomwalters@509 437
tomwalters@509 438 *(--typeTagsCurrent_) = INFINITUM_TYPE_TAG;
tomwalters@509 439
tomwalters@509 440 return *this;
tomwalters@509 441 }
tomwalters@509 442
tomwalters@509 443
tomwalters@509 444 OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs )
tomwalters@509 445 {
tomwalters@509 446 CheckForAvailableArgumentSpace(4);
tomwalters@509 447
tomwalters@509 448 *(--typeTagsCurrent_) = INT32_TYPE_TAG;
tomwalters@509 449 FromInt32( argumentCurrent_, rhs );
tomwalters@509 450 argumentCurrent_ += 4;
tomwalters@509 451
tomwalters@509 452 return *this;
tomwalters@509 453 }
tomwalters@509 454
tomwalters@509 455
tomwalters@509 456 OutboundPacketStream& OutboundPacketStream::operator<<( float rhs )
tomwalters@509 457 {
tomwalters@509 458 CheckForAvailableArgumentSpace(4);
tomwalters@509 459
tomwalters@509 460 *(--typeTagsCurrent_) = FLOAT_TYPE_TAG;
tomwalters@509 461
tomwalters@509 462 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 463 union{
tomwalters@509 464 float f;
tomwalters@509 465 char c[4];
tomwalters@509 466 } u;
tomwalters@509 467
tomwalters@509 468 u.f = rhs;
tomwalters@509 469
tomwalters@509 470 argumentCurrent_[3] = u.c[0];
tomwalters@509 471 argumentCurrent_[2] = u.c[1];
tomwalters@509 472 argumentCurrent_[1] = u.c[2];
tomwalters@509 473 argumentCurrent_[0] = u.c[3];
tomwalters@509 474 #else
tomwalters@509 475 *reinterpret_cast<float*>(argumentCurrent_) = rhs;
tomwalters@509 476 #endif
tomwalters@509 477
tomwalters@509 478 argumentCurrent_ += 4;
tomwalters@509 479
tomwalters@509 480 return *this;
tomwalters@509 481 }
tomwalters@509 482
tomwalters@509 483
tomwalters@509 484 OutboundPacketStream& OutboundPacketStream::operator<<( char rhs )
tomwalters@509 485 {
tomwalters@509 486 CheckForAvailableArgumentSpace(4);
tomwalters@509 487
tomwalters@509 488 *(--typeTagsCurrent_) = CHAR_TYPE_TAG;
tomwalters@509 489 FromInt32( argumentCurrent_, rhs );
tomwalters@509 490 argumentCurrent_ += 4;
tomwalters@509 491
tomwalters@509 492 return *this;
tomwalters@509 493 }
tomwalters@509 494
tomwalters@509 495
tomwalters@509 496 OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs )
tomwalters@509 497 {
tomwalters@509 498 CheckForAvailableArgumentSpace(4);
tomwalters@509 499
tomwalters@509 500 *(--typeTagsCurrent_) = RGBA_COLOR_TYPE_TAG;
tomwalters@509 501 FromUInt32( argumentCurrent_, rhs );
tomwalters@509 502 argumentCurrent_ += 4;
tomwalters@509 503
tomwalters@509 504 return *this;
tomwalters@509 505 }
tomwalters@509 506
tomwalters@509 507
tomwalters@509 508 OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs )
tomwalters@509 509 {
tomwalters@509 510 CheckForAvailableArgumentSpace(4);
tomwalters@509 511
tomwalters@509 512 *(--typeTagsCurrent_) = MIDI_MESSAGE_TYPE_TAG;
tomwalters@509 513 FromUInt32( argumentCurrent_, rhs );
tomwalters@509 514 argumentCurrent_ += 4;
tomwalters@509 515
tomwalters@509 516 return *this;
tomwalters@509 517 }
tomwalters@509 518
tomwalters@509 519
tomwalters@509 520 OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs )
tomwalters@509 521 {
tomwalters@509 522 CheckForAvailableArgumentSpace(8);
tomwalters@509 523
tomwalters@509 524 *(--typeTagsCurrent_) = INT64_TYPE_TAG;
tomwalters@509 525 FromInt64( argumentCurrent_, rhs );
tomwalters@509 526 argumentCurrent_ += 8;
tomwalters@509 527
tomwalters@509 528 return *this;
tomwalters@509 529 }
tomwalters@509 530
tomwalters@509 531
tomwalters@509 532 OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs )
tomwalters@509 533 {
tomwalters@509 534 CheckForAvailableArgumentSpace(8);
tomwalters@509 535
tomwalters@509 536 *(--typeTagsCurrent_) = TIME_TAG_TYPE_TAG;
tomwalters@509 537 FromUInt64( argumentCurrent_, rhs );
tomwalters@509 538 argumentCurrent_ += 8;
tomwalters@509 539
tomwalters@509 540 return *this;
tomwalters@509 541 }
tomwalters@509 542
tomwalters@509 543
tomwalters@509 544 OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )
tomwalters@509 545 {
tomwalters@509 546 CheckForAvailableArgumentSpace(8);
tomwalters@509 547
tomwalters@509 548 *(--typeTagsCurrent_) = DOUBLE_TYPE_TAG;
tomwalters@509 549
tomwalters@509 550 #ifdef OSC_HOST_LITTLE_ENDIAN
tomwalters@509 551 union{
tomwalters@509 552 double f;
tomwalters@509 553 char c[8];
tomwalters@509 554 } u;
tomwalters@509 555
tomwalters@509 556 u.f = rhs;
tomwalters@509 557
tomwalters@509 558 argumentCurrent_[7] = u.c[0];
tomwalters@509 559 argumentCurrent_[6] = u.c[1];
tomwalters@509 560 argumentCurrent_[5] = u.c[2];
tomwalters@509 561 argumentCurrent_[4] = u.c[3];
tomwalters@509 562 argumentCurrent_[3] = u.c[4];
tomwalters@509 563 argumentCurrent_[2] = u.c[5];
tomwalters@509 564 argumentCurrent_[1] = u.c[6];
tomwalters@509 565 argumentCurrent_[0] = u.c[7];
tomwalters@509 566 #else
tomwalters@509 567 *reinterpret_cast<double*>(argumentCurrent_) = rhs;
tomwalters@509 568 #endif
tomwalters@509 569
tomwalters@509 570 argumentCurrent_ += 8;
tomwalters@509 571
tomwalters@509 572 return *this;
tomwalters@509 573 }
tomwalters@509 574
tomwalters@509 575
tomwalters@509 576 OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )
tomwalters@509 577 {
tomwalters@509 578 CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) );
tomwalters@509 579
tomwalters@509 580 *(--typeTagsCurrent_) = STRING_TYPE_TAG;
tomwalters@509 581 strcpy( argumentCurrent_, rhs );
tomwalters@509 582 unsigned long rhsLength = strlen(rhs);
tomwalters@509 583 argumentCurrent_ += rhsLength + 1;
tomwalters@509 584
tomwalters@509 585 // zero pad to 4-byte boundary
tomwalters@509 586 unsigned long i = rhsLength + 1;
tomwalters@509 587 while( i & 0x3 ){
tomwalters@509 588 *argumentCurrent_++ = '\0';
tomwalters@509 589 ++i;
tomwalters@509 590 }
tomwalters@509 591
tomwalters@509 592 return *this;
tomwalters@509 593 }
tomwalters@509 594
tomwalters@509 595
tomwalters@509 596 OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs )
tomwalters@509 597 {
tomwalters@509 598 CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) );
tomwalters@509 599
tomwalters@509 600 *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG;
tomwalters@509 601 strcpy( argumentCurrent_, rhs );
tomwalters@509 602 unsigned long rhsLength = strlen(rhs);
tomwalters@509 603 argumentCurrent_ += rhsLength + 1;
tomwalters@509 604
tomwalters@509 605 // zero pad to 4-byte boundary
tomwalters@509 606 unsigned long i = rhsLength + 1;
tomwalters@509 607 while( i & 0x3 ){
tomwalters@509 608 *argumentCurrent_++ = '\0';
tomwalters@509 609 ++i;
tomwalters@509 610 }
tomwalters@509 611
tomwalters@509 612 return *this;
tomwalters@509 613 }
tomwalters@509 614
tomwalters@509 615
tomwalters@509 616 OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )
tomwalters@509 617 {
tomwalters@509 618 CheckForAvailableArgumentSpace( 4 + RoundUp4(rhs.size) );
tomwalters@509 619
tomwalters@509 620 *(--typeTagsCurrent_) = BLOB_TYPE_TAG;
tomwalters@509 621 FromUInt32( argumentCurrent_, rhs.size );
tomwalters@509 622 argumentCurrent_ += 4;
tomwalters@509 623
tomwalters@509 624 memcpy( argumentCurrent_, rhs.data, rhs.size );
tomwalters@509 625 argumentCurrent_ += rhs.size;
tomwalters@509 626
tomwalters@509 627 // zero pad to 4-byte boundary
tomwalters@509 628 unsigned long i = rhs.size;
tomwalters@509 629 while( i & 0x3 ){
tomwalters@509 630 *argumentCurrent_++ = '\0';
tomwalters@509 631 ++i;
tomwalters@509 632 }
tomwalters@509 633
tomwalters@509 634 return *this;
tomwalters@509 635 }
tomwalters@509 636
tomwalters@509 637 } // namespace osc
tomwalters@509 638
tomwalters@509 639