2 oscpack -- Open Sound Control packet manipulation library
\r
3 http://www.audiomulch.com/~rossb/oscpack
\r
5 Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>
\r
7 Permission is hereby granted, free of charge, to any person obtaining
\r
8 a copy of this software and associated documentation files
\r
9 (the "Software"), to deal in the Software without restriction,
\r
10 including without limitation the rights to use, copy, modify, merge,
\r
11 publish, distribute, sublicense, and/or sell copies of the Software,
\r
12 and to permit persons to whom the Software is furnished to do so,
\r
13 subject to the following conditions:
\r
15 The above copyright notice and this permission notice shall be
\r
16 included in all copies or substantial portions of the Software.
\r
18 Any person wishing to distribute modifications to the Software is
\r
19 requested to send the modifications to the original developer so that
\r
20 they can be incorporated into the canonical version.
\r
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
\r
25 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
\r
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
\r
27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
30 #ifndef INCLUDED_OSCRECEIVEDELEMENTS_H
\r
31 #define INCLUDED_OSCRECEIVEDELEMENTS_H
\r
35 #include "OscTypes.h"
\r
36 #include "OscException.h"
\r
42 class MalformedMessageException : public Exception{
\r
44 MalformedMessageException( const char *w="malformed message" )
\r
48 class MalformedBundleException : public Exception{
\r
50 MalformedBundleException( const char *w="malformed bundle" )
\r
54 class WrongArgumentTypeException : public Exception{
\r
56 WrongArgumentTypeException( const char *w="wrong argument type" )
\r
60 class MissingArgumentException : public Exception{
\r
62 MissingArgumentException( const char *w="missing argument" )
\r
66 class ExcessArgumentException : public Exception{
\r
68 ExcessArgumentException( const char *w="too many arguments" )
\r
73 class ReceivedPacket{
\r
75 ReceivedPacket( const char *contents, int32 size )
\r
76 : contents_( contents )
\r
79 bool IsMessage() const { return !IsBundle(); }
\r
80 bool IsBundle() const;
\r
82 int32 Size() const { return size_; }
\r
83 const char *Contents() const { return contents_; }
\r
86 const char *contents_;
\r
91 class ReceivedBundleElement{
\r
93 ReceivedBundleElement( const char *size )
\r
96 friend class ReceivedBundleElementIterator;
\r
98 bool IsMessage() const { return !IsBundle(); }
\r
99 bool IsBundle() const;
\r
101 int32 Size() const;
\r
102 const char *Contents() const { return size_ + 4; }
\r
109 class ReceivedBundleElementIterator{
\r
111 ReceivedBundleElementIterator( const char *sizePtr )
\r
112 : value_( sizePtr ) {}
\r
114 ReceivedBundleElementIterator operator++()
\r
120 ReceivedBundleElementIterator operator++(int)
\r
122 ReceivedBundleElementIterator old( *this );
\r
127 const ReceivedBundleElement& operator*() const { return value_; }
\r
129 const ReceivedBundleElement* operator->() const { return &value_; }
\r
131 friend bool operator==(const ReceivedBundleElementIterator& lhs,
\r
132 const ReceivedBundleElementIterator& rhs );
\r
135 ReceivedBundleElement value_;
\r
137 void Advance() { value_.size_ = value_.Contents() + value_.Size(); }
\r
139 bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const
\r
141 return value_.size_ == rhs.value_.size_;
\r
145 inline bool operator==(const ReceivedBundleElementIterator& lhs,
\r
146 const ReceivedBundleElementIterator& rhs )
\r
148 return lhs.IsEqualTo( rhs );
\r
151 inline bool operator!=(const ReceivedBundleElementIterator& lhs,
\r
152 const ReceivedBundleElementIterator& rhs )
\r
154 return !( lhs == rhs );
\r
158 class ReceivedMessageArgument{
\r
160 ReceivedMessageArgument( const char *typeTag, const char *argument )
\r
161 : typeTag_( typeTag )
\r
162 , argument_( argument ) {}
\r
164 friend class ReceivedMessageArgumentIterator;
\r
166 const char TypeTag() const { return *typeTag_; }
\r
168 // the unchecked methods below don't check whether the argument actually
\r
169 // is of the specified type. they should only be used if you've already
\r
170 // checked the type tag or the associated IsType() method.
\r
172 bool IsBool() const
\r
173 { return *typeTag_ == TRUE_TYPE_TAG || *typeTag_ == FALSE_TYPE_TAG; }
\r
174 bool AsBool() const;
\r
175 bool AsBoolUnchecked() const;
\r
177 bool IsNil() const { return *typeTag_ == NIL_TYPE_TAG; }
\r
178 bool IsInfinitum() const { return *typeTag_ == INFINITUM_TYPE_TAG; }
\r
180 bool IsInt32() const { return *typeTag_ == INT32_TYPE_TAG; }
\r
181 int32 AsInt32() const;
\r
182 int32 AsInt32Unchecked() const;
\r
184 bool IsFloat() const { return *typeTag_ == FLOAT_TYPE_TAG; }
\r
185 float AsFloat() const;
\r
186 float AsFloatUnchecked() const;
\r
188 bool IsChar() const { return *typeTag_ == CHAR_TYPE_TAG; }
\r
189 char AsChar() const;
\r
190 char AsCharUnchecked() const;
\r
192 bool IsRgbaColor() const { return *typeTag_ == RGBA_COLOR_TYPE_TAG; }
\r
193 uint32 AsRgbaColor() const;
\r
194 uint32 AsRgbaColorUnchecked() const;
\r
196 bool IsMidiMessage() const { return *typeTag_ == MIDI_MESSAGE_TYPE_TAG; }
\r
197 uint32 AsMidiMessage() const;
\r
198 uint32 AsMidiMessageUnchecked() const;
\r
200 bool IsInt64() const { return *typeTag_ == INT64_TYPE_TAG; }
\r
201 int64 AsInt64() const;
\r
202 int64 AsInt64Unchecked() const;
\r
204 bool IsTimeTag() const { return *typeTag_ == TIME_TAG_TYPE_TAG; }
\r
205 uint64 AsTimeTag() const;
\r
206 uint64 AsTimeTagUnchecked() const;
\r
208 bool IsDouble() const { return *typeTag_ == DOUBLE_TYPE_TAG; }
\r
209 double AsDouble() const;
\r
210 double AsDoubleUnchecked() const;
\r
212 bool IsString() const { return *typeTag_ == STRING_TYPE_TAG; }
\r
213 const char* AsString() const;
\r
214 const char* AsStringUnchecked() const { return argument_; }
\r
216 bool IsSymbol() const { return *typeTag_ == SYMBOL_TYPE_TAG; }
\r
217 const char* AsSymbol() const;
\r
218 const char* AsSymbolUnchecked() const { return argument_; }
\r
220 bool IsBlob() const { return *typeTag_ == BLOB_TYPE_TAG; }
\r
221 void AsBlob( const void*& data, unsigned long& size ) const;
\r
222 void AsBlobUnchecked( const void*& data, unsigned long& size ) const;
\r
225 const char *typeTag_;
\r
226 const char *argument_;
\r
230 class ReceivedMessageArgumentIterator{
\r
232 ReceivedMessageArgumentIterator( const char *typeTags, const char *arguments )
\r
233 : value_( typeTags, arguments ) {}
\r
235 ReceivedMessageArgumentIterator operator++()
\r
241 ReceivedMessageArgumentIterator operator++(int)
\r
243 ReceivedMessageArgumentIterator old( *this );
\r
248 const ReceivedMessageArgument& operator*() const { return value_; }
\r
250 const ReceivedMessageArgument* operator->() const { return &value_; }
\r
252 friend bool operator==(const ReceivedMessageArgumentIterator& lhs,
\r
253 const ReceivedMessageArgumentIterator& rhs );
\r
256 ReceivedMessageArgument value_;
\r
260 bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const
\r
262 return value_.typeTag_ == rhs.value_.typeTag_;
\r
266 inline bool operator==(const ReceivedMessageArgumentIterator& lhs,
\r
267 const ReceivedMessageArgumentIterator& rhs )
\r
269 return lhs.IsEqualTo( rhs );
\r
272 inline bool operator!=(const ReceivedMessageArgumentIterator& lhs,
\r
273 const ReceivedMessageArgumentIterator& rhs )
\r
275 return !( lhs == rhs );
\r
279 class ReceivedMessageArgumentStream{
\r
280 friend class ReceivedMessage;
\r
281 ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin,
\r
282 const ReceivedMessageArgumentIterator& end )
\r
286 ReceivedMessageArgumentIterator p_, end_;
\r
291 bool Eos() const { return p_ == end_; }
\r
293 ReceivedMessageArgumentStream& operator>>( bool& rhs )
\r
296 throw MissingArgumentException();
\r
298 rhs = (*p_++).AsBool();
\r
302 // not sure if it would be useful to stream Nil and Infinitum
\r
303 // for now it's not possible
\r
305 ReceivedMessageArgumentStream& operator>>( int32& rhs )
\r
308 throw MissingArgumentException();
\r
310 rhs = (*p_++).AsInt32();
\r
314 ReceivedMessageArgumentStream& operator>>( float& rhs )
\r
317 throw MissingArgumentException();
\r
319 rhs = (*p_++).AsFloat();
\r
323 ReceivedMessageArgumentStream& operator>>( char& rhs )
\r
326 throw MissingArgumentException();
\r
328 rhs = (*p_++).AsChar();
\r
332 ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs )
\r
335 throw MissingArgumentException();
\r
337 rhs.value = (*p_++).AsRgbaColor();
\r
341 ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs )
\r
344 throw MissingArgumentException();
\r
346 rhs.value = (*p_++).AsMidiMessage();
\r
350 ReceivedMessageArgumentStream& operator>>( int64& rhs )
\r
353 throw MissingArgumentException();
\r
355 rhs = (*p_++).AsInt64();
\r
359 ReceivedMessageArgumentStream& operator>>( TimeTag& rhs )
\r
362 throw MissingArgumentException();
\r
364 rhs.value = (*p_++).AsTimeTag();
\r
368 ReceivedMessageArgumentStream& operator>>( double& rhs )
\r
371 throw MissingArgumentException();
\r
373 rhs = (*p_++).AsDouble();
\r
377 ReceivedMessageArgumentStream& operator>>( Blob& rhs )
\r
380 throw MissingArgumentException();
\r
382 (*p_++).AsBlob( rhs.data, rhs.size );
\r
386 ReceivedMessageArgumentStream& operator>>( const char*& rhs )
\r
389 throw MissingArgumentException();
\r
391 rhs = (*p_++).AsString();
\r
395 ReceivedMessageArgumentStream& operator>>( Symbol& rhs )
\r
398 throw MissingArgumentException();
\r
400 rhs.value = (*p_++).AsSymbol();
\r
404 ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs )
\r
407 throw ExcessArgumentException();
\r
414 class ReceivedMessage{
\r
415 void Init( const char *bundle, unsigned long size );
\r
417 explicit ReceivedMessage( const ReceivedPacket& packet );
\r
418 explicit ReceivedMessage( const ReceivedBundleElement& bundleElement );
\r
420 const char *AddressPattern() const { return addressPattern_; }
\r
422 // Support for non-standad SuperCollider integer address patterns:
\r
423 bool AddressPatternIsUInt32() const;
\r
424 uint32 AddressPatternAsUInt32() const;
\r
426 unsigned long ArgumentCount() const { return static_cast<unsigned long>(typeTagsEnd_ - typeTagsBegin_); }
\r
428 const char *TypeTags() const { return typeTagsBegin_; }
\r
431 typedef ReceivedMessageArgumentIterator const_iterator;
\r
433 ReceivedMessageArgumentIterator ArgumentsBegin() const
\r
435 return ReceivedMessageArgumentIterator( typeTagsBegin_, arguments_ );
\r
438 ReceivedMessageArgumentIterator ArgumentsEnd() const
\r
440 return ReceivedMessageArgumentIterator( typeTagsEnd_, 0 );
\r
443 ReceivedMessageArgumentStream ArgumentStream() const
\r
445 return ReceivedMessageArgumentStream( ArgumentsBegin(), ArgumentsEnd() );
\r
449 const char *addressPattern_;
\r
450 const char *typeTagsBegin_;
\r
451 const char *typeTagsEnd_;
\r
452 const char *arguments_;
\r
456 class ReceivedBundle{
\r
457 void Init( const char *message, unsigned long size );
\r
459 explicit ReceivedBundle( const ReceivedPacket& packet );
\r
460 explicit ReceivedBundle( const ReceivedBundleElement& bundleElement );
\r
462 uint64 TimeTag() const;
\r
464 unsigned long ElementCount() const { return elementCount_; }
\r
466 typedef ReceivedBundleElementIterator const_iterator;
\r
468 ReceivedBundleElementIterator ElementsBegin() const
\r
470 return ReceivedBundleElementIterator( timeTag_ + 8 );
\r
473 ReceivedBundleElementIterator ElementsEnd() const
\r
475 return ReceivedBundleElementIterator( end_ );
\r
479 const char *timeTag_;
\r
481 unsigned long elementCount_;
\r
488 #endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */
\r