source: xplra/src/client/c/hu/varadiistvan/xplra/MultiBuffer.cc@ 66:f7c8521991df

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

Added the Doxygen configuration file and updated the documentation to eliminate the warnings

File size: 20.3 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::vector;
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
143void MultiBuffer::forgetRegistration() throw()
144{
145 registeredID = -1;
146}
147
148//------------------------------------------------------------------------------
149
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
241MultiBuffer::MultiBuffer(XPlane& xplane, uint8_t registerCommand,
242 uint8_t unregisterCommand) throw() :
243 data(0),
244 xplane(xplane),
245 registerCommand(registerCommand),
246 unregisterCommand(unregisterCommand),
247 registeredID(-1)
248{
249}
250
251//------------------------------------------------------------------------------
252
253MultiBuffer::~MultiBuffer() throw()
254{
255 unregisterSafelyFromXPlane();
256 delete[] data;
257}
258
259//------------------------------------------------------------------------------
260
261size_t MultiBuffer::addInt(const std::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 std::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 std::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 std::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 std::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 std::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
341 writeSpec(registerCommand);
342
343 uint32_t id = xplane.stream->readU32();
344 xplane.checkStream();
345
346 registeredID = static_cast<int>(id);
347 }
348}
349
350//------------------------------------------------------------------------------
351
352void MultiBuffer::unregisterFromXPlane() throw(Exception)
353{
354 if (registeredID>=0) {
355 xplane.stream->writeU8(unregisterCommand);
356 xplane.stream->writeU32(static_cast<uint32_t>(registeredID));
357 xplane.stream->flush();
358 xplane.checkResult();
359 registeredID = -1;
360 }
361}
362
363//------------------------------------------------------------------------------
364
365bool MultiBuffer::unregisterSafelyFromXPlane() throw()
366{
367 try {
368 unregisterFromXPlane();
369 return true;
370 } catch(...) {
371 registeredID = -1;
372 return false;
373 }
374}
375
376//------------------------------------------------------------------------------
377
378void MultiBuffer::execute() throw(Exception)
379{
380 if (data==0 && registeredID>=0) {
381 unregisterFromXPlane();
382 registerInXPlane();
383 } else {
384 finalize();
385 }
386
387 if (registeredID>=0) {
388 doExecute();
389 } else {
390 doExecuteUnregistered();
391 }
392}
393
394//------------------------------------------------------------------------------
395
396void MultiBuffer::setInt(size_t id, int value)
397 throw(InvalidIDException, TypeMismatchException)
398{
399 *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT)) = value;
400}
401
402//------------------------------------------------------------------------------
403
404int MultiBuffer::getInt(size_t id) const
405 throw(InvalidIDException, TypeMismatchException)
406{
407 return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
408}
409
410//------------------------------------------------------------------------------
411
412const int32_t& MultiBuffer::getIntRef(size_t id) const
413 throw(InvalidIDException, TypeMismatchException)
414{
415 return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
416}
417
418//------------------------------------------------------------------------------
419
420int32_t& MultiBuffer::getIntRef(size_t id)
421 throw(InvalidIDException, TypeMismatchException)
422{
423 return *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT));
424}
425
426//------------------------------------------------------------------------------
427
428void MultiBuffer::setFloat(size_t id, float value)
429 throw(InvalidIDException, TypeMismatchException)
430{
431 *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT)) = value;
432}
433
434//------------------------------------------------------------------------------
435
436float MultiBuffer::getFloat(size_t id) const
437 throw(InvalidIDException, TypeMismatchException)
438{
439 return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
440}
441
442//------------------------------------------------------------------------------
443
444const float& MultiBuffer::getFloatRef(size_t id) const
445 throw(InvalidIDException, TypeMismatchException)
446{
447 return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
448}
449
450//------------------------------------------------------------------------------
451
452float& MultiBuffer::getFloatRef(size_t id)
453 throw(InvalidIDException, TypeMismatchException)
454{
455 return *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT));
456}
457
458//------------------------------------------------------------------------------
459
460void MultiBuffer::setDouble(size_t id, double value)
461 throw(InvalidIDException, TypeMismatchException)
462{
463 *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE)) = value;
464}
465
466//------------------------------------------------------------------------------
467
468double MultiBuffer::getDouble(size_t id) const
469 throw(InvalidIDException, TypeMismatchException)
470{
471 return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
472}
473
474//------------------------------------------------------------------------------
475
476const double& MultiBuffer::getDoubleRef(size_t id) const
477 throw(InvalidIDException, TypeMismatchException)
478{
479 return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
480}
481
482//------------------------------------------------------------------------------
483
484double& MultiBuffer::getDoubleRef(size_t id)
485 throw(InvalidIDException, TypeMismatchException)
486{
487 return *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE));
488}
489
490//------------------------------------------------------------------------------
491
492size_t MultiBuffer::setFloatArray(size_t id, const float* value,
493 size_t length, size_t offset)
494 throw(InvalidIDException, TypeMismatchException)
495{
496 return setArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
497}
498
499//------------------------------------------------------------------------------
500
501size_t MultiBuffer::getFloatArray(size_t id, float* value,
502 size_t length, size_t offset) const
503 throw(InvalidIDException, TypeMismatchException)
504{
505 return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
506}
507
508//------------------------------------------------------------------------------
509
510const float* MultiBuffer::getFloatArray(size_t id, size_t offset) const
511 throw(InvalidIDException, TypeMismatchException)
512{
513 return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, offset);
514}
515
516//------------------------------------------------------------------------------
517
518size_t MultiBuffer::setIntArray(size_t id, const int32_t* value,
519 size_t length, size_t offset)
520 throw(InvalidIDException, TypeMismatchException)
521{
522 return setArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
523}
524
525//------------------------------------------------------------------------------
526
527size_t MultiBuffer::getIntArray(size_t id, int32_t* value,
528 size_t length, size_t offset) const
529 throw(InvalidIDException, TypeMismatchException)
530{
531 return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
532}
533
534//------------------------------------------------------------------------------
535
536const int32_t* MultiBuffer::getIntArray(size_t id, size_t offset) const
537 throw(InvalidIDException, TypeMismatchException)
538{
539 return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, offset);
540}
541
542//------------------------------------------------------------------------------
543
544size_t MultiBuffer::setByteArray(size_t id, const uint8_t* value,
545 size_t length, size_t offset)
546 throw(InvalidIDException, TypeMismatchException)
547{
548 return setArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
549}
550
551//------------------------------------------------------------------------------
552
553size_t MultiBuffer::getByteArray(size_t id, uint8_t* value,
554 size_t length, size_t offset) const
555 throw(InvalidIDException, TypeMismatchException)
556{
557 return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
558}
559
560//------------------------------------------------------------------------------
561
562const uint8_t* MultiBuffer::getByteArray(size_t id, size_t offset) const
563 throw(InvalidIDException, TypeMismatchException)
564{
565 return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, offset);
566}
567
568//------------------------------------------------------------------------------
569
570size_t MultiBuffer::setString(size_t id, const string& value,
571 size_t offset)
572 throw(InvalidIDException, TypeMismatchException)
573{
574 return setByteArray(id, reinterpret_cast<const uint8_t*>(value.c_str()),
575 value.length(), offset);
576}
577
578//------------------------------------------------------------------------------
579
580string MultiBuffer::getString(size_t id, size_t offset) const
581 throw(InvalidIDException, TypeMismatchException)
582{
583 const DataRef& dataRef = getDataRef(id, Protocol::TYPE_BYTE_ARRAY);
584 finalize();
585
586 size_t toCopy = dataRef.getCopyLength(0, offset);
587 const uint8_t* str = data + dataRef.dataOffset + offset;
588
589 size_t length = 0;
590 if (toCopy!=0) {
591 while(length<toCopy && str[length]!=0) ++length;
592 }
593
594 return string(reinterpret_cast<const char*>(str), length);
595}
596
597//------------------------------------------------------------------------------
598
599const char* MultiBuffer::getStringPtr(size_t id, size_t offset) const
600 throw(InvalidIDException, TypeMismatchException)
601{
602 return reinterpret_cast<const char*>(getByteArray(id, offset));
603}
604
605//------------------------------------------------------------------------------
606
607void MultiBuffer::writeSpec(uint8_t command) const throw(Exception)
608{
609 xplane.stream->writeU8(command);
610 xplane.stream->writeU32(dataRefs.size());
611
612 for(vector<DataRef>::const_iterator i = dataRefs.begin();
613 i!=dataRefs.end(); ++i)
614 {
615 const DataRef& dataRef = *i;
616 xplane.stream->writeString(dataRef.name);
617 xplane.stream->writeU8(dataRef.type);
618 if (dataRef.isArray()) {
619 xplane.stream->writeS32(dataRef.length);
620 xplane.stream->writeS32(dataRef.offset);
621 }
622 }
623
624 xplane.stream->flush();
625 xplane.checkResult(true);
626}
627
628//------------------------------------------------------------------------------
629
630void MultiBuffer::reregisterInXPlane() throw(Exception)
631{
632 if (registeredID>=0) {
633 int origRegisteredID = registeredID;
634 try {
635 registeredID = -1;
636 registerInXPlane();
637 } catch(...) {
638 registeredID = origRegisteredID;
639 throw;
640 }
641 }
642}
643
644//------------------------------------------------------------------------------
645
646// Local Variables:
647// mode: C++
648// c-basic-offset: 4
649// indent-tabs-mode: nil
650// End:
Note: See TracBrowser for help on using the repository browser.