source: xplra/src/client/c/hu/varadiistvan/xplra/MultiBuffer.h@ 57:f52efb9ba3d8

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

Implemented the C++ client part of the re-registration support

File size: 18.1 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) throw();
95
96 /**
97 * Get the size of the data represented by this object.
98 */
99 size_t getSize() const throw();
100
101 /**
102 * Get the alignment requirement of the data represented by
103 * this dataref.
104 */
105 size_t getAlignment() const throw();
106
107 /**
108 * Determine if the dataref is an array.
109 */
110 bool isArray() const throw();
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 throw();
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) throw();
156
157 /**
158 * Destroy the buffer. If it is registered, an attempt will be
159 * made to unregister it.
160 */
161 virtual ~MultiBuffer() throw();
162
163public:
164 /**
165 * Get the X-Plane object this buffer belongs to.
166 */
167 XPlane& getXPlane() const throw();
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) throw();
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) throw();
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) throw();
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) throw();
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) throw();
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) throw();
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() throw(Exception);
233
234 /**
235 * Unregister this buffer from X-Plane.
236 */
237 void unregisterFromXPlane() throw(Exception);
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() throw();
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() throw(Exception);
255
256 /**
257 * Set the value of an integer dataref with the given ID.
258 */
259 void setInt(size_t id, int value)
260 throw(InvalidIDException, TypeMismatchException);
261
262 /**
263 * Get the value of an integer dataref with the given ID.
264 */
265 int getInt(size_t id) const
266 throw(InvalidIDException, TypeMismatchException);
267
268 /**
269 * Get a reference to the integer dataref with the given ID
270 */
271 const int32_t& getIntRef(size_t id) const
272 throw(InvalidIDException, TypeMismatchException);
273
274 /**
275 * Get a reference to the integer dataref with the given ID
276 */
277 int32_t& getIntRef(size_t id)
278 throw(InvalidIDException, TypeMismatchException);
279
280 /**
281 * Set the value of a float dataref with the given ID.
282 */
283 void setFloat(size_t id, float value)
284 throw(InvalidIDException, TypeMismatchException);
285
286 /**
287 * Get the value of a float dataref with the given ID.
288 */
289 float getFloat(size_t id) const
290 throw(InvalidIDException, TypeMismatchException);
291
292 /**
293 * Get a reference to the float dataref with the given ID
294 */
295 const float& getFloatRef(size_t id) const
296 throw(InvalidIDException, TypeMismatchException);
297
298 /**
299 * Get a reference to the integer dataref with the given ID
300 */
301 float& getFloatRef(size_t id)
302 throw(InvalidIDException, TypeMismatchException);
303
304 /**
305 * Set the value of a double dataref with the given ID.
306 */
307 void setDouble(size_t id, double value)
308 throw(InvalidIDException, TypeMismatchException);
309
310 /**
311 * Get the value of a double dataref with the given ID.
312 */
313 double getDouble(size_t id) const
314 throw(InvalidIDException, TypeMismatchException);
315
316 /**
317 * Get a reference to the double dataref with the given ID
318 */
319 const double& getDoubleRef(size_t id) const
320 throw(InvalidIDException, TypeMismatchException);
321
322 /**
323 * Get a reference to the double dataref with the given ID
324 */
325 double& getDoubleRef(size_t id)
326 throw(InvalidIDException, TypeMismatchException);
327
328 /**
329 * Set the value of the float array dataref with the given ID.
330 *
331 * @param length the amount of data, i.e. you can set only a part
332 * of the data in the buffer. If 0, it is assumed to be the length
333 * of the data in the buffer minus the offset (see below).
334 *
335 * @param offset the offset within the buffer to set the data from
336 *
337 * @return the number of data items set
338 */
339 size_t setFloatArray(size_t id, const float* value,
340 size_t length = 0, size_t offset = 0)
341 throw(InvalidIDException, TypeMismatchException);
342
343 /**
344 * Get the value of the float array dataref with the given ID
345 *
346 * @param length the size of the buffer. If 0, it is assumed to be
347 * the length of the data in the buffer minus the offset (see
348 * below).
349 *
350 * @param offset the offset within the buffer to get the data from
351 *
352 * @return the number of data items retrieved.
353 */
354 size_t getFloatArray(size_t id, float* value,
355 size_t length = 0, size_t offset = 0) const
356 throw(InvalidIDException, TypeMismatchException);
357
358 /**
359 * Get the array of floating point values as a directly readable
360 * buffer.
361 *
362 * @param offset the offset within the buffer. If it is not less
363 * than the length of the buffer, 0 is returned.
364 */
365 const float* getFloatArray(size_t id, size_t offset = 0) const
366 throw(InvalidIDException, TypeMismatchException);
367
368 /**
369 * Set the value of the integer array dataref with the given ID.
370 *
371 * @param length the amount of data, i.e. you can set only a part
372 * of the data in the buffer. If 0, it is assumed to be the length
373 * of the data in the buffer minus the offset (see below).
374 *
375 * @param offset the offset within the buffer to set the data from
376 *
377 * @return the number of data items set
378 */
379 size_t setIntArray(size_t id, const int32_t* value,
380 size_t length = 0, size_t offset = 0)
381 throw(InvalidIDException, TypeMismatchException);
382
383 /**
384 * Get the value of the integer array dataref with the given ID
385 *
386 * @param length the size of the buffer. If 0, it is assumed to be
387 * the length of the data in the buffer minus the offset (see
388 * below).
389 *
390 * @param offset the offset within the buffer to get the data from
391 *
392 * @return the number of data items retrieved.
393 */
394 size_t getIntArray(size_t id, int32_t* value,
395 size_t length = 0, size_t offset = 0) const
396 throw(InvalidIDException, TypeMismatchException);
397
398 /**
399 * Get the array of integer values as a directly readable buffer.
400 *
401 * @param offset the offset within the buffer. If it is not less
402 * than the length of the buffer, 0 is returned.
403 */
404 const int32_t* getIntArray(size_t id, size_t offset = 0) const
405 throw(InvalidIDException, TypeMismatchException);
406
407
408 /**
409 * Set the value of the byte array dataref with the given ID.
410 *
411 * @param length the amount of data, i.e. you can set only a part
412 * of the data in the buffer. If 0, it is assumed to be the length
413 * of the data in the buffer minus the offset (see below).
414 *
415 * @param offset the offset within the buffer to set the data from
416 *
417 * @return the number of data items set
418 */
419 size_t setByteArray(size_t id, const uint8_t* value,
420 size_t length = 0, size_t offset = 0)
421 throw(InvalidIDException, TypeMismatchException);
422
423 /**
424 * Get the value of the byte array dataref with the given ID
425 *
426 * @param length the size of the buffer. If 0, it is assumed to be
427 * the length of the data in the buffer minus the offset (see
428 * below).
429 *
430 * @param offset the offset within the buffer to get the data from
431 *
432 * @return the number of data items retrieved.
433 */
434 size_t getByteArray(size_t id, uint8_t* value,
435 size_t length = 0, size_t offset = 0) const
436 throw(InvalidIDException, TypeMismatchException);
437
438 /**
439 * Get the array of byte values as a directly readable buffer.
440 *
441 * @param offset the offset within the buffer. If it is not less
442 * than the length of the buffer, 0 is returned.
443 */
444 const uint8_t* getByteArray(size_t id, size_t offset = 0) const
445 throw(InvalidIDException, TypeMismatchException);
446
447
448 /**
449 * Set the value of the byte array dataref with the given ID
450 * from the given string. If the string contains less characters
451 * than the array's length, the rest will be filled with 0s.
452 *
453 * @return the number of bytes set
454 */
455 size_t setString(size_t id, const std::string& value,
456 size_t offset = 0)
457 throw(InvalidIDException, TypeMismatchException);
458
459 /**
460 * Get the value of the byte array dataref with the given ID as
461 * a string.
462 */
463 std::string getString(size_t id, size_t offset = 0) const
464 throw(InvalidIDException, TypeMismatchException);
465
466 /**
467 * Get a string pointer to the value of the byte array dataref
468 * with the given ID.
469 */
470 const char* getStringPtr(size_t id, size_t offset = 0) const
471 throw(InvalidIDException, TypeMismatchException);
472
473protected:
474 /**
475 * Perform the main part of the execution if the buffer is
476 * registered.
477 */
478 virtual void doExecute() throw(Exception) = 0;
479
480 /**
481 * Perform the main part of the execution if the buffer is
482 * not registered.
483 */
484 virtual void doExecuteUnregistered() throw(Exception) = 0;
485
486 /**
487 * Write the data specification with the given command. It also
488 * checks the result
489 */
490 void writeSpec(uint8_t command) const throw(Exception);
491
492 /**
493 * Re-register the buffer in X-Plane, if it has been registered
494 * earlier.
495 *
496 * it has not been registered, nothing is done. Otherwise the
497 * buffer gets registered, and the old ID is forgotten. This
498 * function is meant to be used by the XPlane object when it
499 * creates a new connection. If the registration fails, the
500 * original ID is restored, so that this function could be called
501 * again
502 */
503 void reregisterInXPlane() throw(Exception);
504
505private:
506 /**
507 * Unfinalize the buffer, if it is finalized.
508 */
509 void unfinalize() throw();
510
511 /**
512 * Forget the registration of this buffer. This is called from the
513 * destructor of the XPlane object, since that closes the
514 * connection anyway, so there is no need to unregister the
515 * multi-buffers.
516 */
517 void forgetRegistration() throw();
518
519 /**
520 * Get the last dataref, or 0 if there are not datarefs yet.
521 */
522 const DataRef* getLastDataRef() const throw();
523
524 /**
525 * Get the dataref with the given ID if it is of the given
526 * type. Otherwise throw an exception.
527 */
528 const DataRef& getDataRef(size_t id, uint8_t type) const
529 throw(InvalidIDException, TypeMismatchException);
530
531 /**
532 * Get the data area belonging to the given dataref it is of the
533 * given type. If the buffer is not finalized yet, it will be.
534 */
535 void* getData(size_t id, uint8_t type)
536 throw(InvalidIDException, TypeMismatchException);
537
538 /**
539 * Get the data area belonging to the given dataref it is of the
540 * given type. If the buffer is not finalized yet, it will be.
541 */
542 const void* getData(size_t id, uint8_t type) const
543 throw(InvalidIDException, TypeMismatchException);
544
545 /**
546 * Template function for setting an array of a certain type.
547 */
548 template <typename T, uint8_t type> size_t
549 setArray(size_t id, const T* value, size_t length, size_t offset)
550 throw(InvalidIDException, TypeMismatchException);
551
552 /**
553 * Template function for getting the elements of an array of a
554 * certain type.
555 */
556 template <typename T, uint8_t type> size_t
557 getArray(size_t id, T* value, size_t length, size_t offset) const
558 throw(InvalidIDException, TypeMismatchException);
559
560 /**
561 * Template function for getting the elements of an array of a
562 * certain type.
563 */
564 template <typename T, uint8_t type> const T*
565 getArray(size_t id, size_t offset) const
566 throw(InvalidIDException, TypeMismatchException);
567
568 friend class XPlane;
569};
570
571//------------------------------------------------------------------------------
572// Inline definitions
573//------------------------------------------------------------------------------
574
575inline XPlane& MultiBuffer::getXPlane() const throw()
576{
577 return xplane;
578}
579
580//------------------------------------------------------------------------------
581
582} /* namespace hu::varadiistvan::xplra */ } /* namespace hu::varadiistvan */ } /* namespace hu */
583
584//------------------------------------------------------------------------------
585#endif // HU_VARADIISTVAN_XPLRA_MULTIBUFFER_H
586
587// Local Variables:
588// mode: C++
589// c-basic-offset: 4
590// indent-tabs-mode: nil
591// End:
Note: See TracBrowser for help on using the repository browser.