Update to OSCPack v1.1

This commit is contained in:
brunoherbelin
2020-10-20 18:27:26 +02:00
parent 65aefc9fb8
commit bbeb99056a
23 changed files with 1217 additions and 729 deletions

View File

@@ -1,8 +1,8 @@
/*
oscpack -- Open Sound Control packet manipulation library
http://www.audiomulch.com/~rossb/oscpack
oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
Any person wishing to distribute modifications to the Software is
requested to send the modifications to the original developer so that
they can be incorporated into the canonical version.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,8 +23,23 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H
#define INCLUDED_OSCRECEIVEDELEMENTS_H
/*
The text above constitutes the entire oscpack license; however,
the oscpack developer(s) also make the following non-binding requests:
Any person wishing to distribute modifications to the Software is
requested to send the modifications to the original developer so that
they can be incorporated into the canonical version. It is also
requested that these non-binding requests be included whenever the
above license is reproduced.
*/
#ifndef INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H
#define INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H
#include <cassert>
#include <cstddef>
#include <cstring> // size_t
#include "OscTypes.h"
#include "OscException.h"
@@ -37,6 +48,12 @@
namespace osc{
class MalformedPacketException : public Exception{
public:
MalformedPacketException( const char *w="malformed packet" )
: Exception( w ) {}
};
class MalformedMessageException : public Exception{
public:
MalformedMessageException( const char *w="malformed message" )
@@ -70,37 +87,73 @@ public:
class ReceivedPacket{
public:
ReceivedPacket( const char *contents, int32 size )
// Although the OSC spec is not entirely clear on this, we only support
// packets up to 0x7FFFFFFC bytes long (the maximum 4-byte aligned value
// representable by an int32). An exception will be raised if you pass a
// larger value to the ReceivedPacket() constructor.
ReceivedPacket( const char *contents, osc_bundle_element_size_t size )
: contents_( contents )
, size_( size ) {}
, size_( ValidateSize(size) ) {}
ReceivedPacket( const char *contents, std::size_t size )
: contents_( contents )
, size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {}
#if !(defined(__x86_64__) || defined(_M_X64))
ReceivedPacket( const char *contents, int size )
: contents_( contents )
, size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {}
#endif
bool IsMessage() const { return !IsBundle(); }
bool IsBundle() const;
int32 Size() const { return size_; }
osc_bundle_element_size_t Size() const { return size_; }
const char *Contents() const { return contents_; }
private:
const char *contents_;
int32 size_;
osc_bundle_element_size_t size_;
static osc_bundle_element_size_t ValidateSize( osc_bundle_element_size_t size )
{
// sanity check integer types declared in OscTypes.h
// you'll need to fix OscTypes.h if any of these asserts fail
assert( sizeof(osc::int32) == 4 );
assert( sizeof(osc::uint32) == 4 );
assert( sizeof(osc::int64) == 8 );
assert( sizeof(osc::uint64) == 8 );
if( !IsValidElementSizeValue(size) )
throw MalformedPacketException( "invalid packet size" );
if( size == 0 )
throw MalformedPacketException( "zero length elements not permitted" );
if( !IsMultipleOf4(size) )
throw MalformedPacketException( "element size must be multiple of four" );
return size;
}
};
class ReceivedBundleElement{
public:
ReceivedBundleElement( const char *size )
: size_( size ) {}
ReceivedBundleElement( const char *sizePtr )
: sizePtr_( sizePtr ) {}
friend class ReceivedBundleElementIterator;
bool IsMessage() const { return !IsBundle(); }
bool IsBundle() const;
int32 Size() const;
const char *Contents() const { return size_ + 4; }
osc_bundle_element_size_t Size() const;
const char *Contents() const { return sizePtr_ + osc::OSC_SIZEOF_INT32; }
private:
const char *size_;
const char *sizePtr_;
};
@@ -132,11 +185,11 @@ public:
private:
ReceivedBundleElement value_;
void Advance() { value_.size_ = value_.Contents() + value_.Size(); }
void Advance() { value_.sizePtr_ = value_.Contents() + value_.Size(); }
bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const
{
return value_.size_ == rhs.value_.size_;
return value_.sizePtr_ == rhs.value_.sizePtr_;
}
};
@@ -155,73 +208,79 @@ inline bool operator!=(const ReceivedBundleElementIterator& lhs,
class ReceivedMessageArgument{
public:
ReceivedMessageArgument( const char *typeTag, const char *argument )
: typeTag_( typeTag )
, argument_( argument ) {}
ReceivedMessageArgument( const char *typeTagPtr, const char *argumentPtr )
: typeTagPtr_( typeTagPtr )
, argumentPtr_( argumentPtr ) {}
friend class ReceivedMessageArgumentIterator;
const char TypeTag() const { return *typeTag_; }
char TypeTag() const { return *typeTagPtr_; }
// the unchecked methods below don't check whether the argument actually
// is of the specified type. they should only be used if you've already
// checked the type tag or the associated IsType() method.
bool IsBool() const
{ return *typeTag_ == TRUE_TYPE_TAG || *typeTag_ == FALSE_TYPE_TAG; }
{ return *typeTagPtr_ == TRUE_TYPE_TAG || *typeTagPtr_ == FALSE_TYPE_TAG; }
bool AsBool() const;
bool AsBoolUnchecked() const;
bool IsNil() const { return *typeTag_ == NIL_TYPE_TAG; }
bool IsInfinitum() const { return *typeTag_ == INFINITUM_TYPE_TAG; }
bool IsNil() const { return *typeTagPtr_ == NIL_TYPE_TAG; }
bool IsInfinitum() const { return *typeTagPtr_ == INFINITUM_TYPE_TAG; }
bool IsInt32() const { return *typeTag_ == INT32_TYPE_TAG; }
bool IsInt32() const { return *typeTagPtr_ == INT32_TYPE_TAG; }
int32 AsInt32() const;
int32 AsInt32Unchecked() const;
bool IsFloat() const { return *typeTag_ == FLOAT_TYPE_TAG; }
bool IsFloat() const { return *typeTagPtr_ == FLOAT_TYPE_TAG; }
float AsFloat() const;
float AsFloatUnchecked() const;
bool IsChar() const { return *typeTag_ == CHAR_TYPE_TAG; }
bool IsChar() const { return *typeTagPtr_ == CHAR_TYPE_TAG; }
char AsChar() const;
char AsCharUnchecked() const;
bool IsRgbaColor() const { return *typeTag_ == RGBA_COLOR_TYPE_TAG; }
bool IsRgbaColor() const { return *typeTagPtr_ == RGBA_COLOR_TYPE_TAG; }
uint32 AsRgbaColor() const;
uint32 AsRgbaColorUnchecked() const;
bool IsMidiMessage() const { return *typeTag_ == MIDI_MESSAGE_TYPE_TAG; }
bool IsMidiMessage() const { return *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG; }
uint32 AsMidiMessage() const;
uint32 AsMidiMessageUnchecked() const;
bool IsInt64() const { return *typeTag_ == INT64_TYPE_TAG; }
bool IsInt64() const { return *typeTagPtr_ == INT64_TYPE_TAG; }
int64 AsInt64() const;
int64 AsInt64Unchecked() const;
bool IsTimeTag() const { return *typeTag_ == TIME_TAG_TYPE_TAG; }
bool IsTimeTag() const { return *typeTagPtr_ == TIME_TAG_TYPE_TAG; }
uint64 AsTimeTag() const;
uint64 AsTimeTagUnchecked() const;
bool IsDouble() const { return *typeTag_ == DOUBLE_TYPE_TAG; }
bool IsDouble() const { return *typeTagPtr_ == DOUBLE_TYPE_TAG; }
double AsDouble() const;
double AsDoubleUnchecked() const;
bool IsString() const { return *typeTag_ == STRING_TYPE_TAG; }
bool IsString() const { return *typeTagPtr_ == STRING_TYPE_TAG; }
const char* AsString() const;
const char* AsStringUnchecked() const { return argument_; }
const char* AsStringUnchecked() const { return argumentPtr_; }
bool IsSymbol() const { return *typeTag_ == SYMBOL_TYPE_TAG; }
bool IsSymbol() const { return *typeTagPtr_ == SYMBOL_TYPE_TAG; }
const char* AsSymbol() const;
const char* AsSymbolUnchecked() const { return argument_; }
const char* AsSymbolUnchecked() const { return argumentPtr_; }
bool IsBlob() const { return *typeTag_ == BLOB_TYPE_TAG; }
void AsBlob( const void*& data, unsigned long& size ) const;
void AsBlobUnchecked( const void*& data, unsigned long& size ) const;
bool IsBlob() const { return *typeTagPtr_ == BLOB_TYPE_TAG; }
void AsBlob( const void*& data, osc_bundle_element_size_t& size ) const;
void AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const;
bool IsArrayBegin() const { return *typeTagPtr_ == ARRAY_BEGIN_TYPE_TAG; }
bool IsArrayEnd() const { return *typeTagPtr_ == ARRAY_END_TYPE_TAG; }
// Calculate the number of top-level items in the array. Nested arrays count as one item.
// Only valid at array start. Will throw an exception if IsArrayStart() == false.
std::size_t ComputeArrayItemCount() const;
private:
const char *typeTag_;
const char *argument_;
const char *typeTagPtr_;
const char *argumentPtr_;
};
@@ -257,7 +316,7 @@ private:
bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const
{
return value_.typeTag_ == rhs.value_.typeTag_;
return value_.typeTagPtr_ == rhs.value_.typeTagPtr_;
}
};
@@ -299,6 +358,7 @@ public:
// not sure if it would be useful to stream Nil and Infinitum
// for now it's not possible
// same goes for array boundaries
ReceivedMessageArgumentStream& operator>>( int32& rhs )
{
@@ -401,6 +461,8 @@ public:
ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs )
{
(void) rhs; // suppress unused parameter warning
if( !Eos() )
throw ExcessArgumentException();
@@ -410,18 +472,18 @@ public:
class ReceivedMessage{
void Init( const char *bundle, unsigned long size );
void Init( const char *bundle, osc_bundle_element_size_t size );
public:
explicit ReceivedMessage( const ReceivedPacket& packet );
explicit ReceivedMessage( const ReceivedBundleElement& bundleElement );
const char *AddressPattern() const { return addressPattern_; }
// Support for non-standad SuperCollider integer address patterns:
// Support for non-standard SuperCollider integer address patterns:
bool AddressPatternIsUInt32() const;
uint32 AddressPatternAsUInt32() const;
unsigned long ArgumentCount() const { return static_cast<unsigned long>(typeTagsEnd_ - typeTagsBegin_); }
uint32 ArgumentCount() const { return static_cast<uint32>(typeTagsEnd_ - typeTagsBegin_); }
const char *TypeTags() const { return typeTagsBegin_; }
@@ -452,14 +514,14 @@ private:
class ReceivedBundle{
void Init( const char *message, unsigned long size );
void Init( const char *message, osc_bundle_element_size_t size );
public:
explicit ReceivedBundle( const ReceivedPacket& packet );
explicit ReceivedBundle( const ReceivedBundleElement& bundleElement );
uint64 TimeTag() const;
unsigned long ElementCount() const { return elementCount_; }
uint32 ElementCount() const { return elementCount_; }
typedef ReceivedBundleElementIterator const_iterator;
@@ -476,11 +538,11 @@ public:
private:
const char *timeTag_;
const char *end_;
unsigned long elementCount_;
uint32 elementCount_;
};
} // namespace osc
#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */
#endif /* INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H */