gravitacija-perspektive/lib/OSC/OSCData.cpp

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;
}