Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Allow new messages to be created with a string in ZenGarden.h

Polished PdMessage::initWithString to make it more flexible and robust.
  • Loading branch information...
commit 5ce45ca1862f4c0f6d9276ab6a774011b1579fd1 1 parent b8fb31b
@mhroth authored
View
16 src/MessageMessageBox.cpp
@@ -46,14 +46,17 @@ MessageMessageBox::MessageMessageBox(char *initString, PdGraph *graph) : Message
// parse the first "message" for individual messages that should be sent from the outlet
vector<string> messageInitList = StaticUtils::tokenizeString((char *) messageInitListAll[0].c_str(), "\\,");
- // NOTE(mhroth): we'll be in trouble if the message has more than 16 elements!
- PdMessage *message = PD_MESSAGE_ON_STACK(16);
for (int i = 0; i < messageInitList.size(); i++) {
string initString = messageInitList[i];
+ int maxElements = (initString.size()/2)+1;
+ // NOTE(mhroth): though this is alloca is in a for loop, it is not expected that the compiler
+ // will do anything funny, like unrolling the loop, thereby causing unexpected stack overflows
+ PdMessage *message = PD_MESSAGE_ON_STACK(maxElements);
// StaticUtils::tokenizeString does not remove the trailing ";" from the
// original string. We should not process it because it will result in an empty message.
if (strcmp(initString.c_str(), ";") != 0) {
- message->initWithString(16, (char *) initString.c_str());
+ char str[initString.size()+1]; strcpy(str, initString.c_str());
+ message->initWithString(0.0, maxElements, str);
localMessageList.push_back(message->copyToHeap());
}
}
@@ -66,9 +69,12 @@ MessageMessageBox::MessageMessageBox(char *initString, PdGraph *graph) : Message
// get named destination (first element, delimited by space)
string name = string(initString, 0, initString.find(" "));
string messageString = string(initString, initString.find(" ")+2);
- message->initWithString(16, (char *) messageString.c_str());
+ int maxElements = (messageString.size()/2)+1;
+ PdMessage *message = PD_MESSAGE_ON_STACK(maxElements);
+ char str[messageString.size()+1]; strcpy(str, messageString.c_str());
+ message->initWithString(0.0, maxElements, str);
MessageNamedDestination namedDestination =
- make_pair(StaticUtils::copyString((char *) name.c_str()), message->copyToHeap());
+ make_pair(StaticUtils::copyString(name.c_str()), message->copyToHeap());
remoteMessageList.push_back(namedDestination);
}
}
View
19 src/PdContext.cpp
@@ -444,21 +444,10 @@ void PdContext::scheduleExternalMessageV(const char *receiverName, double timest
message->initWithTimestampAndNumElements(timestamp, numElements);
for (int i = 0; i < numElements; i++) { // format message
switch (messageFormat[i]) {
- case 'f': {
- message->setFloat(i, (float) va_arg(ap, double));
- break;
- }
- case 's': {
- message->setSymbol(i, (char *) va_arg(ap, char *));
- break;
- }
- case 'b': {
- message->setBang(i);
- break;
- }
- default: {
- break;
- }
+ case 'f': message->setFloat(i, (float) va_arg(ap, double)); break;
+ case 's': message->setSymbol(i, (char *) va_arg(ap, char *)); break;
+ case 'b': message->setBang(i); break;
+ default: break;
}
}
View
2  src/PdFileParser.cpp
@@ -230,7 +230,7 @@ PdGraph *PdFileParser::execute(PdMessage *initMsg, PdGraph *graph, PdContext *co
} else if (!strcmp(objectType, "declare")) {
// set environment for loading patch
char *objectInitString = strtok(NULL, ";"); // get the arguments to declare
- initMessage->initWithString(2, objectInitString); // parse them
+ initMessage->initWithString(0.0, 2, objectInitString); // parse them
if (initMessage->isSymbol(0, "-path")) {
if (initMessage->isSymbol(1)) {
// add symbol to declare directories
View
27 src/PdMessage.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2009,2011 Reality Jockey, Ltd.
+ * Copyright 2009,2011,2012 Reality Jockey, Ltd.
* info@rjdj.me
* http://rjdj.me/
*
@@ -26,14 +26,14 @@
void PdMessage::initWithSARb(unsigned int maxElements, char *initString, PdMessage *arguments,
char *buffer, unsigned int bufferLength) {
resolveString(initString, arguments, 0, buffer, bufferLength); // resolve string
- initWithString(maxElements, buffer);
+ initWithString(0.0, maxElements, buffer);
}
-void PdMessage::initWithString(unsigned int maxElements, char *initString) {
- timestamp = 0.0;
+void PdMessage::initWithString(double ts, unsigned int maxElements, char *initString) {
+ timestamp = ts;
- char *token = strtok(initString, " ;");
- if (token == NULL) {
+ char *token = strtok(initString, " ;");
+ if (token == NULL || strlen(initString) == 0) {
initWithTimestampAndBang(0.0); // just in case, there is always at least one element in a message
} else {
int i = 0;
@@ -123,6 +123,10 @@ PdMessage::~PdMessage() {
// nothing to do. Use freeMessage().
}
+unsigned int PdMessage::numBytes() {
+ return PdMessage::numBytes(numElements);
+}
+
void PdMessage::resolveSymbolsToType() {
for (int i = 0; i < numElements; i++) {
if (isSymbol(i)) {
@@ -178,6 +182,7 @@ double PdMessage::getTimestamp() {
#pragma mark initWithTimestampeAnd
void PdMessage::initWithTimestampAndNumElements(double aTimestamp, unsigned int numElem) {
+ memset(this, 0, numBytes(numElem)); // clear the entire contents of the message
timestamp = aTimestamp;
numElements = numElem;
setBang(0); // default value
@@ -288,15 +293,11 @@ void PdMessage::setList(unsigned int index) {
}
-#pragma mark -
-#pragma mark copy/free
+#pragma mark - copy/free
PdMessage *PdMessage::copyToHeap() {
- int numMessageBytes = sizeof(PdMessage) + ((numElements > 0 ? numElements-1 : 0)*sizeof(MessageAtom));
- PdMessage *pdMessage = (PdMessage *) malloc(numMessageBytes);
- pdMessage->initWithTimestampAndNumElements(timestamp, numElements);
- // copy all message type and float info (but symbol pointers must be replaced)
- memcpy(pdMessage->getElement(0), getElement(0), numElements * sizeof(MessageAtom));
+ PdMessage *pdMessage = (PdMessage *) malloc(numBytes());
+ memcpy(pdMessage, this, numBytes()); // copy entire structure (but symbol pointers must be replaced)
for (int i = 0; i < numElements; i++) {
if (isSymbol(i)) {
pdMessage->setSymbol(i, StaticUtils::copyString(getSymbol(i)));
View
22 src/PdMessage.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2009,2011 Reality Jockey, Ltd.
+ * Copyright 2009,2011,2012 Reality Jockey, Ltd.
* info@rjdj.me
* http://rjdj.me/
*
@@ -30,7 +30,7 @@
#include <string.h>
#include "MessageElementType.h"
-#define PD_MESSAGE_ON_STACK(_x) ((PdMessage *) (alloca(sizeof(PdMessage) + (((_x>0)?(_x-1):0) * sizeof(MessageAtom)))));
+#define PD_MESSAGE_ON_STACK(_x) ((PdMessage *) alloca(PdMessage::numBytes(_x)));
typedef struct MessageAtom {
MessageElementType type;
@@ -79,10 +79,11 @@ class PdMessage {
unsigned int bufferLength);
/**
- * Adds elements to the message by tokenizing the given string. Is a token is numeric then it is
- * automatically resolved to a float. Otherwise the string is interpreted as a symbol.
+ * Adds elements to the message by tokenizing the given string. If a token is numeric then it is
+ * automatically resolved to a float. Otherwise the string is interpreted as a symbol. Note that
+ * the <code>initString</code> is tokenized and should be provided in a buffer which may be edited.
*/
- void initWithString(unsigned int maxElements, char *initString);
+ void initWithString(double timestamp, unsigned int maxElements, char *initString);
/** Sets the given message element to a FLOAT or SYMBOL depending on contents of string. */
void setFloatOrSymbol(unsigned int index, char *initString);
@@ -139,6 +140,17 @@ class PdMessage {
void setBang(unsigned int index);
void setAnything(unsigned int index);
void setList(unsigned int index);
+
+ /** Returns the number of bytes in a PdMessage structure with <code>x</code> number of elements. */
+ static inline unsigned int numBytes(unsigned int x) {
+ return sizeof(PdMessage) + (((x>0)?(x-1):0) * sizeof(MessageAtom));
+ }
+
+ /**
+ * Returns the number of bytes in the PdMessage structure
+ * (as it is variable depending on the number of elements).
+ */
+ unsigned int numBytes();
private:
PdMessage();
View
14 src/ZenGarden.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2010,2011 Reality Jockey, Ltd.
+ * Copyright 2010,2011,2012 Reality Jockey, Ltd.
* info@rjdj.me
* http://rjdj.me/
*
@@ -429,12 +429,20 @@ void zg_table_set_buffer(MessageObject *table, float *buffer, unsigned int n) {
ZGMessage *zg_message_new(double timetamp, unsigned int numElements) {
PdMessage *message = PD_MESSAGE_ON_STACK(numElements);
- int numBytes = sizeof(PdMessage) + ((numElements<2)?0:(numElements-1))*sizeof(MessageAtom);
- memset(message, 0, numBytes);
message->initWithTimestampAndNumElements(timetamp, numElements);
return message->copyToHeap();
}
+ZGMessage *zg_message_new_from_string(double timetamp, const char *initString) {
+ unsigned int maxElements = (strlen(initString)/2)+1;
+ PdMessage *message = PD_MESSAGE_ON_STACK(maxElements);
+ // make a local copy of the initString so that strtok in initWithString won't break it
+ char str[strlen(initString)+1]; strcpy(str, initString);
+ // numElements set to correct number after string is parsed
+ message->initWithString(timetamp, maxElements, str);
+ return message->copyToHeap();
+}
+
void zg_message_delete(PdMessage *message) {
message->freeMessage(); // also frees any symbols on the heap
}
View
5 src/ZenGarden.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2010,2011 Reality Jockey, Ltd.
+ * Copyright 2010,2011,2012 Reality Jockey, Ltd.
* info@rjdj.me
* http://rjdj.me/
*
@@ -299,6 +299,9 @@ typedef enum ZGConnectionType {
/** Returns a new message with the given timestamp and the number of elements. */
ZGMessage *zg_message_new(double timetamp, unsigned int numElemets);
+ /** Returns a new message based on the given string. */
+ ZGMessage *zg_message_new_from_string(double timetamp, const char *initMessage);
+
/** The message is released from memory. */
void zg_message_delete(ZGMessage *message);
Please sign in to comment.
Something went wrong with that request. Please try again.