All pastes #953750 Raw Edit

Unnamed

public text v1 · immutable
#953750 ·published 2008-03-23 09:36 UTC
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;
}