common: prevent buffer overflow
[supercollider.git] / include / plugin_interface / sc_msg_iter.h
blob5dc4156ec01a766aa3e2e75dcceccb846ff58001
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #ifndef _sc_msg_iter_
23 #define _sc_msg_iter_
25 #include "SC_Endian.h"
26 #include "SC_Types.h"
27 #include <string.h>
29 // return the ptr to the byte after the OSC string.
30 inline const char* OSCstrskip(const char *str)
32 // while (str[3]) { str += 4; }
33 // return str + 4;
34 do { str += 4; } while (str[-1]);
35 return str;
38 // returns the number of bytes (including padding) for an OSC string.
39 inline int OSCstrlen(const char *strin)
41 return OSCstrskip(strin) - strin;
44 // returns a float, converting an int if necessary
45 inline float32 OSCfloat(const char* inData)
47 elem32 elem;
48 elem.u = ntohl(*(uint32*)inData);
49 return elem.f;
52 inline int32 OSCint(const char* inData)
54 return (int32)ntohl(*(uint32*)inData);
57 inline int64 OSCtime(const char* inData)
59 return ((int64)ntohl(*(uint32*)inData) << 32) + (ntohl(*(uint32*)(inData + 4)));
62 inline float64 OSCdouble(const char* inData)
64 elem64 slot;
65 slot.i = ((int64)ntohl(*(uint32*)inData) << 32) + (ntohl(*(uint32*)(inData + 4)));
66 return slot.f;
69 struct sc_msg_iter
71 const char *data, *rdpos, *endpos, *tags;
72 int size, count;
74 sc_msg_iter();
75 sc_msg_iter(int inSize, const char* inData);
76 void init(int inSize, const char* inData);
77 int32 geti(int32 defaultValue = 0);
78 float32 getf(float32 defaultValue = 0.f);
79 float64 getd(float64 defaultValue = 0.f);
80 const char *gets(const char* defaultValue = 0);
81 int32 *gets4(char* defaultValue = 0);
82 size_t getbsize();
83 void getb(char* outData, size_t inSize);
84 void skipb();
85 int remain() { return endpos - rdpos; }
87 char nextTag(char defaultTag = 'f') { return tags ? tags[count] : defaultTag; }
90 inline sc_msg_iter::sc_msg_iter()
94 inline sc_msg_iter::sc_msg_iter(int inSize, const char* inData)
96 init(inSize, inData);
99 inline void sc_msg_iter::init(int inSize, const char* inData)
101 data = inData;
102 size = inSize;
103 endpos = data + size;
104 count = 0;
105 if (data[0] == ',') {
106 tags = data+1;
107 rdpos = OSCstrskip(data);
108 } else {
109 tags = 0;
110 rdpos = data;
114 inline int32 sc_msg_iter::geti(int32 defaultValue)
116 int value;
117 if (remain() <= 0) return defaultValue;
118 if (tags) {
119 if (tags[count] == 'i') {
120 value = OSCint(rdpos);
121 rdpos += sizeof(int32);
122 } else if (tags[count] == 'f') {
123 value = (int32)OSCfloat(rdpos);
124 rdpos += sizeof(float32);
125 } else if (tags[count] == 's') {
126 /* value = atoi(rdpos); */
127 value = defaultValue;
128 rdpos = OSCstrskip(rdpos);
129 } else if (tags[count] == 'b') {
130 value = defaultValue;
131 skipb();
132 } else {
133 /* this is dangerous, as rdpos is not
134 advanced accordingly while count++ takes
135 place */
136 value = defaultValue;
138 } else {
139 value = (int)OSCint(rdpos);
140 rdpos += sizeof(int32);
142 count ++;
143 return value;
146 inline float32 sc_msg_iter::getf(float32 defaultValue)
148 float32 value;
149 if (remain() <= 0) return defaultValue;
150 if (tags) {
151 if (tags[count] == 'f') {
152 value = OSCfloat(rdpos);
153 rdpos += sizeof(float32);
154 } else if (tags[count] == 'd') {
155 value = static_cast<float32>(OSCdouble(rdpos));
156 rdpos += sizeof(float64);
157 } else if (tags[count] == 'i') {
158 value = static_cast<float32>(OSCint(rdpos));
159 rdpos += sizeof(int32);
160 } else if (tags[count] == 's') {
161 /* value = atof(rdpos); */
162 value = defaultValue;
163 rdpos = OSCstrskip(rdpos);
164 } else if (tags[count] == 'b') {
165 value = defaultValue;
166 skipb();
167 } else {
168 /* this is dangerous, as rdpos is not
169 advanced accordingly while count++ takes
170 place */
171 value = defaultValue;
173 } else {
174 value = OSCfloat(rdpos);
175 rdpos += sizeof(float32);
177 count ++;
178 return value;
181 inline float64 sc_msg_iter::getd(float64 defaultValue)
183 float64 value;
184 if (remain() <= 0) return defaultValue;
185 if (tags) {
186 if (tags[count] == 'f') {
187 value = (float64)OSCfloat(rdpos);
188 rdpos += sizeof(float32);
189 } else if (tags[count] == 'd') {
190 value = OSCdouble(rdpos);
191 rdpos += sizeof(float64);
192 } else if (tags[count] == 'i') {
193 value = (float64)OSCint(rdpos);
194 rdpos += sizeof(int32);
195 } else if (tags[count] == 's') {
196 /* value = atof(rdpos); */
197 value = defaultValue;
198 rdpos = OSCstrskip(rdpos);
199 } else if (tags[count] == 'b') {
200 value = defaultValue;
201 skipb();
202 } else {
203 /* this is dangerous, as rdpos is not
204 advanced accordingly while count++ takes
205 place */
206 value = defaultValue;
208 } else {
209 value = OSCdouble(rdpos);
210 rdpos += sizeof(float64);
212 count ++;
213 return value;
217 inline const char* sc_msg_iter::gets(const char* defaultValue)
219 const char* value;
220 if (remain() <= 0) return 0;
221 if (tags) {
222 if (tags[count] == 's') {
223 value = rdpos;
224 rdpos = OSCstrskip(rdpos);
225 } else {
226 value = defaultValue;
228 } else {
229 value = rdpos;
230 rdpos = OSCstrskip(rdpos);
232 count ++;
233 return value;
236 inline int32* sc_msg_iter::gets4(char* defaultValue)
238 int32* value;
239 if (remain() <= 0) return 0;
240 if (tags) {
241 if (tags[count] == 's') {
242 value = (int32*)rdpos;
243 rdpos = OSCstrskip(rdpos);
244 } else {
245 value = (int32*)defaultValue;
247 } else {
248 value = (int32*)rdpos;
249 rdpos = OSCstrskip(rdpos);
251 count ++;
252 return value;
255 inline size_t sc_msg_iter::getbsize()
257 if (remain() <= 0) return 0;
258 if (tags && tags[count] != 'b') return 0;
259 return (size_t)OSCint(rdpos);
262 inline void sc_msg_iter::getb(char* outArray, size_t size)
264 size_t len = OSCint(rdpos);
265 if (size < len) return;
266 rdpos += sizeof(int32);
267 size_t len4 = (len + 3) & (size_t)-4;
268 memcpy(outArray, rdpos, size);
269 rdpos += len4;
270 count ++;
273 inline void sc_msg_iter::skipb()
275 size_t len = OSCint(rdpos);
276 rdpos += sizeof(int32);
277 size_t len4 = (len + 3) & (size_t)-4;
278 rdpos += len4;
279 count ++;
282 #endif