source: xplra/src/client/c/hu/varadiistvan/xplra/MultiBuffer.cc@ 21:3f824500be71

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

Implemented the multi-dataref setter object

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