swift
datarefs.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #ifndef SWIFT_SIM_XSWIFTBUS_DATAREFS_H
5 #define SWIFT_SIM_XSWIFTBUS_DATAREFS_H
6 
8 
9 #include <XPLM/XPLMDataAccess.h>
10 #include <XPLM/XPLMUtilities.h>
11 
12 #include <algorithm>
13 #include <array>
14 #include <cassert>
15 #include <cstring>
16 #include <string>
17 
18 // Avoid checking large auto-generated header with cppcheck
19 #ifndef CPPCHECK
20 # include "datarefs.inc"
21 #endif
22 
23 namespace XSwiftBus
24 {
25 
27  class DataRefImpl
28  {
29  public:
30  DataRefImpl(char const *name) : m_ref(XPLMFindDataRef(name))
31  {
32  if (!m_ref)
33  {
34  XPLMDebugString("Missing dataref:");
35  XPLMDebugString(name);
36  XPLMDebugString("\n");
37  }
38  }
39 
40  bool isValid() const { return m_ref; }
41 
42  template <typename T>
43  void implSet(T);
44 
45  template <typename T>
46  T implGet() const;
47 
48  private:
49  XPLMDataRef m_ref;
50  };
51 
53  class ArrayDataRefImpl
54  {
55  public:
56  ArrayDataRefImpl(char const *name, int size) : m_ref(XPLMFindDataRef(name)), m_size(size)
57  {
58  if (!m_ref)
59  {
60  XPLMDebugString("Missing dataref:");
61  XPLMDebugString(name);
62  XPLMDebugString("\n");
63  }
64  }
65 
66  bool isValid() const { return m_ref; }
67 
68  template <typename T>
69  void implSetAll(T *const);
70 
71  template <typename T>
72  void implGetAll(T *) const;
73 
74  template <typename T>
75  void implSetAt(int index, T);
76 
77  template <typename T>
78  T implGetAt(int index) const;
79 
80  private:
81  XPLMDataRef m_ref;
82  int const m_size;
83  };
84 
90  template <class DataRefTraits>
91  class DataRef : private DataRefImpl
92  {
93  static_assert(!DataRefTraits::is_array, "this is an array dataref");
94 
95  public:
97  DataRef() : DataRefImpl(DataRefTraits::name()) {}
98 
100  using TraitsType = DataRefTraits;
101 
103  using DataRefType = typename DataRefTraits::type;
104 
106  void set(DataRefType d)
107  {
108  static_assert(DataRefTraits::writable, "read-only dataref");
109  DataRefImpl::implSet(d);
110  }
111 
113  void setAsInt(int d) { this->set(static_cast<DataRefType>(d)); }
114 
116  void setAsDouble(double d) { this->set(static_cast<DataRefType>(d)); }
117 
119  DataRefType get() const { return DataRefImpl::implGet<DataRefType>(); }
120 
121  using DataRefImpl::isValid;
122  };
123 
129  template <class DataRefTraits>
130  class ArrayDataRef : private ArrayDataRefImpl
131  {
132  static_assert(DataRefTraits::is_array, "not an array dataref");
133 
134  public:
136  ArrayDataRef() : ArrayDataRefImpl(DataRefTraits::name(), DataRefTraits::size) {}
137 
139  using TraitsType = DataRefTraits;
140 
142  using DataRefType = typename DataRefTraits::type;
143 
145  static constexpr auto DataRefSize = DataRefTraits::size;
146 
148  void setAll(std::array<DataRefType, DataRefSize> const &a)
149  {
150  static_assert(DataRefTraits::writable, "read-only dataref");
151  ArrayDataRefImpl::implSetAll<DataRefType>(a.data());
152  }
153 
155  std::array<DataRefType, DataRefSize> getAll() const
156  {
157  std::array<DataRefType, DataRefSize> result;
158  ArrayDataRefImpl::implGetAll<DataRefType>(result.data());
159  return result;
160  }
161 
163  void setAt(int index, DataRefType d)
164  {
165  static_assert(DataRefTraits::writable, "read-only dataref");
166  ArrayDataRefImpl::implSetAt(index, d);
167  }
168 
170  DataRefType getAt(int index) const { return ArrayDataRefImpl::implGetAt<DataRefType>(index); }
171 
172  using ArrayDataRefImpl::isValid;
173  };
174 
180  template <class DataRefTraits>
182  {
183  static_assert(DataRefTraits::is_array, "not an array dataref");
184 
185  public:
187  StringDataRef() : m_ref(XPLMFindDataRef(DataRefTraits::name()))
188  {
189  if (!m_ref)
190  {
191  XPLMDebugString("Missing dataref:");
192  XPLMDebugString(DataRefTraits::name());
193  XPLMDebugString("\n");
194  }
195  }
196 
198  bool isValid() const { return m_ref; }
199 
201  void set(std::string const &s) { setSubstr(0, s); }
202 
204  std::string get() const { return getSubstr(0, DataRefTraits::size); }
205 
207  void setSubstr(size_t offset, std::string const &s)
208  {
209  static_assert(DataRefTraits::writable, "read-only dataref");
210  assert((s.size() + 1) <= (DataRefTraits::size - offset));
211  XPLMSetDatab(m_ref, (void *)s.c_str(), (int)offset, (int)s.size() + 1);
212  }
213 
215  std::string getSubstr(size_t offset, size_t size) const
216  {
217  std::string s(size, 0);
218  XPLMGetDatab(m_ref, &s[0], (int)offset, (int)size);
219  size = s.find(char(0));
220  if (size != std::string::npos) s.resize(size);
221  return s;
222  }
223 
224  private:
225  XPLMDataRef m_ref;
226  };
227 
228  /* Helper to conditionally fail compilation if no matching constexpr if case is found */
229  template <class...>
230  constexpr bool dependent_false = false;
231 
237  template <class DataRefTraits>
239  {
240  public:
243  {
244  if constexpr (std::is_same_v<typename DataRefTraits::type, int>)
245  {
246  m_ref = XPLMRegisterDataAccessor(DataRefTraits::name(), xplmType_Int, 0, readInt, nullptr, nullptr,
247  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
248  nullptr, this, nullptr);
249  }
250  else if constexpr (std::is_same_v<typename DataRefTraits::type, std::string>)
251  {
252  m_ref = XPLMRegisterDataAccessor(DataRefTraits::name(), xplmType_Data, 0, nullptr, nullptr, nullptr,
253  nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
254  readData, nullptr, this, nullptr);
255  }
256  else { static_assert(dependent_false<typename DataRefTraits::type>, "Unsupported custom dataref type"); }
257  if (!m_ref)
258  {
259  XPLMDebugString("Missing dataref:");
260  XPLMDebugString(DataRefTraits::name());
261  XPLMDebugString("\n");
262  }
263  }
264 
265  CustomDataRef(const CustomDataRef &) = delete;
266  CustomDataRef &operator=(const CustomDataRef &) = delete;
267  CustomDataRef(CustomDataRef &&other) = delete;
268  CustomDataRef &operator=(CustomDataRef &&other) = delete;
269  ~CustomDataRef()
270  {
271  if (m_ref) { XPLMUnregisterDataAccessor(m_ref); }
272  }
273 
274  static typename DataRefTraits::type readInt(void *refcon)
275  {
276  return reinterpret_cast<CustomDataRef *>(refcon)->get();
277  }
278 
279  static int readData(void *refcon, void *out, int offset, int max_length)
280  {
281  if constexpr (std::is_same_v<typename DataRefTraits::type, std::string>)
282  {
283  std::string_view sv(reinterpret_cast<CustomDataRef *>(refcon)->get());
284  const size_t start = std::clamp<size_t>(offset, 0, sv.size());
285  const size_t remaining_length = sv.size() - start;
286  const auto len = std::min(static_cast<size_t>(max_length), remaining_length);
287  sv = sv.substr(start, len);
288  std::memcpy(out, sv.data(), len);
289  return static_cast<int>(len);
290  }
291 
292  return -1; // should never be reached
293  }
294 
296  bool isValid() const { return m_ref != nullptr; }
297 
299  void set(typename DataRefTraits::type val) { m_datarefVal = val; }
300 
302  const typename DataRefTraits::type &get() const { return m_datarefVal; }
303 
304  XPLMDataRef m_ref;
305  typename DataRefTraits::type m_datarefVal;
306  };
307 
308  template <>
309  inline void DataRefImpl::implSet<int>(int d)
310  {
311  XPLMSetDatai(m_ref, d);
312  }
313  template <>
314  inline void DataRefImpl::implSet<float>(float d)
315  {
316  XPLMSetDataf(m_ref, d);
317  }
318  template <>
319  inline void DataRefImpl::implSet<double>(double d)
320  {
321  XPLMSetDatad(m_ref, d);
322  }
323  template <>
324  inline int DataRefImpl::implGet<int>() const
325  {
326  return XPLMGetDatai(m_ref);
327  }
328  template <>
329  inline float DataRefImpl::implGet<float>() const
330  {
331  return XPLMGetDataf(m_ref);
332  }
333  template <>
334  inline double DataRefImpl::implGet<double>() const
335  {
336  return XPLMGetDatad(m_ref);
337  }
338 
339  template <>
340  inline void ArrayDataRefImpl::implSetAll(int const *v)
341  {
342  XPLMSetDatavi(m_ref, const_cast<int *>(v), 0, m_size);
343  }
344  template <>
345  inline void ArrayDataRefImpl::implSetAll(float const *v)
346  {
347  XPLMSetDatavf(m_ref, const_cast<float *>(v), 0, m_size);
348  }
349  template <>
350  inline void ArrayDataRefImpl::implGetAll(int *v) const
351  {
352  XPLMGetDatavi(m_ref, &v[0], 0, m_size);
353  }
354  template <>
355  inline void ArrayDataRefImpl::implGetAll(float *v) const
356  {
357  XPLMGetDatavf(m_ref, &v[0], 0, m_size);
358  }
359 
360  template <>
361  inline void ArrayDataRefImpl::implSetAt<int>(int i, int d)
362  {
363  assert(i <= m_size);
364  XPLMSetDatavi(m_ref, &d, i, 1);
365  }
366  template <>
367  inline void ArrayDataRefImpl::implSetAt<float>(int i, float d)
368  {
369  assert(i <= m_size);
370  XPLMSetDatavf(m_ref, &d, i, 1);
371  }
372  template <>
373  inline int ArrayDataRefImpl::implGetAt<int>(int i) const
374  {
375  assert(i <= m_size);
376  int d;
377  XPLMGetDatavi(m_ref, &d, i, 1);
378  return d;
379  }
380  template <>
381  inline float ArrayDataRefImpl::implGetAt<float>(int i) const
382  {
383  assert(i <= m_size);
384  float d;
385  XPLMGetDatavf(m_ref, &d, i, 1);
386  return d;
387  }
388 
389 } // namespace XSwiftBus
390 
391 #endif // SWIFT_SIM_XSWIFTBUS_DATAREFS_H
Class providing access to a single X-Plane array dataref.
Definition: datarefs.h:131
static constexpr auto DataRefSize
Array dataref size.
Definition: datarefs.h:145
std::array< DataRefType, DataRefSize > getAll() const
Get the value of the whole array.
Definition: datarefs.h:155
void setAt(int index, DataRefType d)
Set the value of a single element (if it is writable)
Definition: datarefs.h:163
void setAll(std::array< DataRefType, DataRefSize > const &a)
Set the value of the whole array (if it is writable)
Definition: datarefs.h:148
ArrayDataRef()
Constructor.
Definition: datarefs.h:136
DataRefType getAt(int index) const
Get the value of a single element.
Definition: datarefs.h:170
typename DataRefTraits::type DataRefType
Dataref type.
Definition: datarefs.h:142
DataRefTraits TraitsType
Traits type.
Definition: datarefs.h:139
Class providing a custom variable + dataref \hint Currently only readable int and std::string dataref...
Definition: datarefs.h:239
bool isValid() const
True if the dataref exists.
Definition: datarefs.h:296
CustomDataRef()
Constructor.
Definition: datarefs.h:242
const DataRefTraits::type & get() const
Get the value.
Definition: datarefs.h:302
void set(typename DataRefTraits::type val)
Set the value.
Definition: datarefs.h:299
Class providing access to a single X-Plane dataref.
Definition: datarefs.h:92
void set(DataRefType d)
Set the value of the dataref (if it is writable)
Definition: datarefs.h:106
void setAsDouble(double d)
Set as integer, avoids cast warnings such as "possible loss of data".
Definition: datarefs.h:116
void setAsInt(int d)
Set as integer, avoids cast warnings such as "possible loss of data".
Definition: datarefs.h:113
typename DataRefTraits::type DataRefType
Dataref type.
Definition: datarefs.h:103
DataRefTraits TraitsType
Traits type.
Definition: datarefs.h:100
DataRef()
Constructor.
Definition: datarefs.h:97
DataRefType get() const
Get the value of the dataref.
Definition: datarefs.h:119
Class providing access to a single X-Plane string dataref.
Definition: datarefs.h:182
void set(std::string const &s)
Set the value of the whole string (if it is writable)
Definition: datarefs.h:201
std::string getSubstr(size_t offset, size_t size) const
Get the value of part of the string.
Definition: datarefs.h:215
StringDataRef()
Constructor.
Definition: datarefs.h:187
bool isValid() const
True if the dataref exists.
Definition: datarefs.h:198
void setSubstr(size_t offset, std::string const &s)
Set the value of part of the string (if it is writable)
Definition: datarefs.h:207
std::string get() const
Get the value of the whole string.
Definition: datarefs.h:204
Plugin loaded by X-Plane which publishes a DBus service.
Definition: command.h:14