source: xplra/src/client/c/hu/varadiistvan/xplra/MultiBuffer.cc@ 19:280541440d22

Last change on this file since 19:280541440d22 was 19:280541440d22, checked in by István Váradi <ivaradi@…>, 11 years ago

Getting multiple values works

File size: 18.7 KB
Line 
1// Copyright (c) 2013 by István Váradi
2
3// This file is part of XPLRA, a remote-access plugin for X-Plane
4
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7
8// 1. Redistributions of source code must retain the above copyright notice, this
9// list of conditions and the following disclaimer.
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13
14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25// The views and conclusions contained in the software and documentation are those
26// of the authors and should not be interpreted as representing official policies,
27// either expressed or implied, of the FreeBSD Project.
28
29//------------------------------------------------------------------------------
30
31#include "MultiBuffer.h"
32
33#include "XPlane.h"
34
35#include <xplra/Protocol.h>
36
37#include <hu/varadiistvan/scpl/io/DataStream.h>
38
39#include <cstring>
40#include <cstdio>
41
42//------------------------------------------------------------------------------
43
44using hu::varadiistvan::xplra::MultiBuffer;
45
46using xplra::Protocol;
47
48using std::string;
49using std::min;
50
51//------------------------------------------------------------------------------
52
53inline MultiBuffer::DataRef::DataRef(const string& name, uint8_t type,
54 const DataRef* previous,
55 size_t length, size_t offset) throw() :
56 name(name),
57 type(type),
58 length(length),
59 offset(offset),
60 dataOffset(0)
61{
62 if (previous!=0) {
63 size_t alignment = getAlignment();
64 dataOffset = previous->dataOffset + previous->getSize();
65 dataOffset += alignment - 1;
66 dataOffset &= ~(alignment-1);
67 }
68}
69
70//------------------------------------------------------------------------------
71
72inline size_t MultiBuffer::DataRef::getSize() const throw()
73{
74 switch (type) {
75 case Protocol::TYPE_INT:
76 return sizeof(int32_t);
77 case Protocol::TYPE_FLOAT:
78 return sizeof(float);
79 case Protocol::TYPE_DOUBLE:
80 return sizeof(double);
81 case Protocol::TYPE_FLOAT_ARRAY:
82 return sizeof(float) * length;
83 case Protocol::TYPE_INT_ARRAY:
84 return sizeof(int32_t) * length;
85 case Protocol::TYPE_BYTE_ARRAY:
86 return sizeof(uint8_t) * length;
87 default:
88 return 0;
89 }
90}
91
92//------------------------------------------------------------------------------
93
94inline size_t MultiBuffer::DataRef::getAlignment() const throw()
95{
96 switch (type) {
97 case Protocol::TYPE_INT:
98 case Protocol::TYPE_INT_ARRAY:
99 return sizeof(int32_t);
100 case Protocol::TYPE_FLOAT:
101 case Protocol::TYPE_FLOAT_ARRAY:
102 return sizeof(float);
103 case Protocol::TYPE_DOUBLE:
104 return sizeof(double);
105 case Protocol::TYPE_BYTE_ARRAY:
106 default:
107 return sizeof(uint8_t);
108 }
109}
110
111//------------------------------------------------------------------------------
112
113bool MultiBuffer::DataRef::isArray() const throw()
114{
115 return
116 type==Protocol::TYPE_FLOAT_ARRAY ||
117 type==Protocol::TYPE_INT_ARRAY ||
118 type==Protocol::TYPE_BYTE_ARRAY;
119}
120
121//------------------------------------------------------------------------------
122
123inline size_t
124MultiBuffer::DataRef::getCopyLength(size_t userLength, size_t userOffset)
125 const throw()
126{
127 size_t maxLength =
128 (userOffset>length) ? 0 : (length - userOffset);
129 return (userLength==0) ? maxLength : min(userLength, maxLength);
130}
131
132//------------------------------------------------------------------------------
133//------------------------------------------------------------------------------
134
135inline void MultiBuffer::unfinalize() throw()
136{
137 delete data; data = 0;
138}
139
140//------------------------------------------------------------------------------
141
142inline const MultiBuffer::DataRef* MultiBuffer::getLastDataRef() const throw()
143{
144 return dataRefs.empty() ? 0 : &(dataRefs.back());
145}
146
147//------------------------------------------------------------------------------
148
149inline const MultiBuffer::DataRef& MultiBuffer::getDataRef(size_t id, uint8_t type) const
150 throw(InvalidIDException, TypeMismatchException)
151{
152 if (id>=dataRefs.size()) throw InvalidIDException();
153 const DataRef& dataRef = dataRefs[id];
154 if (dataRef.type!=type) throw TypeMismatchException();
155 return dataRef;
156}
157
158//------------------------------------------------------------------------------
159
160inline void* MultiBuffer::getData(size_t id, uint8_t type)
161 throw(InvalidIDException, TypeMismatchException)
162{
163 const DataRef& dataRef = getDataRef(id, type);
164 finalize();
165 return data + dataRef.dataOffset;
166}
167
168//------------------------------------------------------------------------------
169
170inline const void* MultiBuffer::getData(size_t id, uint8_t type) const
171 throw(InvalidIDException, TypeMismatchException)
172{
173 const DataRef& dataRef = getDataRef(id, type);
174 finalize();
175 return data + dataRef.dataOffset;
176}
177
178//------------------------------------------------------------------------------
179
180template <typename T, uint8_t type> size_t
181inline MultiBuffer::setArray(size_t id, const T* value,
182 size_t length, size_t offset)
183 throw(InvalidIDException, TypeMismatchException)
184{
185 const DataRef& dataRef = getDataRef(id, type);
186 finalize();
187
188 size_t toCopy = dataRef.getCopyLength(length, offset);
189
190 if (toCopy>0) {
191 memcpy( data + dataRef.dataOffset + offset * sizeof(T),
192 value, toCopy * sizeof(T) );
193 }
194
195 return toCopy;
196}
197
198//------------------------------------------------------------------------------
199
200template <typename T, uint8_t type>
201inline size_t MultiBuffer::getArray(size_t id, T* value,
202 size_t length, size_t offset) const
203 throw(InvalidIDException, TypeMismatchException)
204{
205 const DataRef& dataRef = getDataRef(id, type);
206 finalize();
207
208 size_t toCopy = dataRef.getCopyLength(length, offset);
209
210 if (toCopy>0) {
211 memcpy( value, data + dataRef.dataOffset + offset * sizeof(T),
212 toCopy * sizeof(T) );
213 }
214
215 return toCopy;
216}
217
218//------------------------------------------------------------------------------
219
220template <typename T, uint8_t type>
221inline const T* MultiBuffer::getArray(size_t id, size_t offset) const
222 throw(InvalidIDException, TypeMismatchException)
223{
224 const DataRef& dataRef = getDataRef(id, type);
225 finalize();
226 return (offset<dataRef.length) ?
227 reinterpret_cast<const T*>(data + dataRef.dataOffset +
228 offset * sizeof(T)) : 0;
229}
230
231//------------------------------------------------------------------------------
232
233MultiBuffer::MultiBuffer(XPlane& xplane) throw() :
234 data(0),
235 xplane(xplane),
236 unregisterCommand(0),
237 registeredID(-1)
238{
239}
240
241//------------------------------------------------------------------------------
242
243MultiBuffer::~MultiBuffer() throw(Exception)
244{
245 unregisterFromXPlane();
246 delete[] data;
247}
248
249//------------------------------------------------------------------------------
250
251size_t MultiBuffer::addInt(const string& name) throw()
252{
253 unfinalize();
254 dataRefs.push_back(DataRef(name, Protocol::TYPE_INT, getLastDataRef()));
255 return dataRefs.size() - 1;
256}
257
258//------------------------------------------------------------------------------
259
260size_t MultiBuffer::addFloat(const string& name) throw()
261{
262 unfinalize();
263 dataRefs.push_back(DataRef(name, Protocol::TYPE_FLOAT, getLastDataRef()));
264 return dataRefs.size() - 1;
265}
266
267//------------------------------------------------------------------------------
268
269size_t MultiBuffer::addDouble(const string& name) throw()
270{
271 unfinalize();
272 dataRefs.push_back(DataRef(name, Protocol::TYPE_DOUBLE, getLastDataRef()));
273 return dataRefs.size() - 1;
274}
275
276//------------------------------------------------------------------------------
277
278size_t MultiBuffer::addFloatArray(const string& name, size_t length,
279 size_t offset) throw()
280{
281 unfinalize();
282 dataRefs.push_back(DataRef(name, Protocol::TYPE_FLOAT_ARRAY,
283 getLastDataRef(), length, offset));
284 return dataRefs.size() - 1;
285}
286
287//------------------------------------------------------------------------------
288
289size_t MultiBuffer::addIntArray(const string& name, size_t length,
290 size_t offset) throw()
291{
292 unfinalize();
293 dataRefs.push_back(DataRef(name, Protocol::TYPE_INT_ARRAY,
294 getLastDataRef(), length, offset));
295 return dataRefs.size() - 1;
296}
297
298//------------------------------------------------------------------------------
299
300size_t MultiBuffer::addByteArray(const string& name, size_t length,
301 size_t offset) throw()
302{
303 unfinalize();
304 dataRefs.push_back(DataRef(name, Protocol::TYPE_BYTE_ARRAY,
305 getLastDataRef(), length, offset));
306 return dataRefs.size() - 1;
307}
308
309//------------------------------------------------------------------------------
310
311bool MultiBuffer::finalize() const
312{
313 if (data==0 && !dataRefs.empty()) {
314 const DataRef* lastDataRef = getLastDataRef();
315 size_t dataSize = lastDataRef->dataOffset + lastDataRef->getSize();
316 data = new unsigned char[dataSize];
317 memset(data, 0, dataSize);
318 return true;
319 } else {
320 return data!=0;
321 }
322}
323
324//------------------------------------------------------------------------------
325
326void MultiBuffer::registerInXPlane() throw(Exception)
327{
328 if (finalize() && registeredID<0) {
329 xplane.checkStream();
330
331 unregisterCommand = doRegister();
332
333 xplane.stream->flush();
334
335 uint8_t result = xplane.stream->readU8();
336 uint32_t id = xplane.stream->readU32();
337 xplane.checkStream();
338 xplane.checkResult(result);
339
340 registeredID = static_cast<int>(id);
341 }
342}
343
344//------------------------------------------------------------------------------
345
346void MultiBuffer::unregisterFromXPlane() throw(Exception)
347{
348 if (registeredID>=0) {
349 xplane.stream->writeU8(unregisterCommand);
350 xplane.stream->writeU32(static_cast<uint32_t>(registeredID));
351 xplane.checkResult();
352 registeredID = -1;
353 }
354}
355
356//------------------------------------------------------------------------------
357
358void MultiBuffer::execute() throw(Exception)
359{
360 if (data==0 && registeredID>=0) {
361 unregisterFromXPlane();
362 registerInXPlane();
363 } else {
364 finalize();
365 }
366
367 if (registeredID>=0) {
368 doExecute();
369 } else {
370 doExecuteUnregistered();
371 }
372}
373
374//------------------------------------------------------------------------------
375
376void MultiBuffer::setInt(size_t id, int value)
377 throw(InvalidIDException, TypeMismatchException)
378{
379 *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT)) = value;
380}
381
382//------------------------------------------------------------------------------
383
384int MultiBuffer::getInt(size_t id) const
385 throw(InvalidIDException, TypeMismatchException)
386{
387 return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
388}
389
390//------------------------------------------------------------------------------
391
392const int32_t& MultiBuffer::getIntRef(size_t id) const
393 throw(InvalidIDException, TypeMismatchException)
394{
395 return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
396}
397
398//------------------------------------------------------------------------------
399
400int32_t& MultiBuffer::getIntRef(size_t id)
401 throw(InvalidIDException, TypeMismatchException)
402{
403 return *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT));
404}
405
406//------------------------------------------------------------------------------
407
408void MultiBuffer::setFloat(size_t id, float value)
409 throw(InvalidIDException, TypeMismatchException)
410{
411 *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT)) = value;
412}
413
414//------------------------------------------------------------------------------
415
416float MultiBuffer::getFloat(size_t id) const
417 throw(InvalidIDException, TypeMismatchException)
418{
419 return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
420}
421
422//------------------------------------------------------------------------------
423
424const float& MultiBuffer::getFloatRef(size_t id) const
425 throw(InvalidIDException, TypeMismatchException)
426{
427 return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
428}
429
430//------------------------------------------------------------------------------
431
432float& MultiBuffer::getFloatRef(size_t id)
433 throw(InvalidIDException, TypeMismatchException)
434{
435 return *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT));
436}
437
438//------------------------------------------------------------------------------
439
440void MultiBuffer::setDouble(size_t id, double value)
441 throw(InvalidIDException, TypeMismatchException)
442{
443 *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE)) = value;
444}
445
446//------------------------------------------------------------------------------
447
448double MultiBuffer::getDouble(size_t id) const
449 throw(InvalidIDException, TypeMismatchException)
450{
451 return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
452}
453
454//------------------------------------------------------------------------------
455
456const double& MultiBuffer::getDoubleRef(size_t id) const
457 throw(InvalidIDException, TypeMismatchException)
458{
459 return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
460}
461
462//------------------------------------------------------------------------------
463
464double& MultiBuffer::getDoubleRef(size_t id)
465 throw(InvalidIDException, TypeMismatchException)
466{
467 return *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE));
468}
469
470//------------------------------------------------------------------------------
471
472size_t MultiBuffer::setFloatArray(size_t id, const float* value,
473 size_t length, size_t offset)
474 throw(InvalidIDException, TypeMismatchException)
475{
476 return setArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
477}
478
479//------------------------------------------------------------------------------
480
481size_t MultiBuffer::getFloatArray(size_t id, float* value,
482 size_t length, size_t offset) const
483 throw(InvalidIDException, TypeMismatchException)
484{
485 return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
486}
487
488//------------------------------------------------------------------------------
489
490const float* MultiBuffer::getFloatArray(size_t id, size_t offset) const
491 throw(InvalidIDException, TypeMismatchException)
492{
493 return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, offset);
494}
495
496//------------------------------------------------------------------------------
497
498size_t MultiBuffer::setIntArray(size_t id, const int32_t* value,
499 size_t length, size_t offset)
500 throw(InvalidIDException, TypeMismatchException)
501{
502 return setArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
503}
504
505//------------------------------------------------------------------------------
506
507size_t MultiBuffer::getIntArray(size_t id, int32_t* value,
508 size_t length, size_t offset) const
509 throw(InvalidIDException, TypeMismatchException)
510{
511 return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
512}
513
514//------------------------------------------------------------------------------
515
516const int32_t* MultiBuffer::getIntArray(size_t id, size_t offset) const
517 throw(InvalidIDException, TypeMismatchException)
518{
519 return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, offset);
520}
521
522//------------------------------------------------------------------------------
523
524size_t MultiBuffer::setByteArray(size_t id, const uint8_t* value,
525 size_t length, size_t offset)
526 throw(InvalidIDException, TypeMismatchException)
527{
528 return setArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
529}
530
531//------------------------------------------------------------------------------
532
533size_t MultiBuffer::getByteArray(size_t id, uint8_t* value,
534 size_t length, size_t offset) const
535 throw(InvalidIDException, TypeMismatchException)
536{
537 return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
538}
539
540//------------------------------------------------------------------------------
541
542const uint8_t* MultiBuffer::getByteArray(size_t id, size_t offset) const
543 throw(InvalidIDException, TypeMismatchException)
544{
545 return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, offset);
546}
547
548//------------------------------------------------------------------------------
549
550size_t MultiBuffer::setString(size_t id, const string& value,
551 size_t offset)
552 throw(InvalidIDException, TypeMismatchException)
553{
554 return setByteArray(id, reinterpret_cast<const uint8_t*>(value.c_str()),
555 value.length(), offset);
556}
557
558//------------------------------------------------------------------------------
559
560string MultiBuffer::getString(size_t id, size_t offset) const
561 throw(InvalidIDException, TypeMismatchException)
562{
563 const DataRef& dataRef = getDataRef(id, Protocol::TYPE_BYTE_ARRAY);
564 finalize();
565
566 size_t toCopy = dataRef.getCopyLength(0, offset);
567 const uint8_t* str = data + dataRef.dataOffset + offset;
568
569 size_t length = 0;
570 if (toCopy!=0) {
571 while(length<toCopy && str[length]!=0) ++length;
572 }
573
574 return string(reinterpret_cast<const char*>(str), length);
575}
576
577//------------------------------------------------------------------------------
578
579const char* MultiBuffer::getStringPtr(size_t id, size_t offset) const
580 throw(InvalidIDException, TypeMismatchException)
581{
582 return reinterpret_cast<const char*>(getByteArray(id, offset));
583}
584
585//------------------------------------------------------------------------------
586
587// Local Variables:
588// mode: C++
589// c-basic-offset: 4
590// indent-tabs-mode: nil
591// End:
Note: See TracBrowser for help on using the repository browser.