source: xplra/src/client/c/hu/varadiistvan/xplra/MultiBuffer.cc@ 22:e29d792d1b5d

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

Moved the registration code into MultiBuffer

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