/
PdMessage.h
164 lines (136 loc) · 6.18 KB
/
PdMessage.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
* Copyright 2009,2011,2012 Reality Jockey, Ltd.
* info@rjdj.me
* http://rjdj.me/
*
* This file is part of ZenGarden.
*
* ZenGarden is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZenGarden is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ZenGarden. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _PD_MESSAGE_H_
#define _PD_MESSAGE_H_
#include <alloca.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MessageElementType.h"
#define PD_MESSAGE_ON_STACK(_x) ((PdMessage *) alloca(PdMessage::numBytes(_x)));
typedef struct MessageAtom {
MessageElementType type;
union {
float constant;
char *symbol;
};
} MessageAtom;
/** Implements a Pd message. */
class PdMessage {
public:
/**
* Resolve arguments in a string with a given argument list into the given <code>buffer</code>
* with <code>bufferLength</code>.
* The <code>offset</code> parameter adjusts the resolution of the <code>$</code> argument.
* In the case of message boxes, <code>$0</code> refers to the graph id, which is the first
* argument in a graph's list of arguments. For all other objects, <code>$1</code> refers
* to the first (0th) element of the argument. The offset is used to distinguish between these
* cases, by offsetting the argument index resolution.
*/
static void resolveString(char *initString, PdMessage *arguments, unsigned int offset,
char *buffer, unsigned int bufferLength);
/**
* Converts symbolic elements referring to message element types (e.g., float or f) to those
* types. For instance, if an element has a symbolic value of "float", then that element is
* converted into one of type <code>FLOAT</code>.
*/
void resolveSymbolsToType();
void initWithTimestampAndNumElements(double aTimestamp, unsigned int numElem);
void initWithTimestampAndFloat(double aTimestamp, float constant);
void initWithTimestampAndBang(double aTimestamp);
void initWithTimestampAndSymbol(double aTimestamp, char *symbol);
/**
* Initialise the message with a string, arguments, and a resolution buffer. The string will
* be resolved into the buffer using the arguments. Any resolved strings in the message will
* point into the resolution buffer. The buffer is generally intended to be a temporary storage
* for such strings while objects are created.
*/
void initWithSARb(unsigned int maxElements, char *initString, PdMessage *arguments, char *buffer,
unsigned int bufferLength);
/**
* 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(double timestamp, unsigned int maxElements, char *initString);
/** Sets the given message element to a FLOAT or SYMBOL depending on contents of string. */
void parseAndSetMessageElement(unsigned int index, char *initString);
MessageAtom *getElement(unsigned int index);
bool atomIsEqualTo(unsigned int index, MessageAtom *messageAtom);
int getNumElements();
/** Get the global timestamp of this message (in milliseconds). */
double getTimestamp();
/** Set the global timestamp of this message (in milliseconds). */
void setTimestamp(double timestamp); // NOTE(mhroth): necessary?
/**
* Returns a copy of the message to the heap. Messages usually only exist temporarily on the
* stack and should be copied to the heap if it should persist. Symbol pointers are copied
* independently to the heap.
*/
PdMessage *copyToHeap();
/** The message memory is freed from the heap, including symbols. */
void freeMessage();
/**
* Create a string representation of the message. Suitable for use by the print object.
* The resulting string must be <code>free()</code>ed by the caller.
*/
char *toString();
/** Convenience function to determine if a particular message element is a float. */
bool isFloat(unsigned int index);
bool isSymbol(unsigned int index);
bool isSymbol(unsigned int index, const char *test);
bool isBang(unsigned int index);
MessageElementType getType(unsigned int index);
/**
* Convenience function to get the float value from a particular message element. The user
* is responsible for checking that the indexed <code>MessageElement</code> is truly a float.
* This function does not check for the existence of the message element.
*/
float getFloat(unsigned int index);
char *getSymbol(unsigned int index);
/**
* Convenience function to set a message element to a float value. This function does not check
* for the existence of a message element.
*/
void setFloat(unsigned int index, float value);
void setSymbol(unsigned int index, char *symbol);
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();
~PdMessage();
double timestamp;
int numElements;
MessageAtom messageAtom;
};
#endif // _PD_MESSAGE_H_