rendered paste body#include "OSC_Message.h"
OSC_Message *OSC_Message_init() {
OSC_Message *msg = calloc( 1, sizeof(OSC_Message) );
msg->path = malloc( InitialPathSize );
msg->types = malloc( InitialTypesSize );
msg->data = malloc( InitialDataSize );
msg->pathSize = InitialPathSize;
msg->typeSize = InitialTypesSize;
msg->dataSize = InitialDataSize;
msg->pathComponents = PathComponents_init();
OSC_Message_reset(msg);
return msg;
}
void OSC_Message_reset(OSC_Message* message) {
message->path[0] = '\0';
message->types[0] = ',';
message->types[1] = 0;
message->numTypes = 1;
message->numArguments = 0;
message->dataOffset = 0;
if(message->arguments) {
free( message->arguments );
message->arguments = NULL;
}
PathComponents_reset(message->pathComponents);
}
void OSC_Message_resetArguments(OSC_Message* message) {
message->types[0] = ',';
message->types[1] = 0;
message->numTypes = 1;
message->numArguments = 0;
message->dataOffset = 0;
}
void OSC_Message_destroy(OSC_Message* message) {
free( message->path );
free( message->types );
free( message->arguments );
PathComponents_destroy(message->pathComponents);
free( message );
}
OSC_Argument **OSC_Message_allocNumArguments(OSC_Message *message, int numArguments) {
message->arguments = calloc(numArguments + 1, sizeof(OSC_Argument*));
message->numArguments = numArguments;
return message->arguments;
}
int OSC_Message_parseMessageFromBuffer(OSC_Message *message, char *buffer, int bufferSize) {
OSC_Argument **argv;
int j, size, numArguments;
char *path, *types, *arguments, *argPtr;
path = buffer;
types = buffer + OSC_Message_stringSize(path);
numArguments = strlen(types) - 1;
arguments = types + OSC_Message_stringSize(types);
argPtr = arguments;
message->virtualArgumentPtr = argPtr;
// make sure we have a valid message...
if( *types != ',' ) {
printf("Invalid OSC message\n");
return -1;
}
//printf("Path: %s Num Args: %d Types: %s\n", path, numArguments, types);
OSC_Message_setPath(message, path);
OSC_Message_setTypes(message, types);
argv = OSC_Message_allocNumArguments(message, numArguments);
//printf("types=%s numArgs=%d\n", types, numArguments);
for(j = 1; j < numArguments+1; j++) {
size = OSC_Message_argumentSize( types[j], argPtr );
argv[j-1] = (OSC_Argument*)argPtr;
OSC_Message_convertArgumentEndian(types[j], argPtr);
argPtr += size;
}
return 0;
}
void OSC_Message_copyArguments(OSC_Message *message) {
int j;
int size;
int32_t *nptr;
OSC_cast32 unionCast;
char *dataPtr;
dataPtr = message->virtualArgumentPtr;
for(j = 0; j < message->numArguments; j++) {
size = OSC_Message_argumentSize( message->types[j+1], dataPtr );
switch(message->types[j+1]) {
case OSC_INT32:
nptr = OSC_Message_addData(message, sizeof(int32_t));
unionCast.i = *((int*)dataPtr);
*nptr = htonl(unionCast.nl); // 32-bit byte-swap if need be
break;
case OSC_FLOAT:
nptr = OSC_Message_addData(message, sizeof(float));
unionCast.f = *((float*)dataPtr);
*nptr = htonl(unionCast.nl); // 32-bit byte-swap if need be
break;
case OSC_STRING:
nptr = OSC_Message_addData(message, size);
strncpy((char*)nptr, dataPtr, size);
break;
case OSC_BLOB:
// TODO
//OSC_Message_addBlobArgument(message, dataPtr);
break;
}
dataPtr += size;
}
}
int OSC_Message_setPath(OSC_Message* message, char *path) {
int pathLen = strlen(path);
if(pathLen > message->pathSize) {
char *result;
if(pathLen > PathSizeLimit) {
printf("Attempted to go beyond path size limit (pathLen=%d)\n", pathLen);
return -1;
}
result = realloc(message->path, pathLen+1);
if(result) {
message->path = result; // only on success, reassign
message->pathSize = pathLen+1;
}
}
strcpy(message->path, path);
return 0;
}
char *OSC_Message_path(OSC_Message* message) {
return message->path;
}
//strncmp
int OSC_Message_parsePath(OSC_Message *message) {
return PathComponents_parse(message->pathComponents, message->path);
}
PathComponents *OSC_Message_pathComponents(OSC_Message *message) {
return message->pathComponents;
}
int OSC_Message_setTypes(OSC_Message* message, char *types) {
int typesLen = strlen(types);
if( OSC_Message_resizeTypes(message, typesLen+1) < 0 ) {
return -1;
}
strcpy(message->types, types);
return 0;
}
int OSC_Message_resizeTypes(OSC_Message *message, int typesLen) {
if(typesLen > message->typeSize) {
char *result;
if(typesLen > TypeSizeLimit) {
printf("Attempted to go beyond types size limit (typesLen=%d)\n", typesLen);
return -1;
}
result = realloc(message->types, typesLen+1);
if(result) {
message->types = result; // only on success, reassign
message->typeSize = typesLen+1;
}
}
return 0;
}
int OSC_Message_resizeData(OSC_Message *message, int newLen) {
if(newLen > message->dataSize) {
char *result;
if(newLen > DataSizeLimit) {
printf("Attempted to go beyond data size limit (newLen=%d)\n", newLen);
return -1;
}
result = realloc(message->data, newLen);
if(result) {
message->data = result;
message->dataSize = newLen;
}
}
return 0;
}
char *OSC_Message_types(OSC_Message* message) {
return message->types;
}
OSC_Argument **OSC_Message_arguments(OSC_Message* message) {
return message->arguments;
}
int OSC_Message_numArguments(OSC_Message* message) {
return message->numArguments;
}
int OSC_Message_addTypeChar(OSC_Message *message, char type) {
// check the size
if(message->numTypes >= message->typeSize) {
int newSize = message->typeSize;
while( newSize <= message->numTypes && newSize < TypeSizeLimit ) {
newSize *= 2;
}
// we need to resize
OSC_Message_resizeTypes(message, newSize);
}
// add the type
message->types[ message->numTypes ] = type;
message->numTypes++;
message->types[ message->numTypes ] = '\0'; // terminate char
return 0; // success
}
void *OSC_Message_addData(OSC_Message *message, size_t size) {
void *result;
int newSize = message->dataOffset + size;
OSC_Message_resizeData(message, newSize);
result = (void*) ((char*)message->data + message->dataOffset);
message->dataOffset += size;
return result;
}
void OSC_Message_addIntArgument(OSC_Message *message, int32_t argument) {
OSC_cast32 unionCast;
int32_t *nptr = OSC_Message_addData(message, sizeof(argument));
unionCast.i = argument;
// add type
if( !OSC_Message_addTypeChar(message, OSC_INT32) ) {
// copy to data buffer
*nptr = htonl(unionCast.nl); // 32-bit byte-swap if need be
}
}
void OSC_Message_addFloatArgument(OSC_Message *message, float argument) {
OSC_cast32 unionCast;
int32_t *nptr = OSC_Message_addData(message, sizeof(argument));
unionCast.f = argument;
// add type
if( !OSC_Message_addTypeChar(message, OSC_FLOAT) ) {
// copy to data buffer
*nptr = htonl(unionCast.nl); // 32-bit byte-swap if need be
}
}
void OSC_Message_addStringArgument(OSC_Message *message, char *argument) {
const int size = OSC_Message_stringSize(argument);
char *nptr = OSC_Message_addData(message, size);
if( !OSC_Message_addTypeChar(message, OSC_STRING) ) {
strncpy(nptr, argument, size);
}
}
// note: this function has not been fully tested...
void OSC_Message_addBlobArgument(OSC_Message *message, OSC_Blob *argument) {
int size = OSC_Blob_size(argument);
int32_t dataSize = htonl(OSC_Blob_dataSize(argument)); // 32-bit byte-swap if need be
char *nptr = OSC_Message_addData(message, size);
if( !OSC_Message_addTypeChar(message, OSC_BLOB) ) {
// clear the last few bytes
memset(nptr + size - 4, 0, 4);
memcpy(nptr, &dataSize, sizeof(dataSize));
memcpy(nptr + sizeof(int32_t), OSC_Blob_dataPtr(argument), OSC_Blob_dataSize(argument));
}
}
// utility function for debugging a message's arguments
void OSC_Message_displayArguments(OSC_Message *message) {
int j;
for(j = 1; j < message->numArguments + 1; j++) {
switch( message->types[j] ) {
case OSC_INT32:
printf("%d=%d ", j-1, message->arguments[j-1]->i);
// OSC_Message_ArgumentInt32( message->arguments[j] ));
break;
case OSC_FLOAT:
printf("%d=%f ", j-1, message->arguments[j-1]->f);
//OSC_Message_ArgumentFloat32( message->arguments[j] ));
break;
case OSC_STRING:
printf("%d=%s ", j-1, message->arguments[j-1]);
break;
}
}
}
int OSC_Message_stringSize(const char *s) {
return 4 * (strlen(s) / 4 + 1);
}
size_t OSC_Message_argumentSize(OSC_Type type, void *data) {
switch(type) {
case OSC_INT32:
case OSC_FLOAT:
return 4;
case OSC_STRING:
return OSC_Message_stringSize((char *)data);
case OSC_BLOB:
return OSC_Blob_size((OSC_Blob*)data);
default:
fprintf(stderr, "warning: unhandled OSC type '%c' at %s:%d\n", type, __FILE__, __LINE__);
return 0;
}
return 0;
}
void OSC_Message_convertArgumentEndian(OSC_Type type, void *data) {
switch (type) {
case OSC_FLOAT:
case OSC_BLOB:
case OSC_INT32:
*(int32_t *)data = htonl(*(int32_t *)data); // 32-bit byte-swap if need be
break;
case OSC_STRING:
break;
default:
fprintf(stderr, "warning: unhandled OSC type '%c' at %s:%d\n",
type, __FILE__, __LINE__);
break;
}
}
size_t OSC_Message_size(OSC_Message *message) {
return OSC_Message_stringSize(message->path) + OSC_Message_stringSize(message->types) + message->dataOffset;
}
int OSC_Message_serializeToNetworkString(OSC_Message *message, char **string) {
size_t size = OSC_Message_size(message) + sizeof(int);
if( size > 0 ) {
int pathSize, typesSize;
OSC_cast32 unionCast;
uint32_t header;
unionCast.i = size - sizeof(int);
header = htonl(unionCast.nl); // 32-bit byte-swap if need be
*string = calloc(1, size);
pathSize = OSC_Message_stringSize(message->path);
typesSize = OSC_Message_stringSize(message->types);
memcpy(*string, (void*)&header, sizeof(int));
strcpy(*string + sizeof(int), message->path);
strcpy(*string + pathSize + sizeof(int), message->types);
memcpy(*string + pathSize + typesSize + sizeof(int), message->data, message->dataOffset);
}
return size;
}