source: xplra/src/client/c/hu/varadiistvan/xplra/MultiBuffer.h@ 107:614b9ff033c1

Last change on this file since 107:614b9ff033c1 was 107:614b9ff033c1, checked in by István Váradi <ivaradi@…>, 17 months ago

Modernized the exception specifications in the C++ client

File size: 17.0 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#ifndef HU_VARADIISTVAN_XPLRA_MULTIBUFFER_H
30#define HU_VARADIISTVAN_XPLRA_MULTIBUFFER_H
31//------------------------------------------------------------------------------
32
33#include "Exception.h"
34
35#include <string>
36#include <vector>
37
38#include <inttypes.h>
39
40//------------------------------------------------------------------------------
41
42namespace hu { namespace varadiistvan { namespace xplra {
43
44//------------------------------------------------------------------------------
45
46class XPlane;
47
48//------------------------------------------------------------------------------
49
50/**
51 * Base class for the multi-get and multi-set handlers. It contains
52 * the meta-data of the datarefs as well as a buffer for storing the
53 * data.
54 */
55class MultiBuffer
56{
57protected:
58 /**
59 * Information about a dataref.
60 */
61 class DataRef
62 {
63 public:
64 /**
65 * The name.
66 */
67 std::string name;
68
69 /**
70 * The type (the protocol constant).
71 */
72 uint8_t type;
73
74 /**
75 * The length in case of array types.
76 */
77 size_t length;
78
79 /**
80 * The offset in case of array types.
81 */
82 size_t offset;
83
84 /**
85 * The offset within the data buffer.
86 */
87 size_t dataOffset;
88
89 /**
90 * Construct the dataref with the given data.
91 */
92 DataRef(const std::string& name, uint8_t type,
93 const DataRef* previous = 0,
94 size_t length = 0, size_t offset = 0) noexcept;
95
96 /**
97 * Get the size of the data represented by this object.
98 */
99 size_t getSize() const noexcept;
100
101 /**
102 * Get the alignment requirement of the data represented by
103 * this dataref.
104 */
105 size_t getAlignment() const noexcept;
106
107 /**
108 * Determine if the dataref is an array.
109 */
110 bool isArray() const noexcept;
111
112 /**
113 * Get the length of the data the can be copied for the given
114 * user parameters.
115 */
116 size_t getCopyLength(size_t userLength, size_t userOffset) const noexcept;
117 };
118
119 /**
120 * The datarefs.
121 */
122 std::vector<DataRef> dataRefs;
123
124 /**
125 * The data buffer.
126 */
127 mutable unsigned char* data;
128
129 /**
130 * The XPlane object this buffer belongs to.
131 */
132 XPlane& xplane;
133
134 /**
135 * The command to use for registering the buffer.
136 */
137 uint8_t registerCommand;
138
139 /**
140 * The command to unregister the buffer.
141 */
142 uint8_t unregisterCommand;
143
144 /**
145 * The ID with which this buffer is registered in the plugin. If
146 * negative, the buffer is not registerd yet.
147 */
148 int registeredID;
149
150protected:
151 /**
152 * Construct an empty buffer for the given XPlane instance.
153 */
154 MultiBuffer(XPlane& xplane, uint8_t registerCommand,
155 uint8_t unregisterCommand) noexcept;
156
157 /**
158 * Destroy the buffer. If it is registered, an attempt will be
159 * made to unregister it.
160 */
161 virtual ~MultiBuffer() noexcept;
162
163public:
164 /**
165 * Get the X-Plane object this buffer belongs to.
166 */
167 XPlane& getXPlane() const noexcept;
168
169 /**
170 * Add an integer dataref.
171 *
172 * @return the ID of the dataref, that can be used later to set or
173 * get the value.
174 */
175 size_t addInt(const std::string& name) noexcept;
176
177 /**
178 * Add a float dataref.
179 *
180 * @return the ID of the dataref, that can be used later to set or
181 * get the value.
182 */
183 size_t addFloat(const std::string& name) noexcept;
184
185 /**
186 * Add a double dataref.
187 *
188 * @return the ID of the dataref, that can be used later to set or
189 * get the value.
190 */
191 size_t addDouble(const std::string& name) noexcept;
192
193 /**
194 * Add a float array dataref.
195 *
196 * @return the ID of the dataref, that can be used later to set or
197 * get the value.
198 */
199 size_t addFloatArray(const std::string& name, size_t length,
200 size_t offset = 0) noexcept;
201
202 /**
203 * Add an integer array dataref.
204 *
205 * @return the ID of the dataref, that can be used later to set or
206 * get the value.
207 */
208 size_t addIntArray(const std::string& name, size_t length,
209 size_t offset = 0) noexcept;
210
211 /**
212 * Add a byte array dataref.
213 *
214 * @return the ID of the dataref, that can be used later to set or
215 * get the value.
216 */
217 size_t addByteArray(const std::string& name, size_t length,
218 size_t offset = 0) noexcept;
219
220 /**
221 * Finalize the buffer, if not finalized yet.
222 *
223 * @return if there is any data in it
224 */
225 bool finalize() const;
226
227 /**
228 * Register this buffer in X-Plane the for either getting or
229 * setting, depending on the actual subclass. It will be finalized
230 * too.
231 */
232 void registerInXPlane();
233
234 /**
235 * Unregister this buffer from X-Plane.
236 */
237 void unregisterFromXPlane();
238
239 /**
240 * Unregister this buffer from X-Plane safely, i.e. without
241 * throwing any exceptions. If unregistration fails, the
242 * registered ID will be cleared anyway.
243 *
244 * @return whether unregistration succeeded.
245 */
246 bool unregisterSafelyFromXPlane() noexcept;
247
248 /**
249 * Execute the buffer by either reading or writing it. If the
250 * buffer is not finalized, it will be finalized. If it is not
251 * finalized, but registered, the registration will be cleared,
252 * and it will be re-registered after finalizing.
253 */
254 void execute();
255
256 /**
257 * Set the value of an integer dataref with the given ID.
258 */
259 void setInt(size_t id, int value);
260
261 /**
262 * Get the value of an integer dataref with the given ID.
263 */
264 int getInt(size_t id) const;
265
266 /**
267 * Get a reference to the integer dataref with the given ID
268 */
269 const int32_t& getIntRef(size_t id) const;
270
271 /**
272 * Get a reference to the integer dataref with the given ID
273 */
274 int32_t& getIntRef(size_t id);
275
276 /**
277 * Set the value of a float dataref with the given ID.
278 */
279 void setFloat(size_t id, float value);
280
281 /**
282 * Get the value of a float dataref with the given ID.
283 */
284 float getFloat(size_t id) const;
285
286 /**
287 * Get a reference to the float dataref with the given ID
288 */
289 const float& getFloatRef(size_t id) const;
290
291 /**
292 * Get a reference to the integer dataref with the given ID
293 */
294 float& getFloatRef(size_t id);
295
296 /**
297 * Set the value of a double dataref with the given ID.
298 */
299 void setDouble(size_t id, double value);
300
301 /**
302 * Get the value of a double dataref with the given ID.
303 */
304 double getDouble(size_t id) const;
305
306 /**
307 * Get a reference to the double dataref with the given ID
308 */
309 const double& getDoubleRef(size_t id) const;
310
311 /**
312 * Get a reference to the double dataref with the given ID
313 */
314 double& getDoubleRef(size_t id);
315
316 /**
317 * Set the value of the float array dataref with the given ID.
318 *
319 * @param id the ID of the float array dataref
320 * @param value the source buffer
321 * @param length the amount of data, i.e. you can set only a part
322 * of the data in the buffer. If 0, it is assumed to be the length
323 * of the data in the buffer minus the offset (see below).
324 *
325 * @param offset the offset within the buffer to set the data from
326 *
327 * @return the number of data items set
328 */
329 size_t setFloatArray(size_t id, const float* value,
330 size_t length = 0, size_t offset = 0);
331
332 /**
333 * Get the value of the float array dataref with the given ID
334 *
335 * @param id the ID of the float array dataref
336 * @param value the destination buffer
337 * @param length the size of the buffer. If 0, it is assumed to be
338 * the length of the data in the buffer minus the offset (see
339 * below).
340 *
341 * @param offset the offset within the buffer to get the data from
342 *
343 * @return the number of data items retrieved.
344 */
345 size_t getFloatArray(size_t id, float* value,
346 size_t length = 0, size_t offset = 0) const;
347
348 /**
349 * Get the array of floating point values as a directly readable
350 * buffer.
351 *
352 * @param id the ID of the float array dataref
353 * @param offset the offset within the buffer. If it is not less
354 * than the length of the buffer, 0 is returned.
355 */
356 const float* getFloatArray(size_t id, size_t offset = 0) const;
357
358 /**
359 * Set the value of the integer array dataref with the given ID.
360 *
361 * @param id the ID of the integer array dataref
362 * @param value the source buffer
363 * @param length the amount of data, i.e. you can set only a part
364 * of the data in the buffer. If 0, it is assumed to be the length
365 * of the data in the buffer minus the offset (see below).
366 *
367 * @param offset the offset within the buffer to set the data from
368 *
369 * @return the number of data items set
370 */
371 size_t setIntArray(size_t id, const int32_t* value,
372 size_t length = 0, size_t offset = 0);
373
374 /**
375 * Get the value of the integer array dataref with the given ID
376 *
377 * @param id the ID of the integer array dataref
378 * @param value the destination buffer
379 * @param length the size of the buffer. If 0, it is assumed to be
380 * the length of the data in the buffer minus the offset (see
381 * below).
382 *
383 * @param offset the offset within the buffer to get the data from
384 *
385 * @return the number of data items retrieved.
386 */
387 size_t getIntArray(size_t id, int32_t* value,
388 size_t length = 0, size_t offset = 0) const;
389
390 /**
391 * Get the array of integer values as a directly readable buffer.
392 *
393 * @param id the ID of the float array dataref
394 * @param offset the offset within the buffer. If it is not less
395 * than the length of the buffer, 0 is returned.
396 */
397 const int32_t* getIntArray(size_t id, size_t offset = 0) const;
398
399 /**
400 * Set the value of the byte array dataref with the given ID.
401 *
402 * @param id the ID of the byte array dataref
403 * @param value the source buffer
404 * @param length the amount of data, i.e. you can set only a part
405 * of the data in the buffer. If 0, it is assumed to be the length
406 * of the data in the buffer minus the offset (see below).
407 *
408 * @param offset the offset within the buffer to set the data from
409 *
410 * @return the number of data items set
411 */
412 size_t setByteArray(size_t id, const uint8_t* value,
413 size_t length = 0, size_t offset = 0);
414
415 /**
416 * Get the value of the byte array dataref with the given ID
417 *
418 * @param id the ID of the byte array dataref
419 * @param value the destination buffer
420 * @param length the size of the buffer. If 0, it is assumed to be
421 * the length of the data in the buffer minus the offset (see
422 * below).
423 *
424 * @param offset the offset within the buffer to get the data from
425 *
426 * @return the number of data items retrieved.
427 */
428 size_t getByteArray(size_t id, uint8_t* value,
429 size_t length = 0, size_t offset = 0) const;
430
431 /**
432 * Get the array of byte values as a directly readable buffer.
433 *
434 * @param id the ID of the byte array dataref
435 * @param offset the offset within the buffer. If it is not less
436 * than the length of the buffer, 0 is returned.
437 */
438 const uint8_t* getByteArray(size_t id, size_t offset = 0) const;
439
440
441 /**
442 * Set the value of the byte array dataref with the given ID
443 * from the given string. If the string contains less characters
444 * than the array's length, the rest will be filled with 0s.
445 *
446 * @return the number of bytes set
447 */
448 size_t setString(size_t id, const std::string& value,
449 size_t offset = 0);
450
451 /**
452 * Get the value of the byte array dataref with the given ID as
453 * a string.
454 */
455 std::string getString(size_t id, size_t offset = 0) const;
456
457 /**
458 * Get a string pointer to the value of the byte array dataref
459 * with the given ID.
460 */
461 const char* getStringPtr(size_t id, size_t offset = 0) const;
462
463protected:
464 /**
465 * Perform the main part of the execution if the buffer is
466 * registered.
467 */
468 virtual void doExecute() = 0;
469
470 /**
471 * Perform the main part of the execution if the buffer is
472 * not registered.
473 */
474 virtual void doExecuteUnregistered() = 0;
475
476 /**
477 * Write the data specification with the given command. It also
478 * checks the result
479 */
480 void writeSpec(uint8_t command) const;
481
482 /**
483 * Re-register the buffer in X-Plane, if it has been registered
484 * earlier.
485 *
486 * it has not been registered, nothing is done. Otherwise the
487 * buffer gets registered, and the old ID is forgotten. This
488 * function is meant to be used by the XPlane object when it
489 * creates a new connection. If the registration fails, the
490 * original ID is restored, so that this function could be called
491 * again
492 */
493 void reregisterInXPlane();
494
495private:
496 /**
497 * Unfinalize the buffer, if it is finalized.
498 */
499 void unfinalize() noexcept;
500
501 /**
502 * Forget the registration of this buffer. This is called from the
503 * destructor of the XPlane object, since that closes the
504 * connection anyway, so there is no need to unregister the
505 * multi-buffers.
506 */
507 void forgetRegistration() noexcept;
508
509 /**
510 * Get the last dataref, or 0 if there are not datarefs yet.
511 */
512 const DataRef* getLastDataRef() const noexcept;
513
514 /**
515 * Get the dataref with the given ID if it is of the given
516 * type. Otherwise throw an exception.
517 */
518 const DataRef& getDataRef(size_t id, uint8_t type) const;
519
520 /**
521 * Get the data area belonging to the given dataref it is of the
522 * given type. If the buffer is not finalized yet, it will be.
523 */
524 void* getData(size_t id, uint8_t type);
525
526 /**
527 * Get the data area belonging to the given dataref it is of the
528 * given type. If the buffer is not finalized yet, it will be.
529 */
530 const void* getData(size_t id, uint8_t type) const;
531
532 /**
533 * Template function for setting an array of a certain type.
534 */
535 template <typename T, uint8_t type> size_t
536 setArray(size_t id, const T* value, size_t length, size_t offset);
537
538 /**
539 * Template function for getting the elements of an array of a
540 * certain type.
541 */
542 template <typename T, uint8_t type> size_t
543 getArray(size_t id, T* value, size_t length, size_t offset) const;
544
545 /**
546 * Template function for getting the elements of an array of a
547 * certain type.
548 */
549 template <typename T, uint8_t type> const T*
550 getArray(size_t id, size_t offset) const;
551
552 friend class XPlane;
553};
554
555//------------------------------------------------------------------------------
556// Inline definitions
557//------------------------------------------------------------------------------
558
559inline XPlane& MultiBuffer::getXPlane() const noexcept
560{
561 return xplane;
562}
563
564//------------------------------------------------------------------------------
565
566} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
567
568//------------------------------------------------------------------------------
569#endif // HU_VARADIISTVAN_XPLRA_MULTIBUFFER_H
570
571// Local Variables:
572// mode: C++
573// c-basic-offset: 4
574// indent-tabs-mode: nil
575// End:
Note: See TracBrowser for help on using the repository browser.