source: xplra/src/client/c/hu/varadiistvan/xplra/MultiBuffer.cc@ 26:77a23a961301

Last change on this file since 26:77a23a961301 was 26:77a23a961301, checked in by István Váradi <ivaradi@…>, 12 years ago

The multi-dataref buffers are managed by the XPlane object

File size: 19.5 KB
RevLine 
[19]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
[22]48using std::vector;
[19]49using std::string;
50using std::min;
51
52//------------------------------------------------------------------------------
53
54inline MultiBuffer::DataRef::DataRef(const string& name, uint8_t type,
55 const DataRef* previous,
56 size_t length, size_t offset) throw() :
57 name(name),
58 type(type),
59 length(length),
60 offset(offset),
61 dataOffset(0)
62{
63 if (previous!=0) {
64 size_t alignment = getAlignment();
65 dataOffset = previous->dataOffset + previous->getSize();
66 dataOffset += alignment - 1;
67 dataOffset &= ~(alignment-1);
68 }
69}
70
71//------------------------------------------------------------------------------
72
73inline size_t MultiBuffer::DataRef::getSize() const throw()
74{
75 switch (type) {
76 case Protocol::TYPE_INT:
77 return sizeof(int32_t);
78 case Protocol::TYPE_FLOAT:
79 return sizeof(float);
80 case Protocol::TYPE_DOUBLE:
81 return sizeof(double);
82 case Protocol::TYPE_FLOAT_ARRAY:
83 return sizeof(float) * length;
84 case Protocol::TYPE_INT_ARRAY:
85 return sizeof(int32_t) * length;
86 case Protocol::TYPE_BYTE_ARRAY:
87 return sizeof(uint8_t) * length;
88 default:
89 return 0;
90 }
91}
92
93//------------------------------------------------------------------------------
94
95inline size_t MultiBuffer::DataRef::getAlignment() const throw()
96{
97 switch (type) {
98 case Protocol::TYPE_INT:
99 case Protocol::TYPE_INT_ARRAY:
100 return sizeof(int32_t);
101 case Protocol::TYPE_FLOAT:
102 case Protocol::TYPE_FLOAT_ARRAY:
103 return sizeof(float);
104 case Protocol::TYPE_DOUBLE:
105 return sizeof(double);
106 case Protocol::TYPE_BYTE_ARRAY:
107 default:
108 return sizeof(uint8_t);
109 }
110}
111
112//------------------------------------------------------------------------------
113
114bool MultiBuffer::DataRef::isArray() const throw()
115{
116 return
117 type==Protocol::TYPE_FLOAT_ARRAY ||
118 type==Protocol::TYPE_INT_ARRAY ||
119 type==Protocol::TYPE_BYTE_ARRAY;
120}
121
122//------------------------------------------------------------------------------
123
124inline size_t
125MultiBuffer::DataRef::getCopyLength(size_t userLength, size_t userOffset)
126 const throw()
127{
128 size_t maxLength =
129 (userOffset>length) ? 0 : (length - userOffset);
130 return (userLength==0) ? maxLength : min(userLength, maxLength);
131}
132
133//------------------------------------------------------------------------------
134//------------------------------------------------------------------------------
135
136inline void MultiBuffer::unfinalize() throw()
137{
138 delete data; data = 0;
139}
140
141//------------------------------------------------------------------------------
142
[26]143void MultiBuffer::forgetRegistration() throw()
144{
145 registeredID = -1;
146}
147
148//------------------------------------------------------------------------------
149
[19]150inline const MultiBuffer::DataRef* MultiBuffer::getLastDataRef() const throw()
151{
152 return dataRefs.empty() ? 0 : &(dataRefs.back());
153}
154
155//------------------------------------------------------------------------------
156
157inline const MultiBuffer::DataRef& MultiBuffer::getDataRef(size_t id, uint8_t type) const
158 throw(InvalidIDException, TypeMismatchException)
159{
160 if (id>=dataRefs.size()) throw InvalidIDException();
161 const DataRef& dataRef = dataRefs[id];
162 if (dataRef.type!=type) throw TypeMismatchException();
163 return dataRef;
164}
165
166//------------------------------------------------------------------------------
167
168inline void* MultiBuffer::getData(size_t id, uint8_t type)
169 throw(InvalidIDException, TypeMismatchException)
170{
171 const DataRef& dataRef = getDataRef(id, type);
172 finalize();
173 return data + dataRef.dataOffset;
174}
175
176//------------------------------------------------------------------------------
177
178inline const void* MultiBuffer::getData(size_t id, uint8_t type) const
179 throw(InvalidIDException, TypeMismatchException)
180{
181 const DataRef& dataRef = getDataRef(id, type);
182 finalize();
183 return data + dataRef.dataOffset;
184}
185
186//------------------------------------------------------------------------------
187
188template <typename T, uint8_t type> size_t
189inline MultiBuffer::setArray(size_t id, const T* value,
190 size_t length, size_t offset)
191 throw(InvalidIDException, TypeMismatchException)
192{
193 const DataRef& dataRef = getDataRef(id, type);
194 finalize();
195
196 size_t toCopy = dataRef.getCopyLength(length, offset);
197
198 if (toCopy>0) {
199 memcpy( data + dataRef.dataOffset + offset * sizeof(T),
200 value, toCopy * sizeof(T) );
201 }
202
203 return toCopy;
204}
205
206//------------------------------------------------------------------------------
207
208template <typename T, uint8_t type>
209inline size_t MultiBuffer::getArray(size_t id, T* value,
210 size_t length, size_t offset) const
211 throw(InvalidIDException, TypeMismatchException)
212{
213 const DataRef& dataRef = getDataRef(id, type);
214 finalize();
215
216 size_t toCopy = dataRef.getCopyLength(length, offset);
217
218 if (toCopy>0) {
219 memcpy( value, data + dataRef.dataOffset + offset * sizeof(T),
220 toCopy * sizeof(T) );
221 }
222
223 return toCopy;
224}
225
226//------------------------------------------------------------------------------
227
228template <typename T, uint8_t type>
229inline const T* MultiBuffer::getArray(size_t id, size_t offset) const
230 throw(InvalidIDException, TypeMismatchException)
231{
232 const DataRef& dataRef = getDataRef(id, type);
233 finalize();
234 return (offset<dataRef.length) ?
235 reinterpret_cast<const T*>(data + dataRef.dataOffset +
236 offset * sizeof(T)) : 0;
237}
238
239//------------------------------------------------------------------------------
240
[22]241MultiBuffer::MultiBuffer(XPlane& xplane, uint8_t registerCommand,
242 uint8_t unregisterCommand) throw() :
[19]243 data(0),
244 xplane(xplane),
[22]245 registerCommand(registerCommand),
246 unregisterCommand(unregisterCommand),
[19]247 registeredID(-1)
248{
249}
250
251//------------------------------------------------------------------------------
252
253MultiBuffer::~MultiBuffer() throw(Exception)
254{
255 unregisterFromXPlane();
256 delete[] data;
257}
258
259//------------------------------------------------------------------------------
260
261size_t MultiBuffer::addInt(const string& name) throw()
262{
263 unfinalize();
264 dataRefs.push_back(DataRef(name, Protocol::TYPE_INT, getLastDataRef()));
265 return dataRefs.size() - 1;
266}
267
268//------------------------------------------------------------------------------
269
270size_t MultiBuffer::addFloat(const string& name) throw()
271{
272 unfinalize();
273 dataRefs.push_back(DataRef(name, Protocol::TYPE_FLOAT, getLastDataRef()));
274 return dataRefs.size() - 1;
275}
276
277//------------------------------------------------------------------------------
278
279size_t MultiBuffer::addDouble(const string& name) throw()
280{
281 unfinalize();
282 dataRefs.push_back(DataRef(name, Protocol::TYPE_DOUBLE, getLastDataRef()));
283 return dataRefs.size() - 1;
284}
285
286//------------------------------------------------------------------------------
287
288size_t MultiBuffer::addFloatArray(const string& name, size_t length,
289 size_t offset) throw()
290{
291 unfinalize();
292 dataRefs.push_back(DataRef(name, Protocol::TYPE_FLOAT_ARRAY,
293 getLastDataRef(), length, offset));
294 return dataRefs.size() - 1;
295}
296
297//------------------------------------------------------------------------------
298
299size_t MultiBuffer::addIntArray(const string& name, size_t length,
300 size_t offset) throw()
301{
302 unfinalize();
303 dataRefs.push_back(DataRef(name, Protocol::TYPE_INT_ARRAY,
304 getLastDataRef(), length, offset));
305 return dataRefs.size() - 1;
306}
307
308//------------------------------------------------------------------------------
309
310size_t MultiBuffer::addByteArray(const string& name, size_t length,
311 size_t offset) throw()
312{
313 unfinalize();
314 dataRefs.push_back(DataRef(name, Protocol::TYPE_BYTE_ARRAY,
315 getLastDataRef(), length, offset));
316 return dataRefs.size() - 1;
317}
318
319//------------------------------------------------------------------------------
320
321bool MultiBuffer::finalize() const
322{
323 if (data==0 && !dataRefs.empty()) {
324 const DataRef* lastDataRef = getLastDataRef();
325 size_t dataSize = lastDataRef->dataOffset + lastDataRef->getSize();
326 data = new unsigned char[dataSize];
327 memset(data, 0, dataSize);
328 return true;
329 } else {
330 return data!=0;
331 }
332}
333
334//------------------------------------------------------------------------------
335
336void MultiBuffer::registerInXPlane() throw(Exception)
337{
338 if (finalize() && registeredID<0) {
339 xplane.checkStream();
340
[22]341 xplane.stream->writeU8(registerCommand);
342 xplane.stream->writeU32(dataRefs.size());
343
344 for(vector<DataRef>::const_iterator i = dataRefs.begin();
345 i!=dataRefs.end(); ++i)
346 {
347 const DataRef& dataRef = *i;
348 xplane.stream->writeString(dataRef.name);
349 xplane.stream->writeU8(dataRef.type);
350 if (dataRef.isArray()) {
351 xplane.stream->writeS32(dataRef.length);
352 xplane.stream->writeS32(dataRef.offset);
353 }
354 }
[19]355
356 xplane.stream->flush();
357
358 uint8_t result = xplane.stream->readU8();
359 uint32_t id = xplane.stream->readU32();
360 xplane.checkStream();
361 xplane.checkResult(result);
362
363 registeredID = static_cast<int>(id);
364 }
365}
366
367//------------------------------------------------------------------------------
368
369void MultiBuffer::unregisterFromXPlane() throw(Exception)
370{
371 if (registeredID>=0) {
372 xplane.stream->writeU8(unregisterCommand);
373 xplane.stream->writeU32(static_cast<uint32_t>(registeredID));
[21]374 xplane.stream->flush();
[19]375 xplane.checkResult();
376 registeredID = -1;
377 }
378}
379
380//------------------------------------------------------------------------------
381
382void MultiBuffer::execute() throw(Exception)
383{
384 if (data==0 && registeredID>=0) {
385 unregisterFromXPlane();
386 registerInXPlane();
387 } else {
388 finalize();
389 }
390
391 if (registeredID>=0) {
392 doExecute();
393 } else {
394 doExecuteUnregistered();
395 }
396}
397
398//------------------------------------------------------------------------------
399
400void MultiBuffer::setInt(size_t id, int value)
401 throw(InvalidIDException, TypeMismatchException)
402{
403 *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT)) = value;
404}
405
406//------------------------------------------------------------------------------
407
408int MultiBuffer::getInt(size_t id) const
409 throw(InvalidIDException, TypeMismatchException)
410{
411 return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
412}
413
414//------------------------------------------------------------------------------
415
416const int32_t& MultiBuffer::getIntRef(size_t id) const
417 throw(InvalidIDException, TypeMismatchException)
418{
419 return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
420}
421
422//------------------------------------------------------------------------------
423
424int32_t& MultiBuffer::getIntRef(size_t id)
425 throw(InvalidIDException, TypeMismatchException)
426{
427 return *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT));
428}
429
430//------------------------------------------------------------------------------
431
432void MultiBuffer::setFloat(size_t id, float value)
433 throw(InvalidIDException, TypeMismatchException)
434{
435 *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT)) = value;
436}
437
438//------------------------------------------------------------------------------
439
440float MultiBuffer::getFloat(size_t id) const
441 throw(InvalidIDException, TypeMismatchException)
442{
443 return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
444}
445
446//------------------------------------------------------------------------------
447
448const float& MultiBuffer::getFloatRef(size_t id) const
449 throw(InvalidIDException, TypeMismatchException)
450{
451 return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
452}
453
454//------------------------------------------------------------------------------
455
456float& MultiBuffer::getFloatRef(size_t id)
457 throw(InvalidIDException, TypeMismatchException)
458{
459 return *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT));
460}
461
462//------------------------------------------------------------------------------
463
464void MultiBuffer::setDouble(size_t id, double value)
465 throw(InvalidIDException, TypeMismatchException)
466{
467 *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE)) = value;
468}
469
470//------------------------------------------------------------------------------
471
472double MultiBuffer::getDouble(size_t id) const
473 throw(InvalidIDException, TypeMismatchException)
474{
475 return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
476}
477
478//------------------------------------------------------------------------------
479
480const double& MultiBuffer::getDoubleRef(size_t id) const
481 throw(InvalidIDException, TypeMismatchException)
482{
483 return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
484}
485
486//------------------------------------------------------------------------------
487
488double& MultiBuffer::getDoubleRef(size_t id)
489 throw(InvalidIDException, TypeMismatchException)
490{
491 return *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE));
492}
493
494//------------------------------------------------------------------------------
495
496size_t MultiBuffer::setFloatArray(size_t id, const float* value,
497 size_t length, size_t offset)
498 throw(InvalidIDException, TypeMismatchException)
499{
500 return setArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
501}
502
503//------------------------------------------------------------------------------
504
505size_t MultiBuffer::getFloatArray(size_t id, float* value,
506 size_t length, size_t offset) const
507 throw(InvalidIDException, TypeMismatchException)
508{
509 return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
510}
511
512//------------------------------------------------------------------------------
513
514const float* MultiBuffer::getFloatArray(size_t id, size_t offset) const
515 throw(InvalidIDException, TypeMismatchException)
516{
517 return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, offset);
518}
519
520//------------------------------------------------------------------------------
521
522size_t MultiBuffer::setIntArray(size_t id, const int32_t* value,
523 size_t length, size_t offset)
524 throw(InvalidIDException, TypeMismatchException)
525{
526 return setArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
527}
528
529//------------------------------------------------------------------------------
530
531size_t MultiBuffer::getIntArray(size_t id, int32_t* value,
532 size_t length, size_t offset) const
533 throw(InvalidIDException, TypeMismatchException)
534{
535 return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
536}
537
538//------------------------------------------------------------------------------
539
540const int32_t* MultiBuffer::getIntArray(size_t id, size_t offset) const
541 throw(InvalidIDException, TypeMismatchException)
542{
543 return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, offset);
544}
545
546//------------------------------------------------------------------------------
547
548size_t MultiBuffer::setByteArray(size_t id, const uint8_t* value,
549 size_t length, size_t offset)
550 throw(InvalidIDException, TypeMismatchException)
551{
552 return setArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
553}
554
555//------------------------------------------------------------------------------
556
557size_t MultiBuffer::getByteArray(size_t id, uint8_t* value,
558 size_t length, size_t offset) const
559 throw(InvalidIDException, TypeMismatchException)
560{
561 return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
562}
563
564//------------------------------------------------------------------------------
565
566const uint8_t* MultiBuffer::getByteArray(size_t id, size_t offset) const
567 throw(InvalidIDException, TypeMismatchException)
568{
569 return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, offset);
570}
571
572//------------------------------------------------------------------------------
573
574size_t MultiBuffer::setString(size_t id, const string& value,
575 size_t offset)
576 throw(InvalidIDException, TypeMismatchException)
577{
578 return setByteArray(id, reinterpret_cast<const uint8_t*>(value.c_str()),
579 value.length(), offset);
580}
581
582//------------------------------------------------------------------------------
583
584string MultiBuffer::getString(size_t id, size_t offset) const
585 throw(InvalidIDException, TypeMismatchException)
586{
587 const DataRef& dataRef = getDataRef(id, Protocol::TYPE_BYTE_ARRAY);
588 finalize();
589
590 size_t toCopy = dataRef.getCopyLength(0, offset);
591 const uint8_t* str = data + dataRef.dataOffset + offset;
592
593 size_t length = 0;
594 if (toCopy!=0) {
595 while(length<toCopy && str[length]!=0) ++length;
596 }
597
598 return string(reinterpret_cast<const char*>(str), length);
599}
600
601//------------------------------------------------------------------------------
602
603const char* MultiBuffer::getStringPtr(size_t id, size_t offset) const
604 throw(InvalidIDException, TypeMismatchException)
605{
606 return reinterpret_cast<const char*>(getByteArray(id, offset));
607}
608
609//------------------------------------------------------------------------------
610
611// Local Variables:
612// mode: C++
613// c-basic-offset: 4
614// indent-tabs-mode: nil
615// End:
Note: See TracBrowser for help on using the repository browser.