Jamoma API  0.6.0.a19
OscReceivedElements.h
1 /*
2  oscpack -- Open Sound Control (OSC) packet manipulation library
3  http://www.rossbencina.com/code/oscpack
4 
5  Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
6 
7  Permission is hereby granted, free of charge, to any person obtaining
8  a copy of this software and associated documentation files
9  (the "Software"), to deal in the Software without restriction,
10  including without limitation the rights to use, copy, modify, merge,
11  publish, distribute, sublicense, and/or sell copies of the Software,
12  and to permit persons to whom the Software is furnished to do so,
13  subject to the following conditions:
14 
15  The above copyright notice and this permission notice shall be
16  included in all copies or substantial portions of the Software.
17 
18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26 
27 /*
28  The text above constitutes the entire oscpack license; however,
29  the oscpack developer(s) also make the following non-binding requests:
30 
31  Any person wishing to distribute modifications to the Software is
32  requested to send the modifications to the original developer so that
33  they can be incorporated into the canonical version. It is also
34  requested that these non-binding requests be included whenever the
35  above license is reproduced.
36 */
37 #ifndef INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H
38 #define INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H
39 
40 #include <cassert>
41 #include <cstddef>
42 #include <cstring> // size_t
43 
44 #include "OscTypes.h"
45 #include "OscException.h"
46 
47 
48 namespace osc{
49 
50 
51 class MalformedPacketException : public Exception{
52 public:
53  MalformedPacketException( const char *w="malformed packet" )
54  : Exception( w ) {}
55 };
56 
57 class MalformedMessageException : public Exception{
58 public:
59  MalformedMessageException( const char *w="malformed message" )
60  : Exception( w ) {}
61 };
62 
63 class MalformedBundleException : public Exception{
64 public:
65  MalformedBundleException( const char *w="malformed bundle" )
66  : Exception( w ) {}
67 };
68 
69 class WrongArgumentTypeException : public Exception{
70 public:
71  WrongArgumentTypeException( const char *w="wrong argument type" )
72  : Exception( w ) {}
73 };
74 
75 class MissingArgumentException : public Exception{
76 public:
77  MissingArgumentException( const char *w="missing argument" )
78  : Exception( w ) {}
79 };
80 
81 class ExcessArgumentException : public Exception{
82 public:
83  ExcessArgumentException( const char *w="too many arguments" )
84  : Exception( w ) {}
85 };
86 
87 
88 class ReceivedPacket{
89 public:
90  // Although the OSC spec is not entirely clear on this, we only support
91  // packets up to 0x7FFFFFFC bytes long (the maximum 4-byte aligned value
92  // representable by an int32). An exception will be raised if you pass a
93  // larger value to the ReceivedPacket() constructor.
94 
95  ReceivedPacket( const char *contents, osc_bundle_element_size_t size )
96  : contents_( contents )
97  , size_( ValidateSize(size) ) {}
98 
99  ReceivedPacket( const char *contents, std::size_t size )
100  : contents_( contents )
101  , size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {}
102 
103 #if !(defined(__x86_64__) || defined(_M_X64))
104  ReceivedPacket( const char *contents, int size )
105  : contents_( contents )
106  , size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {}
107 #endif
108 
109  bool IsMessage() const { return !IsBundle(); }
110  bool IsBundle() const;
111 
112  osc_bundle_element_size_t Size() const { return size_; }
113  const char *Contents() const { return contents_; }
114 
115 private:
116  const char *contents_;
117  osc_bundle_element_size_t size_;
118 
119  static osc_bundle_element_size_t ValidateSize( osc_bundle_element_size_t size )
120  {
121  // sanity check integer types declared in OscTypes.h
122  // you'll need to fix OscTypes.h if any of these asserts fail
123  assert( sizeof(osc::int32) == 4 );
124  assert( sizeof(osc::uint32) == 4 );
125  assert( sizeof(osc::int64) == 8 );
126  assert( sizeof(osc::uint64) == 8 );
127 
128  if( !IsValidElementSizeValue(size) )
129  throw MalformedPacketException( "invalid packet size" );
130 
131  if( size == 0 )
132  throw MalformedPacketException( "zero length elements not permitted" );
133 
134  if( !IsMultipleOf4(size) )
135  throw MalformedPacketException( "element size must be multiple of four" );
136 
137  return size;
138  }
139 };
140 
141 
142 class ReceivedBundleElement{
143 public:
144  ReceivedBundleElement( const char *sizePtr )
145  : sizePtr_( sizePtr ) {}
146 
147  friend class ReceivedBundleElementIterator;
148 
149  bool IsMessage() const { return !IsBundle(); }
150  bool IsBundle() const;
151 
152  osc_bundle_element_size_t Size() const;
153  const char *Contents() const { return sizePtr_ + osc::OSC_SIZEOF_INT32; }
154 
155 private:
156  const char *sizePtr_;
157 };
158 
159 
160 class ReceivedBundleElementIterator{
161 public:
162  ReceivedBundleElementIterator( const char *sizePtr )
163  : value_( sizePtr ) {}
164 
165  ReceivedBundleElementIterator operator++()
166  {
167  Advance();
168  return *this;
169  }
170 
171  ReceivedBundleElementIterator operator++(int)
172  {
173  ReceivedBundleElementIterator old( *this );
174  Advance();
175  return old;
176  }
177 
178  const ReceivedBundleElement& operator*() const { return value_; }
179 
180  const ReceivedBundleElement* operator->() const { return &value_; }
181 
182  friend bool operator==(const ReceivedBundleElementIterator& lhs,
183  const ReceivedBundleElementIterator& rhs );
184 
185 private:
186  ReceivedBundleElement value_;
187 
188  void Advance() { value_.sizePtr_ = value_.Contents() + value_.Size(); }
189 
190  bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const
191  {
192  return value_.sizePtr_ == rhs.value_.sizePtr_;
193  }
194 };
195 
196 inline bool operator==(const ReceivedBundleElementIterator& lhs,
197  const ReceivedBundleElementIterator& rhs )
198 {
199  return lhs.IsEqualTo( rhs );
200 }
201 
202 inline bool operator!=(const ReceivedBundleElementIterator& lhs,
203  const ReceivedBundleElementIterator& rhs )
204 {
205  return !( lhs == rhs );
206 }
207 
208 
209 class ReceivedMessageArgument{
210 public:
211  ReceivedMessageArgument( const char *typeTagPtr, const char *argumentPtr )
212  : typeTagPtr_( typeTagPtr )
213  , argumentPtr_( argumentPtr ) {}
214 
215  friend class ReceivedMessageArgumentIterator;
216 
217  char TypeTag() const { return *typeTagPtr_; }
218 
219  // the unchecked methods below don't check whether the argument actually
220  // is of the specified type. they should only be used if you've already
221  // checked the type tag or the associated IsType() method.
222 
223  bool IsBool() const
224  { return *typeTagPtr_ == TRUE_TYPE_TAG || *typeTagPtr_ == FALSE_TYPE_TAG; }
225  bool AsBool() const;
226  bool AsBoolUnchecked() const;
227 
228  bool IsNil() const { return *typeTagPtr_ == NIL_TYPE_TAG; }
229  bool IsInfinitum() const { return *typeTagPtr_ == INFINITUM_TYPE_TAG; }
230 
231  bool IsInt32() const { return *typeTagPtr_ == INT32_TYPE_TAG; }
232  int32 AsInt32() const;
233  int32 AsInt32Unchecked() const;
234 
235  bool IsFloat() const { return *typeTagPtr_ == FLOAT_TYPE_TAG; }
236  float AsFloat() const;
237  float AsFloatUnchecked() const;
238 
239  bool IsChar() const { return *typeTagPtr_ == CHAR_TYPE_TAG; }
240  char AsChar() const;
241  char AsCharUnchecked() const;
242 
243  bool IsRgbaColor() const { return *typeTagPtr_ == RGBA_COLOR_TYPE_TAG; }
244  uint32 AsRgbaColor() const;
245  uint32 AsRgbaColorUnchecked() const;
246 
247  bool IsMidiMessage() const { return *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG; }
248  uint32 AsMidiMessage() const;
249  uint32 AsMidiMessageUnchecked() const;
250 
251  bool IsInt64() const { return *typeTagPtr_ == INT64_TYPE_TAG; }
252  int64 AsInt64() const;
253  int64 AsInt64Unchecked() const;
254 
255  bool IsTimeTag() const { return *typeTagPtr_ == TIME_TAG_TYPE_TAG; }
256  uint64 AsTimeTag() const;
257  uint64 AsTimeTagUnchecked() const;
258 
259  bool IsDouble() const { return *typeTagPtr_ == DOUBLE_TYPE_TAG; }
260  double AsDouble() const;
261  double AsDoubleUnchecked() const;
262 
263  bool IsString() const { return *typeTagPtr_ == STRING_TYPE_TAG; }
264  const char* AsString() const;
265  const char* AsStringUnchecked() const { return argumentPtr_; }
266 
267  bool IsSymbol() const { return *typeTagPtr_ == SYMBOL_TYPE_TAG; }
268  const char* AsSymbol() const;
269  const char* AsSymbolUnchecked() const { return argumentPtr_; }
270 
271  bool IsBlob() const { return *typeTagPtr_ == BLOB_TYPE_TAG; }
272  void AsBlob( const void*& data, osc_bundle_element_size_t& size ) const;
273  void AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const;
274 
275  bool IsArrayBegin() const { return *typeTagPtr_ == ARRAY_BEGIN_TYPE_TAG; }
276  bool IsArrayEnd() const { return *typeTagPtr_ == ARRAY_END_TYPE_TAG; }
277  // Calculate the number of top-level items in the array. Nested arrays count as one item.
278  // Only valid at array start. Will throw an exception if IsArrayStart() == false.
279  std::size_t ComputeArrayItemCount() const;
280 
281 private:
282  const char *typeTagPtr_;
283  const char *argumentPtr_;
284 };
285 
286 
287 class ReceivedMessageArgumentIterator{
288 public:
289  ReceivedMessageArgumentIterator( const char *typeTags, const char *arguments )
290  : value_( typeTags, arguments ) {}
291 
292  ReceivedMessageArgumentIterator operator++()
293  {
294  Advance();
295  return *this;
296  }
297 
298  ReceivedMessageArgumentIterator operator++(int)
299  {
300  ReceivedMessageArgumentIterator old( *this );
301  Advance();
302  return old;
303  }
304 
305  const ReceivedMessageArgument& operator*() const { return value_; }
306 
307  const ReceivedMessageArgument* operator->() const { return &value_; }
308 
309  friend bool operator==(const ReceivedMessageArgumentIterator& lhs,
310  const ReceivedMessageArgumentIterator& rhs );
311 
312 private:
313  ReceivedMessageArgument value_;
314 
315  void Advance();
316 
317  bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const
318  {
319  return value_.typeTagPtr_ == rhs.value_.typeTagPtr_;
320  }
321 };
322 
323 inline bool operator==(const ReceivedMessageArgumentIterator& lhs,
324  const ReceivedMessageArgumentIterator& rhs )
325 {
326  return lhs.IsEqualTo( rhs );
327 }
328 
329 inline bool operator!=(const ReceivedMessageArgumentIterator& lhs,
330  const ReceivedMessageArgumentIterator& rhs )
331 {
332  return !( lhs == rhs );
333 }
334 
335 
336 class ReceivedMessageArgumentStream{
337  friend class ReceivedMessage;
338  ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin,
339  const ReceivedMessageArgumentIterator& end )
340  : p_( begin )
341  , end_( end ) {}
342 
343  ReceivedMessageArgumentIterator p_, end_;
344 
345 public:
346 
347  // end of stream
348  bool Eos() const { return p_ == end_; }
349 
350  ReceivedMessageArgumentStream& operator>>( bool& rhs )
351  {
352  if( Eos() )
353  throw MissingArgumentException();
354 
355  rhs = (*p_++).AsBool();
356  return *this;
357  }
358 
359  // not sure if it would be useful to stream Nil and Infinitum
360  // for now it's not possible
361  // same goes for array boundaries
362 
363  ReceivedMessageArgumentStream& operator>>( int32& rhs )
364  {
365  if( Eos() )
366  throw MissingArgumentException();
367 
368  rhs = (*p_++).AsInt32();
369  return *this;
370  }
371 
372  ReceivedMessageArgumentStream& operator>>( float& rhs )
373  {
374  if( Eos() )
375  throw MissingArgumentException();
376 
377  rhs = (*p_++).AsFloat();
378  return *this;
379  }
380 
381  ReceivedMessageArgumentStream& operator>>( char& rhs )
382  {
383  if( Eos() )
384  throw MissingArgumentException();
385 
386  rhs = (*p_++).AsChar();
387  return *this;
388  }
389 
390  ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs )
391  {
392  if( Eos() )
393  throw MissingArgumentException();
394 
395  rhs.value = (*p_++).AsRgbaColor();
396  return *this;
397  }
398 
399  ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs )
400  {
401  if( Eos() )
402  throw MissingArgumentException();
403 
404  rhs.value = (*p_++).AsMidiMessage();
405  return *this;
406  }
407 
408  ReceivedMessageArgumentStream& operator>>( int64& rhs )
409  {
410  if( Eos() )
411  throw MissingArgumentException();
412 
413  rhs = (*p_++).AsInt64();
414  return *this;
415  }
416 
417  ReceivedMessageArgumentStream& operator>>( TimeTag& rhs )
418  {
419  if( Eos() )
420  throw MissingArgumentException();
421 
422  rhs.value = (*p_++).AsTimeTag();
423  return *this;
424  }
425 
426  ReceivedMessageArgumentStream& operator>>( double& rhs )
427  {
428  if( Eos() )
429  throw MissingArgumentException();
430 
431  rhs = (*p_++).AsDouble();
432  return *this;
433  }
434 
435  ReceivedMessageArgumentStream& operator>>( Blob& rhs )
436  {
437  if( Eos() )
438  throw MissingArgumentException();
439 
440  (*p_++).AsBlob( rhs.data, rhs.size );
441  return *this;
442  }
443 
444  ReceivedMessageArgumentStream& operator>>( const char*& rhs )
445  {
446  if( Eos() )
447  throw MissingArgumentException();
448 
449  rhs = (*p_++).AsString();
450  return *this;
451  }
452 
453  ReceivedMessageArgumentStream& operator>>( Symbol& rhs )
454  {
455  if( Eos() )
456  throw MissingArgumentException();
457 
458  rhs.value = (*p_++).AsSymbol();
459  return *this;
460  }
461 
462  ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs )
463  {
464  (void) rhs; // suppress unused parameter warning
465 
466  if( !Eos() )
467  throw ExcessArgumentException();
468 
469  return *this;
470  }
471 };
472 
473 
474 class ReceivedMessage{
475  void Init( const char *bundle, osc_bundle_element_size_t size );
476 public:
477  explicit ReceivedMessage( const ReceivedPacket& packet );
478  explicit ReceivedMessage( const ReceivedBundleElement& bundleElement );
479 
480  const char *AddressPattern() const { return addressPattern_; }
481 
482  // Support for non-standard SuperCollider integer address patterns:
483  bool AddressPatternIsUInt32() const;
484  uint32 AddressPatternAsUInt32() const;
485 
486  uint32 ArgumentCount() const { return static_cast<uint32>(typeTagsEnd_ - typeTagsBegin_); }
487 
488  const char *TypeTags() const { return typeTagsBegin_; }
489 
490 
491  typedef ReceivedMessageArgumentIterator const_iterator;
492 
493  ReceivedMessageArgumentIterator ArgumentsBegin() const
494  {
495  return ReceivedMessageArgumentIterator( typeTagsBegin_, arguments_ );
496  }
497 
498  ReceivedMessageArgumentIterator ArgumentsEnd() const
499  {
500  return ReceivedMessageArgumentIterator( typeTagsEnd_, 0 );
501  }
502 
503  ReceivedMessageArgumentStream ArgumentStream() const
504  {
505  return ReceivedMessageArgumentStream( ArgumentsBegin(), ArgumentsEnd() );
506  }
507 
508 private:
509  const char *addressPattern_;
510  const char *typeTagsBegin_;
511  const char *typeTagsEnd_;
512  const char *arguments_;
513 };
514 
515 
516 class ReceivedBundle{
517  void Init( const char *message, osc_bundle_element_size_t size );
518 public:
519  explicit ReceivedBundle( const ReceivedPacket& packet );
520  explicit ReceivedBundle( const ReceivedBundleElement& bundleElement );
521 
522  uint64 TimeTag() const;
523 
524  uint32 ElementCount() const { return elementCount_; }
525 
526  typedef ReceivedBundleElementIterator const_iterator;
527 
528  ReceivedBundleElementIterator ElementsBegin() const
529  {
530  return ReceivedBundleElementIterator( timeTag_ + 8 );
531  }
532 
533  ReceivedBundleElementIterator ElementsEnd() const
534  {
535  return ReceivedBundleElementIterator( end_ );
536  }
537 
538 private:
539  const char *timeTag_;
540  const char *end_;
541  uint32 elementCount_;
542 };
543 
544 
545 } // namespace osc
546 
547 
548 #endif /* INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H */
bool TTFOUNDATION_EXPORT operator!=(const TTObject &anObject, const TTObject &anotherObject)
Compare two objects for inequality.
Definition: TTObject.cpp:173
bool TTFOUNDATION_EXPORT operator==(const TTObject &anObject, const TTObject &anotherObject)
Compare two objects for equality.
Definition: TTObject.cpp:167