source: xplra/src/client/c/hu/varadiistvan/xplra/MultiBuffer.cc@ 40:ec5dde8a6ff6

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

Implemented the client support for the new commands and updated the basic test programs with tests showing messages

File size: 19.6 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(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
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
365void MultiBuffer::execute() throw(Exception)
366{
367 if (data==0 && registeredID>=0) {
368 unregisterFromXPlane();
369 registerInXPlane();
370 } else {
371 finalize();
372 }
373
374 if (registeredID>=0) {
375 doExecute();
376 } else {
377 doExecuteUnregistered();
378 }
379}
380
381//------------------------------------------------------------------------------
382
383void MultiBuffer::setInt(size_t id, int value)
384 throw(InvalidIDException, TypeMismatchException)
385{
386 *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT)) = value;
387}
388
389//------------------------------------------------------------------------------
390
391int MultiBuffer::getInt(size_t id) const
392 throw(InvalidIDException, TypeMismatchException)
393{
394 return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
395}
396
397//------------------------------------------------------------------------------
398
399const int32_t& MultiBuffer::getIntRef(size_t id) const
400 throw(InvalidIDException, TypeMismatchException)
401{
402 return *reinterpret_cast<const int32_t*>(getData(id, Protocol::TYPE_INT));
403}
404
405//------------------------------------------------------------------------------
406
407int32_t& MultiBuffer::getIntRef(size_t id)
408 throw(InvalidIDException, TypeMismatchException)
409{
410 return *reinterpret_cast<int32_t*>(getData(id, Protocol::TYPE_INT));
411}
412
413//------------------------------------------------------------------------------
414
415void MultiBuffer::setFloat(size_t id, float value)
416 throw(InvalidIDException, TypeMismatchException)
417{
418 *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT)) = value;
419}
420
421//------------------------------------------------------------------------------
422
423float MultiBuffer::getFloat(size_t id) const
424 throw(InvalidIDException, TypeMismatchException)
425{
426 return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
427}
428
429//------------------------------------------------------------------------------
430
431const float& MultiBuffer::getFloatRef(size_t id) const
432 throw(InvalidIDException, TypeMismatchException)
433{
434 return *reinterpret_cast<const float*>(getData(id, Protocol::TYPE_FLOAT));
435}
436
437//------------------------------------------------------------------------------
438
439float& MultiBuffer::getFloatRef(size_t id)
440 throw(InvalidIDException, TypeMismatchException)
441{
442 return *reinterpret_cast<float*>(getData(id, Protocol::TYPE_FLOAT));
443}
444
445//------------------------------------------------------------------------------
446
447void MultiBuffer::setDouble(size_t id, double value)
448 throw(InvalidIDException, TypeMismatchException)
449{
450 *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE)) = value;
451}
452
453//------------------------------------------------------------------------------
454
455double MultiBuffer::getDouble(size_t id) const
456 throw(InvalidIDException, TypeMismatchException)
457{
458 return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
459}
460
461//------------------------------------------------------------------------------
462
463const double& MultiBuffer::getDoubleRef(size_t id) const
464 throw(InvalidIDException, TypeMismatchException)
465{
466 return *reinterpret_cast<const double*>(getData(id, Protocol::TYPE_DOUBLE));
467}
468
469//------------------------------------------------------------------------------
470
471double& MultiBuffer::getDoubleRef(size_t id)
472 throw(InvalidIDException, TypeMismatchException)
473{
474 return *reinterpret_cast<double*>(getData(id, Protocol::TYPE_DOUBLE));
475}
476
477//------------------------------------------------------------------------------
478
479size_t MultiBuffer::setFloatArray(size_t id, const float* value,
480 size_t length, size_t offset)
481 throw(InvalidIDException, TypeMismatchException)
482{
483 return setArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
484}
485
486//------------------------------------------------------------------------------
487
488size_t MultiBuffer::getFloatArray(size_t id, float* value,
489 size_t length, size_t offset) const
490 throw(InvalidIDException, TypeMismatchException)
491{
492 return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, value, length, offset);
493}
494
495//------------------------------------------------------------------------------
496
497const float* MultiBuffer::getFloatArray(size_t id, size_t offset) const
498 throw(InvalidIDException, TypeMismatchException)
499{
500 return getArray<float, Protocol::TYPE_FLOAT_ARRAY>(id, offset);
501}
502
503//------------------------------------------------------------------------------
504
505size_t MultiBuffer::setIntArray(size_t id, const int32_t* value,
506 size_t length, size_t offset)
507 throw(InvalidIDException, TypeMismatchException)
508{
509 return setArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
510}
511
512//------------------------------------------------------------------------------
513
514size_t MultiBuffer::getIntArray(size_t id, int32_t* value,
515 size_t length, size_t offset) const
516 throw(InvalidIDException, TypeMismatchException)
517{
518 return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, value, length, offset);
519}
520
521//------------------------------------------------------------------------------
522
523const int32_t* MultiBuffer::getIntArray(size_t id, size_t offset) const
524 throw(InvalidIDException, TypeMismatchException)
525{
526 return getArray<int32_t, Protocol::TYPE_INT_ARRAY>(id, offset);
527}
528
529//------------------------------------------------------------------------------
530
531size_t MultiBuffer::setByteArray(size_t id, const uint8_t* value,
532 size_t length, size_t offset)
533 throw(InvalidIDException, TypeMismatchException)
534{
535 return setArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
536}
537
538//------------------------------------------------------------------------------
539
540size_t MultiBuffer::getByteArray(size_t id, uint8_t* value,
541 size_t length, size_t offset) const
542 throw(InvalidIDException, TypeMismatchException)
543{
544 return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, value, length, offset);
545}
546
547//------------------------------------------------------------------------------
548
549const uint8_t* MultiBuffer::getByteArray(size_t id, size_t offset) const
550 throw(InvalidIDException, TypeMismatchException)
551{
552 return getArray<uint8_t, Protocol::TYPE_BYTE_ARRAY>(id, offset);
553}
554
555//------------------------------------------------------------------------------
556
557size_t MultiBuffer::setString(size_t id, const string& value,
558 size_t offset)
559 throw(InvalidIDException, TypeMismatchException)
560{
561 return setByteArray(id, reinterpret_cast<const uint8_t*>(value.c_str()),
562 value.length(), offset);
563}
564
565//------------------------------------------------------------------------------
566
567string MultiBuffer::getString(size_t id, size_t offset) const
568 throw(InvalidIDException, TypeMismatchException)
569{
570 const DataRef& dataRef = getDataRef(id, Protocol::TYPE_BYTE_ARRAY);
571 finalize();
572
573 size_t toCopy = dataRef.getCopyLength(0, offset);
574 const uint8_t* str = data + dataRef.dataOffset + offset;
575
576 size_t length = 0;
577 if (toCopy!=0) {
578 while(length<toCopy && str[length]!=0) ++length;
579 }
580
581 return string(reinterpret_cast<const char*>(str), length);
582}
583
584//------------------------------------------------------------------------------
585
586const char* MultiBuffer::getStringPtr(size_t id, size_t offset) const
587 throw(InvalidIDException, TypeMismatchException)
588{
589 return reinterpret_cast<const char*>(getByteArray(id, offset));
590}
591
592//------------------------------------------------------------------------------
593
594void MultiBuffer::writeSpec(uint8_t command) const throw(Exception)
595{
596 xplane.stream->writeU8(command);
597 xplane.stream->writeU32(dataRefs.size());
598
599 for(vector<DataRef>::const_iterator i = dataRefs.begin();
600 i!=dataRefs.end(); ++i)
601 {
602 const DataRef& dataRef = *i;
603 xplane.stream->writeString(dataRef.name);
604 xplane.stream->writeU8(dataRef.type);
605 if (dataRef.isArray()) {
606 xplane.stream->writeS32(dataRef.length);
607 xplane.stream->writeS32(dataRef.offset);
608 }
609 }
610
611 xplane.stream->flush();
612 xplane.checkResult(true);
613}
614
615//------------------------------------------------------------------------------
616
617// Local Variables:
618// mode: C++
619// c-basic-offset: 4
620// indent-tabs-mode: nil
621// End:
Note: See TracBrowser for help on using the repository browser.