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
34 #include "OscException.h"
40 class MalformedMessageException
: public Exception
{
42 MalformedMessageException( const char *w
="malformed message" )
46 class MalformedBundleException
: public Exception
{
48 MalformedBundleException( const char *w
="malformed bundle" )
52 class WrongArgumentTypeException
: public Exception
{
54 WrongArgumentTypeException( const char *w
="wrong argument type" )
58 class MissingArgumentException
: public Exception
{
60 MissingArgumentException( const char *w
="missing argument" )
64 class ExcessArgumentException
: public Exception
{
66 ExcessArgumentException( const char *w
="too many arguments" )
73 ReceivedPacket( const char *contents
, int32 size
)
74 : contents_( contents
)
77 bool IsMessage() const { return !IsBundle(); }
78 bool IsBundle() const;
80 int32
Size() const { return size_
; }
81 const char *Contents() const { return contents_
; }
84 const char *contents_
;
89 class ReceivedBundleElement
{
91 ReceivedBundleElement( const char *size
)
94 friend class ReceivedBundleElementIterator
;
96 bool IsMessage() const { return !IsBundle(); }
97 bool IsBundle() const;
100 const char *Contents() const { return size_
+ 4; }
107 class ReceivedBundleElementIterator
{
109 ReceivedBundleElementIterator( const char *sizePtr
)
110 : value_( sizePtr
) {}
112 ReceivedBundleElementIterator
operator++()
118 ReceivedBundleElementIterator
operator++(int)
120 ReceivedBundleElementIterator
old( *this );
125 const ReceivedBundleElement
& operator*() const { return value_
; }
127 const ReceivedBundleElement
* operator->() const { return &value_
; }
129 friend bool operator==(const ReceivedBundleElementIterator
& lhs
,
130 const ReceivedBundleElementIterator
& rhs
);
133 ReceivedBundleElement value_
;
135 void Advance() { value_
.size_
= value_
.Contents() + value_
.Size(); }
137 bool IsEqualTo( const ReceivedBundleElementIterator
& rhs
) const
139 return value_
.size_
== rhs
.value_
.size_
;
143 inline bool operator==(const ReceivedBundleElementIterator
& lhs
,
144 const ReceivedBundleElementIterator
& rhs
)
146 return lhs
.IsEqualTo( rhs
);
149 inline bool operator!=(const ReceivedBundleElementIterator
& lhs
,
150 const ReceivedBundleElementIterator
& rhs
)
152 return !( lhs
== rhs
);
156 class ReceivedMessageArgument
{
158 ReceivedMessageArgument( const char *typeTag
, const char *argument
)
159 : typeTag_( typeTag
)
160 , argument_( argument
) {}
162 friend class ReceivedMessageArgumentIterator
;
164 const char TypeTag() const { return *typeTag_
; }
166 // the unchecked methods below don't check whether the argument actually
167 // is of the specified type. they should only be used if you've already
168 // checked the type tag or the associated IsType() method.
171 { return *typeTag_
== TRUE_TYPE_TAG
|| *typeTag_
== FALSE_TYPE_TAG
; }
173 bool AsBoolUnchecked() const;
175 bool IsNil() const { return *typeTag_
== NIL_TYPE_TAG
; }
176 bool IsInfinitum() const { return *typeTag_
== INFINITUM_TYPE_TAG
; }
178 bool IsInt32() const { return *typeTag_
== INT32_TYPE_TAG
; }
179 int32
AsInt32() const;
180 int32
AsInt32Unchecked() const;
182 bool IsFloat() const { return *typeTag_
== FLOAT_TYPE_TAG
; }
183 float AsFloat() const;
184 float AsFloatUnchecked() const;
186 bool IsChar() const { return *typeTag_
== CHAR_TYPE_TAG
; }
188 char AsCharUnchecked() const;
190 bool IsRgbaColor() const { return *typeTag_
== RGBA_COLOR_TYPE_TAG
; }
191 uint32
AsRgbaColor() const;
192 uint32
AsRgbaColorUnchecked() const;
194 bool IsMidiMessage() const { return *typeTag_
== MIDI_MESSAGE_TYPE_TAG
; }
195 uint32
AsMidiMessage() const;
196 uint32
AsMidiMessageUnchecked() const;
198 bool IsInt64() const { return *typeTag_
== INT64_TYPE_TAG
; }
199 int64
AsInt64() const;
200 int64
AsInt64Unchecked() const;
202 bool IsTimeTag() const { return *typeTag_
== TIME_TAG_TYPE_TAG
; }
203 uint64
AsTimeTag() const;
204 uint64
AsTimeTagUnchecked() const;
206 bool IsDouble() const { return *typeTag_
== DOUBLE_TYPE_TAG
; }
207 double AsDouble() const;
208 double AsDoubleUnchecked() const;
210 bool IsString() const { return *typeTag_
== STRING_TYPE_TAG
; }
211 const char* AsString() const;
212 const char* AsStringUnchecked() const { return argument_
; }
214 bool IsSymbol() const { return *typeTag_
== SYMBOL_TYPE_TAG
; }
215 const char* AsSymbol() const;
216 const char* AsSymbolUnchecked() const { return argument_
; }
218 bool IsBlob() const { return *typeTag_
== BLOB_TYPE_TAG
; }
219 void AsBlob( const void*& data
, unsigned long& size
) const;
220 void AsBlobUnchecked( const void*& data
, unsigned long& size
) const;
223 const char *typeTag_
;
224 const char *argument_
;
228 class ReceivedMessageArgumentIterator
{
230 ReceivedMessageArgumentIterator( const char *typeTags
, const char *arguments
)
231 : value_( typeTags
, arguments
) {}
233 ReceivedMessageArgumentIterator
operator++()
239 ReceivedMessageArgumentIterator
operator++(int)
241 ReceivedMessageArgumentIterator
old( *this );
246 const ReceivedMessageArgument
& operator*() const { return value_
; }
248 const ReceivedMessageArgument
* operator->() const { return &value_
; }
250 friend bool operator==(const ReceivedMessageArgumentIterator
& lhs
,
251 const ReceivedMessageArgumentIterator
& rhs
);
254 ReceivedMessageArgument value_
;
258 bool IsEqualTo( const ReceivedMessageArgumentIterator
& rhs
) const
260 return value_
.typeTag_
== rhs
.value_
.typeTag_
;
264 inline bool operator==(const ReceivedMessageArgumentIterator
& lhs
,
265 const ReceivedMessageArgumentIterator
& rhs
)
267 return lhs
.IsEqualTo( rhs
);
270 inline bool operator!=(const ReceivedMessageArgumentIterator
& lhs
,
271 const ReceivedMessageArgumentIterator
& rhs
)
273 return !( lhs
== rhs
);
277 class ReceivedMessageArgumentStream
{
278 friend class ReceivedMessage
;
279 ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator
& begin
,
280 const ReceivedMessageArgumentIterator
& end
)
284 ReceivedMessageArgumentIterator p_
, end_
;
289 bool Eos() const { return p_
== end_
; }
291 ReceivedMessageArgumentStream
& operator>>( bool& rhs
)
294 throw MissingArgumentException();
296 rhs
= (*p_
++).AsBool();
300 // not sure if it would be useful to stream Nil and Infinitum
301 // for now it's not possible
303 ReceivedMessageArgumentStream
& operator>>( int32
& rhs
)
306 throw MissingArgumentException();
308 rhs
= (*p_
++).AsInt32();
312 ReceivedMessageArgumentStream
& operator>>( float& rhs
)
315 throw MissingArgumentException();
317 rhs
= (*p_
++).AsFloat();
321 ReceivedMessageArgumentStream
& operator>>( char& rhs
)
324 throw MissingArgumentException();
326 rhs
= (*p_
++).AsChar();
330 ReceivedMessageArgumentStream
& operator>>( RgbaColor
& rhs
)
333 throw MissingArgumentException();
335 rhs
.value
= (*p_
++).AsRgbaColor();
339 ReceivedMessageArgumentStream
& operator>>( MidiMessage
& rhs
)
342 throw MissingArgumentException();
344 rhs
.value
= (*p_
++).AsMidiMessage();
348 ReceivedMessageArgumentStream
& operator>>( int64
& rhs
)
351 throw MissingArgumentException();
353 rhs
= (*p_
++).AsInt64();
357 ReceivedMessageArgumentStream
& operator>>( TimeTag
& rhs
)
360 throw MissingArgumentException();
362 rhs
.value
= (*p_
++).AsTimeTag();
366 ReceivedMessageArgumentStream
& operator>>( double& rhs
)
369 throw MissingArgumentException();
371 rhs
= (*p_
++).AsDouble();
375 ReceivedMessageArgumentStream
& operator>>( Blob
& rhs
)
378 throw MissingArgumentException();
380 (*p_
++).AsBlob( rhs
.data
, rhs
.size
);
384 ReceivedMessageArgumentStream
& operator>>( const char*& rhs
)
387 throw MissingArgumentException();
389 rhs
= (*p_
++).AsString();
393 ReceivedMessageArgumentStream
& operator>>( Symbol
& rhs
)
396 throw MissingArgumentException();
398 rhs
.value
= (*p_
++).AsSymbol();
402 ReceivedMessageArgumentStream
& operator>>( MessageTerminator
& )
405 throw ExcessArgumentException();
412 class ReceivedMessage
{
413 void Init( const char *bundle
, unsigned long size
);
415 explicit ReceivedMessage( const ReceivedPacket
& packet
);
416 explicit ReceivedMessage( const ReceivedBundleElement
& bundleElement
);
418 const char *AddressPattern() const { return addressPattern_
; }
420 // Support for non-standad SuperCollider integer address patterns:
421 bool AddressPatternIsUInt32() const;
422 uint32
AddressPatternAsUInt32() const;
424 unsigned long ArgumentCount() const { return static_cast<unsigned long>(typeTagsEnd_
- typeTagsBegin_
); }
426 const char *TypeTags() const { return typeTagsBegin_
; }
429 typedef ReceivedMessageArgumentIterator const_iterator
;
431 ReceivedMessageArgumentIterator
ArgumentsBegin() const
433 return ReceivedMessageArgumentIterator( typeTagsBegin_
, arguments_
);
436 ReceivedMessageArgumentIterator
ArgumentsEnd() const
438 return ReceivedMessageArgumentIterator( typeTagsEnd_
, 0 );
441 ReceivedMessageArgumentStream
ArgumentStream() const
443 return ReceivedMessageArgumentStream( ArgumentsBegin(), ArgumentsEnd() );
447 const char *addressPattern_
;
448 const char *typeTagsBegin_
;
449 const char *typeTagsEnd_
;
450 const char *arguments_
;
454 class ReceivedBundle
{
455 void Init( const char *message
, unsigned long size
);
457 explicit ReceivedBundle( const ReceivedPacket
& packet
);
458 explicit ReceivedBundle( const ReceivedBundleElement
& bundleElement
);
460 uint64
TimeTag() const;
462 unsigned long ElementCount() const { return elementCount_
; }
464 typedef ReceivedBundleElementIterator const_iterator
;
466 ReceivedBundleElementIterator
ElementsBegin() const
468 return ReceivedBundleElementIterator( timeTag_
+ 8 );
471 ReceivedBundleElementIterator
ElementsEnd() const
473 return ReceivedBundleElementIterator( end_
);
477 const char *timeTag_
;
479 unsigned long elementCount_
;
486 #endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */