2 oscpack -- Open Sound Control packet manipulation library
3 http://www.audiomulch.com/~rossb/oscpack
5 Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>
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:
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
18 Any person wishing to distribute modifications to the Software is
19 requested to send the modifications to the original developer so that
20 they can be incorporated into the canonical version.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #ifndef INCLUDED_OSCRECEIVEDELEMENTS_H
31 #define INCLUDED_OSCRECEIVEDELEMENTS_H
36 #include "OscException.h"
42 class MalformedMessageException
: public Exception
{
44 MalformedMessageException( const char *w
="malformed message" )
48 class MalformedBundleException
: public Exception
{
50 MalformedBundleException( const char *w
="malformed bundle" )
54 class WrongArgumentTypeException
: public Exception
{
56 WrongArgumentTypeException( const char *w
="wrong argument type" )
60 class MissingArgumentException
: public Exception
{
62 MissingArgumentException( const char *w
="missing argument" )
66 class ExcessArgumentException
: public Exception
{
68 ExcessArgumentException( const char *w
="too many arguments" )
75 ReceivedPacket( const char *contents
, int32 size
)
76 : contents_( contents
)
79 bool IsMessage() const { return !IsBundle(); }
80 bool IsBundle() const;
82 int32
Size() const { return size_
; }
83 const char *Contents() const { return contents_
; }
86 const char *contents_
;
91 class ReceivedBundleElement
{
93 ReceivedBundleElement( const char *size
)
96 friend class ReceivedBundleElementIterator
;
98 bool IsMessage() const { return !IsBundle(); }
99 bool IsBundle() const;
102 const char *Contents() const { return size_
+ 4; }
109 class ReceivedBundleElementIterator
{
111 ReceivedBundleElementIterator( const char *sizePtr
)
112 : value_( sizePtr
) {}
114 ReceivedBundleElementIterator
operator++()
120 ReceivedBundleElementIterator
operator++(int)
122 ReceivedBundleElementIterator
old( *this );
127 const ReceivedBundleElement
& operator*() const { return value_
; }
129 const ReceivedBundleElement
* operator->() const { return &value_
; }
131 friend bool operator==(const ReceivedBundleElementIterator
& lhs
,
132 const ReceivedBundleElementIterator
& rhs
);
135 ReceivedBundleElement value_
;
137 void Advance() { value_
.size_
= value_
.Contents() + value_
.Size(); }
139 bool IsEqualTo( const ReceivedBundleElementIterator
& rhs
) const
141 return value_
.size_
== rhs
.value_
.size_
;
145 inline bool operator==(const ReceivedBundleElementIterator
& lhs
,
146 const ReceivedBundleElementIterator
& rhs
)
148 return lhs
.IsEqualTo( rhs
);
151 inline bool operator!=(const ReceivedBundleElementIterator
& lhs
,
152 const ReceivedBundleElementIterator
& rhs
)
154 return !( lhs
== rhs
);
158 class ReceivedMessageArgument
{
160 ReceivedMessageArgument( const char *typeTag
, const char *argument
)
161 : typeTag_( typeTag
)
162 , argument_( argument
) {}
164 friend class ReceivedMessageArgumentIterator
;
166 const char TypeTag() const { return *typeTag_
; }
168 // the unchecked methods below don't check whether the argument actually
169 // is of the specified type. they should only be used if you've already
170 // checked the type tag or the associated IsType() method.
173 { return *typeTag_
== TRUE_TYPE_TAG
|| *typeTag_
== FALSE_TYPE_TAG
; }
175 bool AsBoolUnchecked() const;
177 bool IsNil() const { return *typeTag_
== NIL_TYPE_TAG
; }
178 bool IsInfinitum() const { return *typeTag_
== INFINITUM_TYPE_TAG
; }
180 bool IsInt32() const { return *typeTag_
== INT32_TYPE_TAG
; }
181 int32
AsInt32() const;
182 int32
AsInt32Unchecked() const;
184 bool IsFloat() const { return *typeTag_
== FLOAT_TYPE_TAG
; }
185 float AsFloat() const;
186 float AsFloatUnchecked() const;
188 bool IsChar() const { return *typeTag_
== CHAR_TYPE_TAG
; }
190 char AsCharUnchecked() const;
192 bool IsRgbaColor() const { return *typeTag_
== RGBA_COLOR_TYPE_TAG
; }
193 uint32
AsRgbaColor() const;
194 uint32
AsRgbaColorUnchecked() const;
196 bool IsMidiMessage() const { return *typeTag_
== MIDI_MESSAGE_TYPE_TAG
; }
197 uint32
AsMidiMessage() const;
198 uint32
AsMidiMessageUnchecked() const;
200 bool IsInt64() const { return *typeTag_
== INT64_TYPE_TAG
; }
201 int64
AsInt64() const;
202 int64
AsInt64Unchecked() const;
204 bool IsTimeTag() const { return *typeTag_
== TIME_TAG_TYPE_TAG
; }
205 uint64
AsTimeTag() const;
206 uint64
AsTimeTagUnchecked() const;
208 bool IsDouble() const { return *typeTag_
== DOUBLE_TYPE_TAG
; }
209 double AsDouble() const;
210 double AsDoubleUnchecked() const;
212 bool IsString() const { return *typeTag_
== STRING_TYPE_TAG
; }
213 const char* AsString() const;
214 const char* AsStringUnchecked() const { return argument_
; }
216 bool IsSymbol() const { return *typeTag_
== SYMBOL_TYPE_TAG
; }
217 const char* AsSymbol() const;
218 const char* AsSymbolUnchecked() const { return argument_
; }
220 bool IsBlob() const { return *typeTag_
== BLOB_TYPE_TAG
; }
221 void AsBlob( const void*& data
, unsigned long& size
) const;
222 void AsBlobUnchecked( const void*& data
, unsigned long& size
) const;
224 bool IsArrayStart() const { return *typeTag_
== ARRAY_START_TYPE_TAG
; }
225 bool IsArrayEnd() const { return *typeTag_
== ARRAY_END_TYPE_TAG
; }
227 std::size_t ArraySize() const;
230 const char *typeTag_
;
231 const char *argument_
;
235 class ReceivedMessageArgumentIterator
{
237 ReceivedMessageArgumentIterator( const char *typeTags
, const char *arguments
)
238 : value_( typeTags
, arguments
) {}
240 ReceivedMessageArgumentIterator
operator++()
246 ReceivedMessageArgumentIterator
operator++(int)
248 ReceivedMessageArgumentIterator
old( *this );
253 const ReceivedMessageArgument
& operator*() const { return value_
; }
255 const ReceivedMessageArgument
* operator->() const { return &value_
; }
257 friend bool operator==(const ReceivedMessageArgumentIterator
& lhs
,
258 const ReceivedMessageArgumentIterator
& rhs
);
261 ReceivedMessageArgument value_
;
265 bool IsEqualTo( const ReceivedMessageArgumentIterator
& rhs
) const
267 return value_
.typeTag_
== rhs
.value_
.typeTag_
;
271 inline bool operator==(const ReceivedMessageArgumentIterator
& lhs
,
272 const ReceivedMessageArgumentIterator
& rhs
)
274 return lhs
.IsEqualTo( rhs
);
277 inline bool operator!=(const ReceivedMessageArgumentIterator
& lhs
,
278 const ReceivedMessageArgumentIterator
& rhs
)
280 return !( lhs
== rhs
);
284 class ReceivedMessageArgumentStream
{
285 friend class ReceivedMessage
;
286 ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator
& begin
,
287 const ReceivedMessageArgumentIterator
& end
)
291 ReceivedMessageArgumentIterator p_
, end_
;
296 bool Eos() const { return p_
== end_
; }
298 ReceivedMessageArgumentStream
& operator>>( bool& rhs
)
301 throw MissingArgumentException();
303 rhs
= (*p_
++).AsBool();
307 // not sure if it would be useful to stream Nil and Infinitum
308 // for now it's not possible
309 // same goes for array boundaries
311 ReceivedMessageArgumentStream
& operator>>( int32
& rhs
)
314 throw MissingArgumentException();
316 rhs
= (*p_
++).AsInt32();
320 ReceivedMessageArgumentStream
& operator>>( float& rhs
)
323 throw MissingArgumentException();
325 rhs
= (*p_
++).AsFloat();
329 ReceivedMessageArgumentStream
& operator>>( char& rhs
)
332 throw MissingArgumentException();
334 rhs
= (*p_
++).AsChar();
338 ReceivedMessageArgumentStream
& operator>>( RgbaColor
& rhs
)
341 throw MissingArgumentException();
343 rhs
.value
= (*p_
++).AsRgbaColor();
347 ReceivedMessageArgumentStream
& operator>>( MidiMessage
& rhs
)
350 throw MissingArgumentException();
352 rhs
.value
= (*p_
++).AsMidiMessage();
356 ReceivedMessageArgumentStream
& operator>>( int64
& rhs
)
359 throw MissingArgumentException();
361 rhs
= (*p_
++).AsInt64();
365 ReceivedMessageArgumentStream
& operator>>( TimeTag
& rhs
)
368 throw MissingArgumentException();
370 rhs
.value
= (*p_
++).AsTimeTag();
374 ReceivedMessageArgumentStream
& operator>>( double& rhs
)
377 throw MissingArgumentException();
379 rhs
= (*p_
++).AsDouble();
383 ReceivedMessageArgumentStream
& operator>>( Blob
& rhs
)
386 throw MissingArgumentException();
388 (*p_
++).AsBlob( rhs
.data
, rhs
.size
);
392 ReceivedMessageArgumentStream
& operator>>( const char*& rhs
)
395 throw MissingArgumentException();
397 rhs
= (*p_
++).AsString();
401 ReceivedMessageArgumentStream
& operator>>( Symbol
& rhs
)
404 throw MissingArgumentException();
406 rhs
.value
= (*p_
++).AsSymbol();
410 ReceivedMessageArgumentStream
& operator>>( MessageTerminator
& rhs
)
413 throw ExcessArgumentException();
420 class ReceivedMessage
{
421 void Init( const char *bundle
, unsigned long size
);
423 explicit ReceivedMessage( const ReceivedPacket
& packet
);
424 explicit ReceivedMessage( const ReceivedBundleElement
& bundleElement
);
426 const char *AddressPattern() const { return addressPattern_
; }
428 // Support for non-standad SuperCollider integer address patterns:
429 bool AddressPatternIsUInt32() const;
430 uint32
AddressPatternAsUInt32() const;
432 unsigned long ArgumentCount() const { return static_cast<unsigned long>(typeTagsEnd_
- typeTagsBegin_
); }
434 const char *TypeTags() const { return typeTagsBegin_
; }
437 typedef ReceivedMessageArgumentIterator const_iterator
;
439 ReceivedMessageArgumentIterator
ArgumentsBegin() const
441 return ReceivedMessageArgumentIterator( typeTagsBegin_
, arguments_
);
444 ReceivedMessageArgumentIterator
ArgumentsEnd() const
446 return ReceivedMessageArgumentIterator( typeTagsEnd_
, 0 );
449 ReceivedMessageArgumentStream
ArgumentStream() const
451 return ReceivedMessageArgumentStream( ArgumentsBegin(), ArgumentsEnd() );
455 const char *addressPattern_
;
456 const char *typeTagsBegin_
;
457 const char *typeTagsEnd_
;
458 const char *arguments_
;
462 class ReceivedBundle
{
463 void Init( const char *message
, unsigned long size
);
465 explicit ReceivedBundle( const ReceivedPacket
& packet
);
466 explicit ReceivedBundle( const ReceivedBundleElement
& bundleElement
);
468 uint64
TimeTag() const;
470 unsigned long ElementCount() const { return elementCount_
; }
472 typedef ReceivedBundleElementIterator const_iterator
;
474 ReceivedBundleElementIterator
ElementsBegin() const
476 return ReceivedBundleElementIterator( timeTag_
+ 8 );
479 ReceivedBundleElementIterator
ElementsEnd() const
481 return ReceivedBundleElementIterator( end_
);
485 const char *timeTag_
;
487 unsigned long elementCount_
;
494 #endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */