336 lines
6.9 KiB
C++
336 lines
6.9 KiB
C++
|
|
#include "OSCData.h"
|
|
|
|
|
|
osctime_t zerotime = {0,0};
|
|
/*=============================================================================
|
|
CONSTRUCTORS
|
|
|
|
overloaded methods for each of the types which will
|
|
set the type flag, the size (in bytes), and the data
|
|
=============================================================================*/
|
|
|
|
|
|
OSCData::OSCData(const char * s){
|
|
error = OSC_OK;
|
|
type = 's';
|
|
bytes = (strlen(s) + 1);
|
|
//own the data
|
|
char * mem = (char *) malloc(bytes);
|
|
if (mem == NULL){
|
|
error = ALLOCFAILED;
|
|
} else {
|
|
strcpy(mem, s);
|
|
data.s = mem;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
OSCData::OSCData(int32_t i){
|
|
error = OSC_OK;
|
|
type = 'i';
|
|
bytes = 4;
|
|
data.i = i;
|
|
}
|
|
#ifndef ESPxx
|
|
OSCData::OSCData(int i){
|
|
error = OSC_OK;
|
|
type = 'i';
|
|
bytes = 4;
|
|
data.i = i;
|
|
}
|
|
#endif
|
|
OSCData::OSCData(unsigned int i){
|
|
error = OSC_OK;
|
|
type = 'i';
|
|
bytes = 4;
|
|
data.i = i;
|
|
}
|
|
#if defined(__SAM3X8E__)
|
|
OSCData::OSCData(int16_t i){
|
|
error = OSC_OK;
|
|
type = 'i';
|
|
bytes = 4;
|
|
data.i = i;
|
|
}
|
|
#endif
|
|
|
|
OSCData::OSCData(float f){
|
|
error = OSC_OK;
|
|
type = 'f';
|
|
bytes = 4;
|
|
data.f = f;
|
|
}
|
|
|
|
OSCData::OSCData(osctime_t t){
|
|
error = OSC_OK;
|
|
type = 't';
|
|
bytes = 8;
|
|
data.time = t;
|
|
}
|
|
OSCData::OSCData(boolean b){
|
|
error = OSC_OK;
|
|
type = b?'T':'F';
|
|
bytes = 0;
|
|
}
|
|
|
|
|
|
OSCData::OSCData(double d){
|
|
error = OSC_OK;
|
|
bytes = sizeof(double);
|
|
//if it's not 8 bytes it's not a true double
|
|
if (bytes == 8){
|
|
type = 'd';
|
|
data.d = d;
|
|
} else {
|
|
type = 'f';
|
|
data.f = d;
|
|
}
|
|
}
|
|
|
|
OSCData::OSCData(uint8_t * b, int len){
|
|
error = OSC_OK;
|
|
type = 'b';
|
|
bytes = len + 4;
|
|
//add the size to the front of the blob
|
|
uint32_t len32 = (uint32_t) len;
|
|
//make sure the length is endian-safe
|
|
len32 = BigEndian(len32);
|
|
uint8_t * lenPtr = (uint8_t *) (& len32);
|
|
//own the data
|
|
if(bytes>0)
|
|
{
|
|
|
|
uint8_t * mem = (uint8_t * ) malloc(bytes);
|
|
if (mem == NULL){
|
|
error = ALLOCFAILED;
|
|
} else {
|
|
//copy over the blob length
|
|
memcpy(mem, lenPtr, 4);
|
|
//copy over the blob data
|
|
memcpy(mem + 4, b, len);
|
|
data.b = mem;
|
|
}
|
|
}
|
|
else
|
|
data.b = 0;
|
|
}
|
|
|
|
OSCData::OSCData (OSCData * datum){
|
|
error = OSC_OK;
|
|
type = datum->type;
|
|
bytes = datum->bytes;
|
|
if ( (type == 'i') || (type == 'f') || (type == 'd') || (type == 't')
|
|
|| (type == 'h') || (type == 'c') || (type == 'r') || (type == 'm')
|
|
)
|
|
{
|
|
data = datum->data;
|
|
} else if ((type == 's') || (type == 'b')){
|
|
//allocate a new piece of memory
|
|
uint8_t * mem = (uint8_t * ) malloc(bytes);
|
|
if (mem == NULL){
|
|
error = ALLOCFAILED;
|
|
} else {
|
|
//copy over the blob length
|
|
memcpy(mem, datum->data.b, bytes);
|
|
data.b = mem;
|
|
}
|
|
}
|
|
}
|
|
|
|
//DESTRUCTOR
|
|
OSCData::~OSCData(){
|
|
//if there are no bytes, there is nothing to free
|
|
if (bytes>0){
|
|
//if the data is of type 's' or 'b', need to free that memory
|
|
if (type == 's'){
|
|
free(data.s);
|
|
}else if( type == 'b'){
|
|
free(data.b);
|
|
}
|
|
}
|
|
}
|
|
|
|
//sets just the type as a message placeholder
|
|
//no data
|
|
OSCData::OSCData(char t){
|
|
error = (t == 'T' || t == 'F') ? OSC_OK : INVALID_OSC;
|
|
type = t;
|
|
bytes = 0;
|
|
}
|
|
|
|
/*=============================================================================
|
|
GETTERS
|
|
|
|
perform a safety check to make sure the data type matches the request
|
|
otherwise returns NULL
|
|
=============================================================================*/
|
|
|
|
int32_t OSCData::getInt(){
|
|
if (type == 'i'){
|
|
return data.i;
|
|
} else {
|
|
#ifndef ESPxx
|
|
return (int32_t)NULL;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
}
|
|
osctime_t OSCData::getTime(){
|
|
if (type == 't'){
|
|
return data.time;
|
|
} else {
|
|
|
|
return zerotime;
|
|
}
|
|
}
|
|
float OSCData::getFloat(){
|
|
if (type == 'f'){
|
|
return data.f;
|
|
} else {
|
|
#ifndef ESPxx
|
|
return (float)NULL;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
double OSCData::getDouble(){
|
|
if (type == 'd'){
|
|
return data.d;
|
|
} else {
|
|
#ifndef ESPxx
|
|
return (double)NULL;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
}
|
|
bool OSCData::getBoolean(){
|
|
if (type == 'T'){
|
|
return true;
|
|
} else if (type=='F'){
|
|
return false;
|
|
}
|
|
else
|
|
#ifndef ESPxx
|
|
return NULL;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
|
|
// no-safety-check straightforward way to fill the passed buffer
|
|
// with the received string
|
|
int OSCData::getString(char * strBuffer){
|
|
if (type == 's'){
|
|
strncpy(strBuffer, data.s, bytes);
|
|
return bytes;
|
|
} else {
|
|
#ifndef ESPxx
|
|
return (int)NULL;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// it's possible to pass strBuffer's size as argument (length)
|
|
// in order to check that it won't be overflown
|
|
int OSCData::getString(char * strBuffer, int length){
|
|
if (type == 's' && bytes <= length){
|
|
strncpy(strBuffer, data.s, bytes);
|
|
return bytes;
|
|
} else {
|
|
#ifndef ESPxx
|
|
return (int)NULL;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// Here we can get only a part of the string
|
|
int OSCData::getString(char * strBuffer, int length, int offset, int size)
|
|
{
|
|
int maxLen = bytes - offset;
|
|
if (type == 's' && maxLen >= 0 && size <= maxLen && size <= length){
|
|
strncpy(strBuffer, data.s + offset, size);
|
|
return size;
|
|
} else {
|
|
#ifndef ESPxx
|
|
return (int)NULL;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// no-safety-check straightforward way to fill the passed buffer
|
|
// with the contents of the received blob
|
|
int OSCData::getBlob(uint8_t * blobBuffer){
|
|
// read the blob length
|
|
int blobLength = getBlobLength();
|
|
|
|
if (type == 'b'){
|
|
memcpy(blobBuffer, data.b + 4, blobLength);
|
|
return blobLength;
|
|
} else {
|
|
#ifndef ESPxx
|
|
return (int)NULL;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// it's possible to pass blobBuffer's size as argument (length)
|
|
// in order to check that it won't be overflown
|
|
int OSCData::getBlob(uint8_t * blobBuffer, int length){
|
|
//jump over the first 4 bytes which encode the length
|
|
int blobLength = bytes-4;
|
|
if (type == 'b' && blobLength <= length){
|
|
memcpy(blobBuffer, data.b + 4, blobLength);
|
|
return blobLength;
|
|
} else {
|
|
#ifndef ESPxx
|
|
return (int)NULL;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// Here we can get only a part of the blob
|
|
int OSCData::getBlob(uint8_t * blobBuffer, int length, int offset, int size){
|
|
//jump over the first 4 bytes which encode the length
|
|
int blobLength = bytes-4-offset;
|
|
if (type == 'b' && blobLength >= 0 && size <= blobLength && size <= length){
|
|
memcpy(blobBuffer, data.b + 4 + offset, size);
|
|
return size;
|
|
} else {
|
|
#ifndef ESPxx
|
|
return (int)NULL;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
const uint8_t* OSCData::getBlob() {
|
|
return type == 'b' ? data.b + 4 : NULL;
|
|
}
|
|
|
|
int OSCData::getBlobLength(){
|
|
if (type == 'b'){
|
|
//jump over the first 4 bytes which encode the length
|
|
return bytes-4;
|
|
}
|
|
return -1;
|
|
}
|