root/oscpack/trunk/osc/OscReceivedElements.h

Revision 71, 12.8 kB (checked in by ross, 2 years ago)

patch to support SuperCollider? integer address patterns

  • Property svn:eol-style set to native
Line 
1 /*
2         oscpack -- Open Sound Control packet manipulation library
3         http://www.audiomulch.com/~rossb/oscpack
4
5         Copyright (c) 2004-2005 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         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.
21
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.
29 */
30 #ifndef INCLUDED_OSCRECEIVEDELEMENTS_H
31 #define INCLUDED_OSCRECEIVEDELEMENTS_H
32
33 #include "OscTypes.h"
34 #include "OscException.h"
35
36
37 namespace osc{
38
39
40 class MalformedMessageException : public Exception{
41 public:
42     MalformedMessageException( const char *w="malformed message" )
43         : Exception( w ) {}
44 };
45
46 class MalformedBundleException : public Exception{
47 public:
48     MalformedBundleException( const char *w="malformed bundle" )
49         : Exception( w ) {}
50 };
51
52 class WrongArgumentTypeException : public Exception{
53 public:
54     WrongArgumentTypeException( const char *w="wrong argument type" )
55         : Exception( w ) {}
56 };
57
58 class MissingArgumentException : public Exception{
59 public:
60     MissingArgumentException( const char *w="missing argument" )
61         : Exception( w ) {}
62 };
63
64 class ExcessArgumentException : public Exception{
65 public:
66     ExcessArgumentException( const char *w="too many arguments" )
67         : Exception( w ) {}
68 };
69
70
71 class ReceivedPacket{
72 public:
73     ReceivedPacket( const char *contents, int32 size )
74         : contents_( contents )
75         , size_( size ) {}
76
77     bool IsMessage() const { return !IsBundle(); }
78     bool IsBundle() const;
79
80     int32 Size() const { return size_; }
81     const char *Contents() const { return contents_; }
82
83 private:
84     const char *contents_;
85     int32 size_;
86 };
87
88
89 class ReceivedBundleElement{
90 public:
91     ReceivedBundleElement( const char *size )
92         : size_( size ) {}
93
94     friend class ReceivedBundleElementIterator;
95
96     bool IsMessage() const { return !IsBundle(); }
97     bool IsBundle() const;
98
99     int32 Size() const;
100     const char *Contents() const { return size_ + 4; }
101
102 private:
103     const char *size_;
104 };
105
106
107 class ReceivedBundleElementIterator{
108 public:
109         ReceivedBundleElementIterator( const char *sizePtr )
110         : value_( sizePtr ) {}
111
112         ReceivedBundleElementIterator operator++()
113         {
114         Advance();
115         return *this;
116         }
117
118     ReceivedBundleElementIterator operator++(int)
119     {
120         ReceivedBundleElementIterator old( *this );
121         Advance();
122         return old;
123     }
124
125         const ReceivedBundleElement& operator*() const { return value_; }
126
127     const ReceivedBundleElement* operator->() const { return &value_; }
128
129         friend bool operator==(const ReceivedBundleElementIterator& lhs,
130             const ReceivedBundleElementIterator& rhs );
131
132 private:
133         ReceivedBundleElement value_;
134
135         void Advance() { value_.size_ = value_.Contents() + value_.Size(); }
136
137     bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const
138     {
139         return value_.size_ == rhs.value_.size_;
140     }
141 };
142
143 inline bool operator==(const ReceivedBundleElementIterator& lhs,
144         const ReceivedBundleElementIterator& rhs )
145 {       
146         return lhs.IsEqualTo( rhs );
147 }
148
149 inline bool operator!=(const ReceivedBundleElementIterator& lhs,
150         const ReceivedBundleElementIterator& rhs )
151 {
152         return !( lhs == rhs );
153 }
154
155
156 class ReceivedMessageArgument{
157 public:
158         ReceivedMessageArgument( const char *typeTag, const char *argument )
159                 : typeTag_( typeTag )
160                 , argument_( argument ) {}
161
162     friend class ReceivedMessageArgumentIterator;
163    
164         const char TypeTag() const { return *typeTag_; }
165
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.
169
170     bool IsBool() const
171         { return *typeTag_ == TRUE_TYPE_TAG || *typeTag_ == FALSE_TYPE_TAG; }
172     bool AsBool() const;
173     bool AsBoolUnchecked() const;
174
175     bool IsNil() const { return *typeTag_ == NIL_TYPE_TAG; }
176     bool IsInfinitum() const { return *typeTag_ == INFINITUM_TYPE_TAG; }
177
178     bool IsInt32() const { return *typeTag_ == INT32_TYPE_TAG; }
179     int32 AsInt32() const;
180     int32 AsInt32Unchecked() const;
181
182     bool IsFloat() const { return *typeTag_ == FLOAT_TYPE_TAG; }
183     float AsFloat() const;
184     float AsFloatUnchecked() const;
185
186     bool IsChar() const { return *typeTag_ == CHAR_TYPE_TAG; }
187     char AsChar() const;
188     char AsCharUnchecked() const;
189
190     bool IsRgbaColor() const { return *typeTag_ == RGBA_COLOR_TYPE_TAG; }
191     uint32 AsRgbaColor() const;
192     uint32 AsRgbaColorUnchecked() const;
193
194     bool IsMidiMessage() const { return *typeTag_ == MIDI_MESSAGE_TYPE_TAG; }
195     uint32 AsMidiMessage() const;
196     uint32 AsMidiMessageUnchecked() const;
197
198     bool IsInt64() const { return *typeTag_ == INT64_TYPE_TAG; }
199     int64 AsInt64() const;
200     int64 AsInt64Unchecked() const;
201
202     bool IsTimeTag() const { return *typeTag_ == TIME_TAG_TYPE_TAG; }
203     uint64 AsTimeTag() const;
204     uint64 AsTimeTagUnchecked() const;
205
206     bool IsDouble() const { return *typeTag_ == DOUBLE_TYPE_TAG; }
207     double AsDouble() const;
208     double AsDoubleUnchecked() const;
209
210     bool IsString() const { return *typeTag_ == STRING_TYPE_TAG; }
211     const char* AsString() const;
212     const char* AsStringUnchecked() const { return argument_; }
213
214     bool IsSymbol() const { return *typeTag_ == SYMBOL_TYPE_TAG; }
215     const char* AsSymbol() const;
216     const char* AsSymbolUnchecked() const { return argument_; }
217
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;
221    
222 private:
223         const char *typeTag_;
224         const char *argument_;
225 };
226
227
228 class ReceivedMessageArgumentIterator{
229 public:
230         ReceivedMessageArgumentIterator( const char *typeTags, const char *arguments )
231         : value_( typeTags, arguments ) {}
232
233         ReceivedMessageArgumentIterator operator++()
234         {
235         Advance();
236         return *this;
237         }
238
239     ReceivedMessageArgumentIterator operator++(int)
240     {
241         ReceivedMessageArgumentIterator old( *this );
242         Advance();
243         return old;
244     }
245
246         const ReceivedMessageArgument& operator*() const { return value_; }
247
248     const ReceivedMessageArgument* operator->() const { return &value_; }
249
250         friend bool operator==(const ReceivedMessageArgumentIterator& lhs,
251             const ReceivedMessageArgumentIterator& rhs );
252
253 private:
254         ReceivedMessageArgument value_;
255
256         void Advance();
257
258     bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const
259     {
260         return value_.typeTag_ == rhs.value_.typeTag_;
261     }
262 };
263
264 inline bool operator==(const ReceivedMessageArgumentIterator& lhs,
265         const ReceivedMessageArgumentIterator& rhs )
266 {       
267         return lhs.IsEqualTo( rhs );
268 }
269
270 inline bool operator!=(const ReceivedMessageArgumentIterator& lhs,
271         const ReceivedMessageArgumentIterator& rhs )
272 {       
273         return !( lhs == rhs );
274 }
275
276
277 class ReceivedMessageArgumentStream{
278     friend class ReceivedMessage;
279     ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin,
280             const ReceivedMessageArgumentIterator& end )
281         : p_( begin )
282         , end_( end ) {}
283
284     ReceivedMessageArgumentIterator p_, end_;
285    
286 public:
287
288     // end of stream
289     bool Eos() const { return p_ == end_; }
290
291     ReceivedMessageArgumentStream& operator>>( bool& rhs )
292     {
293         if( Eos() )
294             throw MissingArgumentException();
295
296         rhs = (*p_++).AsBool();
297         return *this;
298     }
299
300     // not sure if it would be useful to stream Nil and Infinitum
301     // for now it's not possible
302
303     ReceivedMessageArgumentStream& operator>>( int32& rhs )
304     {
305         if( Eos() )
306             throw MissingArgumentException();
307
308         rhs = (*p_++).AsInt32();
309         return *this;
310     }     
311
312     ReceivedMessageArgumentStream& operator>>( float& rhs )
313     {
314         if( Eos() )
315             throw MissingArgumentException();
316
317         rhs = (*p_++).AsFloat();
318         return *this;
319     }
320
321     ReceivedMessageArgumentStream& operator>>( char& rhs )
322     {
323         if( Eos() )
324             throw MissingArgumentException();
325
326         rhs = (*p_++).AsChar();
327         return *this;
328     }
329
330     ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs )
331     {
332         if( Eos() )
333             throw MissingArgumentException();
334
335         rhs.value = (*p_++).AsRgbaColor();
336         return *this;
337     }
338
339     ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs )
340     {
341         if( Eos() )
342             throw MissingArgumentException();
343
344         rhs.value = (*p_++).AsMidiMessage();
345         return *this;
346     }
347
348     ReceivedMessageArgumentStream& operator>>( int64& rhs )
349     {
350         if( Eos() )
351             throw MissingArgumentException();
352
353         rhs = (*p_++).AsInt64();
354         return *this;
355     }
356    
357     ReceivedMessageArgumentStream& operator>>( TimeTag& rhs )
358     {
359         if( Eos() )
360             throw MissingArgumentException();
361
362         rhs.value = (*p_++).AsTimeTag();
363         return *this;
364     }
365
366     ReceivedMessageArgumentStream& operator>>( double& rhs )
367     {
368         if( Eos() )
369             throw MissingArgumentException();
370
371         rhs = (*p_++).AsDouble();
372         return *this;
373     }
374
375     ReceivedMessageArgumentStream& operator>>( Blob& rhs )
376     {
377         if( Eos() )
378             throw MissingArgumentException();
379
380         (*p_++).AsBlob( rhs.data, rhs.size );
381         return *this;
382     }
383    
384     ReceivedMessageArgumentStream& operator>>( const char*& rhs )
385     {
386         if( Eos() )
387             throw MissingArgumentException();
388
389         rhs = (*p_++).AsString();
390         return *this;
391     }
392    
393     ReceivedMessageArgumentStream& operator>>( Symbol& rhs )
394     {
395         if( Eos() )
396             throw MissingArgumentException();
397
398         rhs.value = (*p_++).AsSymbol();
399         return *this;
400     }
401
402     ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs )
403     {
404         if( !Eos() )
405             throw ExcessArgumentException();
406
407         return *this;
408     }
409 };
410
411
412 class ReceivedMessage{
413     void Init( const char *bundle, unsigned long size );
414 public:
415     explicit ReceivedMessage( const ReceivedPacket& packet );
416     explicit ReceivedMessage( const ReceivedBundleElement& bundleElement );
417
418         const char *AddressPattern() const { return addressPattern_; }
419
420         // Support for non-standad SuperCollider integer address patterns:
421         bool AddressPatternIsUInt32() const;
422         uint32 AddressPatternAsUInt32() const;
423
424         unsigned long ArgumentCount() const { return static_cast<unsigned long>(typeTagsEnd_ - typeTagsBegin_); }
425
426     const char *TypeTags() const { return typeTagsBegin_; }
427
428
429     typedef ReceivedMessageArgumentIterator const_iterator;
430    
431         ReceivedMessageArgumentIterator ArgumentsBegin() const
432     {
433         return ReceivedMessageArgumentIterator( typeTagsBegin_, arguments_ );
434     }
435      
436         ReceivedMessageArgumentIterator ArgumentsEnd() const
437     {
438         return ReceivedMessageArgumentIterator( typeTagsEnd_, 0 );
439     }
440
441     ReceivedMessageArgumentStream ArgumentStream() const
442     {
443         return ReceivedMessageArgumentStream( ArgumentsBegin(), ArgumentsEnd() );
444     }
445
446 private:
447         const char *addressPattern_;
448         const char *typeTagsBegin_;
449         const char *typeTagsEnd_;
450     const char *arguments_;
451 };
452
453
454 class ReceivedBundle{
455     void Init( const char *message, unsigned long size );
456 public:
457     explicit ReceivedBundle( const ReceivedPacket& packet );
458     explicit ReceivedBundle( const ReceivedBundleElement& bundleElement );
459
460     uint64 TimeTag() const;
461
462     unsigned long ElementCount() const { return elementCount_; }
463
464     typedef ReceivedBundleElementIterator const_iterator;
465    
466         ReceivedBundleElementIterator ElementsBegin() const
467     {
468         return ReceivedBundleElementIterator( timeTag_ + 8 );
469     }
470      
471         ReceivedBundleElementIterator ElementsEnd() const
472     {
473         return ReceivedBundleElementIterator( end_ );
474     }
475
476 private:
477     const char *timeTag_;
478     const char *end_;
479     unsigned long elementCount_;
480 };
481
482
483 } // namespace osc
484
485
486 #endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */
Note: See TracBrowser for help on using the browser.