libacfutils
A general purpose library of utility functions designed to make it easier to develop addons for the X-Plane flight simulator.
Loading...
Searching...
No Matches
dr.c
1/*OH
2 * CDDL HEADER START
3 *
4 * This file and its contents are supplied under the terms of the
5 * Common Development and Distribution License ("CDDL"), version 1.0.
6 * You may only use this file in accordance with the terms of version
7 * 1.0 of the CDDL.
8 *
9 * A full copy of the text of the CDDL should have accompanied this
10 * source. A copy of the CDDL is also available via the Internet at
11 * http://www.illumos.org/license/CDDL.
12 *
13 * CDDL HEADER END
14*/
15/*
16 * Copyright 2025 Saso Kiselkov. All rights reserved.
17 */
18
19#include <XPLMPlugin.h>
20
21#include <stdarg.h>
22#include <stdio.h>
23#include <string.h>
24
25#include "acfutils/assert.h"
26#define __INCLUDED_FROM_DR_C__
27#include "acfutils/dr.h"
28#include "acfutils/safe_alloc.h"
29
30#define DRE_MSG_ADD_DATAREF 0x01000000
31#define DR_TYPE_CHECK(__check_type, __type) \
32 __check_type ## _MSG(dr->type & (__type), \
33 "dataref \"%s\" has bad type %x (%s:%d: %s)", dr->name, \
34 dr->type, filename, line, varname)
35#define DR_WRITE_CHECK(__check_type) \
36 __check_type ## _MSG(dr->writable, "dataref \"%s\" is not writable " \
37 "(%s:%d: %s)", dr->name, filename, line, varname)
38
39static bool_t dre_plug_lookup_done = B_FALSE;
40static XPLMPluginID dre_plug = XPLM_NO_PLUGIN_ID; /* DataRefEditor */
41static XPLMPluginID drt_plug = XPLM_NO_PLUGIN_ID; /* DataRefTool */
42
43bool_t
44dr_find(dr_t *dr, const char *fmt, ...)
45{
46 va_list ap;
47
48 memset(dr, 0, sizeof (*dr));
49
50 va_start(ap, fmt);
51 vsnprintf(dr->name, sizeof (dr->name), fmt, ap);
52 va_end(ap);
53
54 dr->dr = XPLMFindDataRef(dr->name);
55 if (dr->dr == NULL) {
56 memset(dr, 0, sizeof (*dr));
57 return (B_FALSE);
58 }
59 dr->type = XPLMGetDataRefTypes(dr->dr);
60 VERIFY_MSG(dr->type & (xplmType_Int | xplmType_Float | xplmType_Double |
61 xplmType_IntArray | xplmType_FloatArray | xplmType_Data),
62 "dataref \"%s\" has bad type %x", dr->name, dr->type);
63 dr->writable = XPLMCanWriteDataRef(dr->dr);
64 return (B_TRUE);
65}
66
67bool_t
68dr_writable(dr_t *dr)
69{
70 return (dr->writable);
71}
72
73int
74dr_geti_impl(const dr_t *dr, DR_DEBUG_VARS)
75{
76 if (dr->type & xplmType_Int)
77 return (XPLMGetDatai(dr->dr));
78 if (dr->type & xplmType_Float)
79 return (XPLMGetDataf(dr->dr));
80 if (dr->type & xplmType_Double)
81 return (XPLMGetDatad(dr->dr));
82 if (dr->type & (xplmType_FloatArray | xplmType_IntArray |
83 xplmType_Data)) {
84 int i;
85 VERIFY3S(dr_getvi_impl(dr, filename, line, varname, &i, 0, 1),
86 ==, 1);
87 return (i);
88 }
89 VERIFY_MSG(0, "dataref \"%s\" has bad type %x (%s:%d: %s)", dr->name,
90 dr->type, filename, line, varname);
91}
92
93void
94dr_seti_impl(const dr_t *dr, DR_DEBUG_VARS, int i)
95{
96 DR_WRITE_CHECK(VERIFY);
97 if (dr->type & xplmType_Int) {
98 XPLMSetDatai(dr->dr, i);
99 } else if (dr->type & xplmType_Float) {
100 XPLMSetDataf(dr->dr, i);
101 } else if (dr->type & xplmType_Double) {
102 XPLMSetDatad(dr->dr, i);
103 } else if (dr->type & (xplmType_FloatArray | xplmType_IntArray |
104 xplmType_Data)) {
105 dr_setvi_impl(dr, filename, line, varname, &i, 0, 1);
106 } else {
107 VERIFY_MSG(0, "dataref \"%s\" has bad type %x (%s:%d: %s)",
108 dr->name, dr->type, filename, line, varname);
109 }
110}
111
112double
113dr_getf_impl(const dr_t *dr, DR_DEBUG_VARS)
114{
115 if (dr->type & xplmType_Double)
116 return (XPLMGetDatad(dr->dr));
117 if (dr->type & xplmType_Float)
118 return (XPLMGetDataf(dr->dr));
119 if (dr->type & xplmType_Int)
120 return (XPLMGetDatai(dr->dr));
121 if (dr->type & (xplmType_FloatArray | xplmType_IntArray |
122 xplmType_Data)) {
123 double f;
124 VERIFY3U(dr_getvf_impl(dr, filename, line, varname, &f, 0, 1),
125 ==, 1);
126 return (f);
127 }
128 VERIFY_MSG(0, "dataref \"%s\" has bad type %x (%s%d: %s)", dr->name,
129 dr->type, filename, line, varname);
130}
131
132void
133dr_setf_impl(const dr_t *dr, DR_DEBUG_VARS, double f)
134{
135 DR_WRITE_CHECK(VERIFY);
136 ASSERT_MSG(!isnan(f), "%s (%s%d: %s)", dr->name, filename, line,
137 varname);
138 ASSERT_MSG(isfinite(f), "%s (%s%d: %s)", dr->name, filename, line,
139 varname);
140 if (dr->type & xplmType_Double)
141 XPLMSetDatad(dr->dr, f);
142 else if (dr->type & xplmType_Float)
143 XPLMSetDataf(dr->dr, f);
144 else if (dr->type & xplmType_Int)
145 XPLMSetDatai(dr->dr, f);
146 else if (dr->type & (xplmType_FloatArray | xplmType_IntArray |
147 xplmType_Data))
148 dr_setvf_impl(dr, filename, line, varname, &f, 0, 1);
149 else
150 VERIFY_MSG(0, "dataref \"%s\" has bad type %x (%s:%d: %s)",
151 dr->name, dr->type, filename, line, varname);
152}
153
154int
155dr_getvi_impl(const dr_t *dr, DR_DEBUG_VARS, int *i, unsigned off, unsigned num)
156{
157 ASSERT(i != NULL || num == 0);
158
159 if (dr->type & xplmType_IntArray)
160 return (XPLMGetDatavi(dr->dr, i, off, num));
161 if (dr->type & xplmType_FloatArray) {
162 float *f = safe_malloc(num * sizeof (*f));
163 int n = XPLMGetDatavf(dr->dr, num > 0 ? f : NULL, off, num);
164 if (num != 0) {
165 for (int x = 0; x < n; x++)
166 i[x] = f[x];
167 }
168 free(f);
169 return (n);
170 }
171 if (dr->type & xplmType_Data) {
172 uint8_t *u = safe_malloc(num * sizeof (*u));
173 int n = XPLMGetDatab(dr->dr, num > 0 ? u : NULL, off, num);
174 if (num != 0) {
175 for (int x = 0; x < n; x++)
176 i[x] = u[x];
177 }
178 free(u);
179 return (n);
180 }
181 ASSERT_MSG(off == 0, "Attempted read scalar dataref %s (type: %x) at "
182 "offset other than 0 (%d) (%s%d: %s)", dr->name, dr->type, off,
183 filename, line, varname);
184 if (num != 0)
185 i[0] = dr_geti_impl(dr, filename, line, varname);
186 return (1);
187}
188
189void
190dr_setvi_impl(const dr_t *dr, DR_DEBUG_VARS, int *i, unsigned off, unsigned num)
191{
192 ASSERT(i != NULL);
193 DR_WRITE_CHECK(VERIFY);
194 if (dr->type & xplmType_IntArray) {
195 XPLMSetDatavi(dr->dr, i, off, num);
196 } else if (dr->type & xplmType_FloatArray) {
197 float *f = safe_malloc(num * sizeof (*f));
198 for (unsigned x = 0; x < num; x++)
199 f[x] = i[x];
200 XPLMSetDatavf(dr->dr, f, off, num);
201 free(f);
202 } else if (dr->type & xplmType_Data) {
203 uint8_t *u = safe_malloc(num * sizeof (*u));
204 for (unsigned x = 0; x < num; x++)
205 u[x] = i[x];
206 XPLMSetDatab(dr->dr, u, off, num);
207 free(u);
208 } else {
209 ASSERT_MSG(off == 0, "Attempted write scalar dataref %s "
210 "(type: %x) at offset other than 0 (%d) (%s:%d: %s)",
211 dr->name, dr->type, off, filename, line, varname);
212 dr_seti_impl(dr, filename, line, varname, i[0]);
213 }
214}
215
216int
217dr_getvf_impl(const dr_t *dr, DR_DEBUG_VARS, double *df, unsigned off,
218 unsigned num)
219{
220 ASSERT(df != NULL || num == 0);
221
222 if (dr->type & xplmType_IntArray) {
223 int *i = safe_malloc(num * sizeof (*i));
224 int n = XPLMGetDatavi(dr->dr, num > 0 ? i : NULL, off, num);
225 if (num != 0) {
226 for (int x = 0; x < n; x++)
227 df[x] = i[x];
228 }
229 free(i);
230 return (n);
231 }
232 if (dr->type & xplmType_FloatArray) {
233 float *f = safe_malloc(num * sizeof (*f));
234 int n = XPLMGetDatavf(dr->dr, num > 0 ? f : NULL, off, num);
235 if (num != 0) {
236 for (int x = 0; x < n; x++)
237 df[x] = f[x];
238 }
239 free(f);
240 return (n);
241 }
242 if (dr->type & xplmType_Data) {
243 uint8_t *u = safe_malloc(num * sizeof (*u));
244 int n = XPLMGetDatab(dr->dr, num > 0 ? u : NULL, off, num);
245 if (num != 0) {
246 for (int x = 0; x < n; x++)
247 df[x] = u[x];
248 }
249 free(u);
250 return (n);
251 }
252 ASSERT_MSG(off == 0, "Attempted read scalar dataref %s (type: %x) at "
253 "offset other than 0 (%d) (%s:%d: %s)", dr->name, dr->type, off,
254 filename, line, varname);
255 if (num != 0)
256 df[0] = dr_getf_impl(dr, filename, line, varname);
257 return (1);
258}
259
260int
261dr_getvf32_impl(const dr_t *dr, DR_DEBUG_VARS, float *ff, unsigned off,
262 unsigned num)
263{
264 ASSERT(ff != NULL || num == 0);
265
266 if (dr->type & xplmType_IntArray) {
267 int *i = safe_malloc(num * sizeof (*i));
268 int n = XPLMGetDatavi(dr->dr, num > 0 ? i : NULL, off, num);
269 if (num != 0) {
270 for (int x = 0; x < n; x++)
271 ff[x] = i[x];
272 }
273 free(i);
274 return (n);
275 }
276 if (dr->type & xplmType_FloatArray) {
277 int n = XPLMGetDatavf(dr->dr, ff, off, num);
278 return (n);
279 }
280 if (dr->type & xplmType_Data) {
281 uint8_t *u = safe_malloc(num * sizeof (*u));
282 int n = XPLMGetDatab(dr->dr, num > 0 ? u : NULL, off, num);
283 if (num != 0) {
284 for (int x = 0; x < n; x++)
285 ff[x] = u[x];
286 }
287 free(u);
288 return (n);
289 }
290 ASSERT_MSG(off == 0, "Attempted read scalar dataref %s (type: %x) at "
291 "offset other than 0 (%d) (%s:%d: %s)", dr->name, dr->type, off,
292 filename, line, varname);
293 if (num != 0)
294 ff[0] = dr_getf_impl(dr, filename, line, varname);
295 return (1);
296}
297
298void
299dr_setvf_impl(const dr_t *dr, DR_DEBUG_VARS, double *df, unsigned off,
300 unsigned num)
301{
302 ASSERT(df != NULL);
303 DR_WRITE_CHECK(VERIFY);
304 for (unsigned x = 0; x < num; x++) {
305 ASSERT_MSG(!isnan(df[x]), "%s[%d]", dr->name, x);
306 ASSERT_MSG(isfinite(df[x]), "%s[%d]", dr->name, x);
307 }
308 if (dr->type & xplmType_IntArray) {
309 int *i = safe_malloc(num * sizeof (*i));
310 for (unsigned x = 0; x < num; x++)
311 i[x] = df[x];
312 XPLMSetDatavi(dr->dr, i, off, num);
313 free(i);
314 } else if (dr->type & xplmType_FloatArray) {
315 float *f = safe_malloc(num * sizeof (*f));
316 for (unsigned x = 0; x < num; x++)
317 f[x] = df[x];
318 XPLMSetDatavf(dr->dr, f, off, num);
319 free(f);
320 } else if (dr->type & xplmType_Data) {
321 uint8_t *u = safe_malloc(num * sizeof (*u));
322 for (unsigned x = 0; x < num; x++)
323 u[x] = df[x];
324 XPLMSetDatab(dr->dr, u, off, num);
325 free(u);
326 } else {
327 ASSERT_MSG(off == 0, "Attempted write scalar dataref %s "
328 "(type: %x) at offset other than 0 (%d) (%s:%d: %s)",
329 dr->name, dr->type, off, filename, line, varname);
330 dr_setf_impl(dr, filename, line, varname, df[0]);
331 }
332}
333
334void
335dr_setvf32_impl(const dr_t *dr, DR_DEBUG_VARS, float *ff, unsigned off,
336 unsigned num)
337{
338 ASSERT(ff != NULL);
339 DR_WRITE_CHECK(VERIFY);
340 for (unsigned x = 0; x < num; x++) {
341 ASSERT_MSG(!isnan(ff[x]), "%s[%d]", dr->name, x);
342 ASSERT_MSG(isfinite(ff[x]), "%s[%d]", dr->name, x);
343 }
344 if (dr->type & xplmType_IntArray) {
345 int *i = safe_malloc(num * sizeof (*i));
346 for (unsigned x = 0; x < num; x++)
347 i[x] = ff[x];
348 XPLMSetDatavi(dr->dr, i, off, num);
349 free(i);
350 } else if (dr->type & xplmType_FloatArray) {
351 XPLMSetDatavf(dr->dr, ff, off, num);
352 } else if (dr->type & xplmType_Data) {
353 uint8_t *u = safe_malloc(num * sizeof (*u));
354 for (unsigned x = 0; x < num; x++)
355 u[x] = ff[x];
356 XPLMSetDatab(dr->dr, u, off, num);
357 free(u);
358 } else {
359 ASSERT_MSG(off == 0, "Attempted write scalar dataref %s "
360 "(type: %x) at offset other than 0 (%d) (%s:%d: %s)",
361 dr->name, dr->type, off, filename, line, varname);
362 dr_setf_impl(dr, filename, line, varname, ff[0]);
363 }
364}
365
366int
367dr_gets_impl(const dr_t *dr, DR_DEBUG_VARS, char *str, size_t cap)
368{
369 int n;
370
371 DR_TYPE_CHECK(VERIFY, xplmType_Data);
372 n = XPLMGetDatab(dr->dr, str, 0, cap > 0 ? cap - 1 : 0);
373 if (cap != 0)
374 str[n] = '\0'; /* make sure it's properly terminated */
375
376 return (n);
377}
378
379void
380dr_sets_impl(const dr_t *dr, DR_DEBUG_VARS, char *str)
381{
382 DR_TYPE_CHECK(VERIFY, xplmType_Data);
383 DR_WRITE_CHECK(VERIFY);
384 XPLMSetDatab(dr->dr, str, 0, strlen(str));
385}
386
387int
388dr_getbytes_impl(const dr_t *dr, DR_DEBUG_VARS, void *data, unsigned off,
389 unsigned num)
390{
391 DR_TYPE_CHECK(VERIFY, xplmType_Data);
392 return (XPLMGetDatab(dr->dr, data, off, num));
393}
394
395void
396dr_setbytes_impl(const dr_t *dr, DR_DEBUG_VARS, void *data, unsigned off,
397 unsigned num)
398{
399 DR_TYPE_CHECK(VERIFY, xplmType_Data);
400 DR_WRITE_CHECK(VERIFY);
401 XPLMSetDatab(dr->dr, data, off, num);
402}
403
404static int
405read_int_cb(void *refcon)
406{
407 dr_t *dr = refcon;
408 int value;
409 ASSERT(dr != NULL);
410 ASSERT_MSG(dr->type & xplmType_Int, "%s", dr->name);
411 if (dr->read_scalar_cb != NULL && dr->read_scalar_cb(dr, &value))
412 return (value);
413 ASSERT_MSG(dr->value != NULL, "%s", dr->name);
414 value = *(int *)dr->value;
415 if (dr->read_cb != NULL)
416 dr->read_cb(dr, &value);
417 return (value);
418}
419
420static void
421write_int_cb(void *refcon, int value)
422{
423 dr_t *dr = refcon;
424 ASSERT(dr != NULL);
425 ASSERT_MSG(dr->type & xplmType_Int, "%s", dr->name);
426 ASSERT_MSG(dr->writable, "%s", dr->name);
427 if (dr->write_scalar_cb != NULL && dr->write_scalar_cb(dr, &value))
428 return;
429 ASSERT_MSG(dr->value != NULL, "%s", dr->name);
430 if (dr->write_cb != NULL)
431 dr->write_cb(dr, &value);
432 *(int *)dr->value = value;
433}
434
435static float
436read_float_cb(void *refcon)
437{
438 dr_t *dr = refcon;
439 ASSERT(dr != NULL);
440 ASSERT_MSG(dr->type & xplmType_Float, "%s", dr->name);
441 if (dr->wide_type) {
442 double value;
443 if (dr->read_scalar_cb != NULL &&
444 dr->read_scalar_cb(dr, &value)) {
445 return (value);
446 }
447 ASSERT_MSG(dr->value != NULL, "%s", dr->name);
448 value = *(double *)dr->value;
449 if (dr->read_cb != NULL)
450 dr->read_cb(dr, &value);
451 return (value);
452 } else {
453 float value;
454 if (dr->read_scalar_cb != NULL &&
455 dr->read_scalar_cb(dr, &value)) {
456 return (value);
457 }
458 ASSERT_MSG(dr->value != NULL, "%s", dr->name);
459 value = *(float *)dr->value;
460 if (dr->read_cb != NULL)
461 dr->read_cb(dr, &value);
462 return (value);
463 }
464}
465
466static void
467write_float_cb(void *refcon, float value)
468{
469 dr_t *dr = refcon;
470 ASSERT(dr != NULL);
471 ASSERT_MSG(dr->type & xplmType_Float, "%s", dr->name);
472 ASSERT_MSG(dr->writable, "%s", dr->name);
473 if (dr->write_scalar_cb != NULL && dr->write_scalar_cb(dr, &value))
474 return;
475 ASSERT_MSG(dr->value != NULL, "%s", dr->name);
476 if (dr->write_cb != NULL)
477 dr->write_cb(dr, &value);
478 if (dr->wide_type)
479 *(double *)dr->value = value;
480 else
481 *(float *)dr->value = value;
482}
483
484#define DEF_READ_ARRAY_CB(typename, xp_typename, type_sz) \
485static int \
486read_ ## typename ## _array_cb(void *refcon, typename *out_values, int off, \
487 int count) \
488{ \
489 dr_t *dr = refcon; \
490 \
491 ASSERT(dr != NULL); \
492 ASSERT_MSG(dr->type & xplmType_ ## xp_typename, "%s", dr->name); \
493 \
494 if (dr->read_array_cb != NULL) { \
495 int ret = dr->read_array_cb(dr, out_values, off, count); \
496 if (ret >= 0) \
497 return (ret); \
498 } \
499 ASSERT_MSG(dr->value != NULL, "%s", dr->name); \
500 if (out_values == NULL) \
501 return (dr->count); \
502 if (off < dr->count) { \
503 count = MIN(count, dr->count - off); \
504 if (dr->stride == 0) { \
505 memcpy(out_values, dr->value + (off * type_sz), \
506 type_sz * count); \
507 } else { \
508 for (int i = 0; i < count; i++) { \
509 memcpy((void *)out_values + (i * type_sz), \
510 dr->value + ((off + i) * dr->stride), \
511 type_sz); \
512 } \
513 } \
514 } else { \
515 return (0); \
516 } \
517 \
518 return (count); \
519}
520
521#define DEF_WRITE_ARRAY_CB(typename, xp_typename, type_sz) \
522static void \
523write_ ## typename ## _array_cb(void *refcon, typename *in_values, int off, \
524 int count) \
525{ \
526 dr_t *dr = refcon; \
527 \
528 ASSERT(dr != NULL); \
529 ASSERT_MSG(dr->type & xplmType_ ## xp_typename, "%s", dr->name); \
530 ASSERT_MSG(dr->writable, "%s", dr->name); \
531 ASSERT_MSG(in_values != NULL || count == 0, "%s", dr->name); \
532 \
533 if (dr->write_array_cb != NULL) { \
534 dr->write_array_cb(dr, in_values, off, count); \
535 return; \
536 } \
537 ASSERT_MSG(dr->value != NULL, "%s", dr->name); \
538 if (off < dr->count) { \
539 count = MIN(count, dr->count - off); \
540 if (dr->stride == 0) { \
541 memcpy(dr->value + (off * type_sz), in_values, \
542 type_sz * count); \
543 } else { \
544 for (int i = 0; i < count; i++) { \
545 memcpy(dr->value + ((off + i) * dr->stride), \
546 ((void *)in_values) + (i * type_sz), \
547 type_sz); \
548 } \
549 } \
550 } \
551}
552
553DEF_READ_ARRAY_CB(int, IntArray, sizeof (int))
554DEF_WRITE_ARRAY_CB(int, IntArray, sizeof (int))
555DEF_READ_ARRAY_CB(float, FloatArray, sizeof (float))
556DEF_WRITE_ARRAY_CB(float, FloatArray, sizeof (float))
557DEF_READ_ARRAY_CB(void, Data, sizeof (uint8_t))
558DEF_WRITE_ARRAY_CB(void, Data, sizeof (uint8_t))
559
560#undef DEF_READ_ARRAY_CB
561#undef DEF_WRITE_ARRAY_CB
562
563/*
564 * For double arrays we can't use the normal array read/write callbacks,
565 * because those use memcpy when stride == 0. For double arrays, we need
566 * to convert each value as it enters/exits our interface.
567 */
568static int
569read_double_array_cb(void *refcon, float *out_values, int off, int count)
570{
571 dr_t *dr = refcon;
572
573 ASSERT(dr != NULL);
574 ASSERT_MSG(dr->type & xplmType_FloatArray, "%s", dr->name);
575
576 if (dr->read_array_cb != NULL) {
577 int ret = dr->read_array_cb(dr, out_values, off, count);
578 if (ret >= 0)
579 return (ret);
580 }
581 ASSERT_MSG(dr->value != NULL, "%s", dr->name);
582 if (out_values == NULL)
583 return (dr->count);
584 if (off < dr->count) {
585 size_t stride =
586 (dr->stride != 0 ? dr->stride : sizeof (double));
587 count = MIN(count, dr->count - off);
588 for (int i = 0; i < count; i++) {
589 out_values[i] =
590 *(double *)(dr->value + ((off + i) * stride));
591 }
592 } else {
593 return (0);
594 }
595
596 return (count);
597}
598
599static void
600write_double_array_cb(void *refcon, float *in_values, int off, int count)
601{
602 dr_t *dr = refcon;
603
604 ASSERT(dr != NULL);
605 ASSERT_MSG(dr->type & xplmType_FloatArray, "%s", dr->name);
606 ASSERT_MSG(dr->writable, "%s", dr->name);
607 ASSERT_MSG(in_values != NULL || count == 0, "%s", dr->name);
608
609 if (dr->write_array_cb != NULL) {
610 dr->write_array_cb(dr, in_values, off, count);
611 return;
612 }
613 ASSERT_MSG(dr->value != NULL, "%s", dr->name);
614 if (off < dr->count) {
615 size_t stride =
616 (dr->stride != 0 ? dr->stride : sizeof (double));
617 count = MIN(count, dr->count - off);
618 for (int i = 0; i < count; i++) {
619 *(double *)(dr->value + ((off + i) * stride)) =
620 in_values[i];
621 }
622 }
623}
624
625void
626dr_array_set_stride(dr_t *dr, size_t stride)
627{
628 ASSERT(dr != NULL);
629 dr->stride = stride;
630}
631
632static void
633dr_create_common(dr_t *dr, XPLMDataTypeID type, void *value,
634 dr_cfg_t cfg, bool_t wide_type, const char *fmt, va_list ap)
635{
636 ASSERT(dr != NULL);
637 /*
638 * value can be NULL - the caller might be using callbacks to
639 * override value access.
640 */
641 ASSERT(fmt != NULL);
642
643 memset(dr, 0, sizeof (*dr));
644
645 vsnprintf(dr->name, sizeof (dr->name), fmt, ap);
646
647 dr->dr = XPLMRegisterDataAccessor(dr->name, type, cfg.writable,
648 read_int_cb, write_int_cb, read_float_cb, write_float_cb,
649 NULL, NULL, read_int_array_cb, write_int_array_cb,
650 wide_type ? read_double_array_cb : read_float_array_cb,
651 wide_type ? write_double_array_cb : write_float_array_cb,
652 read_void_array_cb, write_void_array_cb, dr, dr);
653
654 VERIFY(dr->dr != NULL);
655 dr->type = type;
656 dr->writable = cfg.writable;
657 dr->value = value;
658 dr->count = cfg.count;
659 dr->stride = cfg.stride;
660 dr->read_cb = cfg.read_cb;
661 dr->write_cb = cfg.write_cb;
662 dr->read_scalar_cb = cfg.read_scalar_cb;
663 dr->write_scalar_cb = cfg.write_scalar_cb;
664 dr->read_array_cb = cfg.read_array_cb;
665 dr->write_array_cb = cfg.write_array_cb;
666 dr->cb_userinfo = cfg.cb_userinfo;
667 dr->wide_type = wide_type;
668
669 if (!dre_plug_lookup_done) {
670 dre_plug = XPLMFindPluginBySignature(
671 "xplanesdk.examples.DataRefEditor");
672 drt_plug = XPLMFindPluginBySignature(
673 "com.leecbaker.datareftool");
674 dre_plug_lookup_done = B_TRUE;
675 }
676 if (dre_plug != XPLM_NO_PLUGIN_ID) {
677 XPLMSendMessageToPlugin(dre_plug, DRE_MSG_ADD_DATAREF,
678 (void*)dr->name);
679 }
680 if (drt_plug != XPLM_NO_PLUGIN_ID) {
681 XPLMSendMessageToPlugin(drt_plug, DRE_MSG_ADD_DATAREF,
682 (void*)dr->name);
683 }
684}
685
686/*
687 * Sets up an integer dataref that will read and optionally write to
688 * an int*.
689 */
690void
691dr_create_i(dr_t *dr, int *value, bool_t writable, const char *fmt, ...)
692{
693 ASSERT(dr != NULL);
694 ASSERT(fmt != NULL);
695 va_list ap;
696 va_start(ap, fmt);
697 dr_create_common(dr, xplmType_Int, value,
698 (dr_cfg_t){ .count = 1, .writable = writable }, B_FALSE, fmt, ap);
699 va_end(ap);
700}
701
702void
703dr_create_i_cfg(dr_t *dr, int *value, dr_cfg_t cfg, const char *fmt, ...)
704{
705 ASSERT(dr != NULL);
706 ASSERT(fmt != NULL);
707 va_list ap;
708 va_start(ap, fmt);
709 dr_create_common(dr, xplmType_Int, value, cfg, B_FALSE, fmt, ap);
710 va_end(ap);
711}
712
713/*
714 * Sets up a float dataref that will read and optionally write to
715 * a float*.
716 */
717void
718dr_create_f(dr_t *dr, float *value, bool_t writable, const char *fmt, ...)
719{
720 ASSERT(dr != NULL);
721 ASSERT(fmt != NULL);
722 va_list ap;
723 va_start(ap, fmt);
724 dr_create_common(dr, xplmType_Float, value,
725 (dr_cfg_t){ .count = 1, .writable = writable }, B_FALSE, fmt, ap);
726 va_end(ap);
727}
728
729void
730dr_create_f_cfg(dr_t *dr, float *value, dr_cfg_t cfg, const char *fmt, ...)
731{
732 ASSERT(dr != NULL);
733 ASSERT(fmt != NULL);
734 va_list ap;
735 va_start(ap, fmt);
736 dr_create_common(dr, xplmType_Float, value, cfg, B_FALSE, fmt, ap);
737 va_end(ap);
738}
739
740/*
741 * Sets up a float dataref that will read and optionally write to
742 * a double*.
743 */
744void
745dr_create_f64(dr_t *dr, double *value, bool_t writable, const char *fmt, ...)
746{
747 ASSERT(dr != NULL);
748 ASSERT(fmt != NULL);
749 va_list ap;
750 va_start(ap, fmt);
751 dr_create_common(dr, xplmType_Float, value,
752 (dr_cfg_t){ .count = 1, .writable = writable }, B_TRUE, fmt, ap);
753 va_end(ap);
754}
755
756void
757dr_create_f64_cfg(dr_t *dr, double *value, dr_cfg_t cfg, const char *fmt, ...)
758{
759 ASSERT(dr != NULL);
760 ASSERT(fmt != NULL);
761 va_list ap;
762 va_start(ap, fmt);
763 dr_create_common(dr, xplmType_Float, value, cfg, B_TRUE, fmt, ap);
764 va_end(ap);
765}
766
767void
768dr_create_vi(dr_t *dr, int *value, size_t n, bool_t writable,
769 const char *fmt, ...)
770{
771 ASSERT(dr != NULL);
772 ASSERT(fmt != NULL);
773 va_list ap;
774 va_start(ap, fmt);
775 dr_create_common(dr, xplmType_IntArray, value,
776 (dr_cfg_t){ .count = n, .writable = writable }, B_FALSE, fmt, ap);
777 va_end(ap);
778}
779
780void
781dr_create_vi_cfg(dr_t *dr, int *value, dr_cfg_t cfg, const char *fmt, ...)
782{
783 ASSERT(dr != NULL);
784 ASSERT(fmt != NULL);
785 va_list ap;
786 va_start(ap, fmt);
787 dr_create_common(dr, xplmType_IntArray, value,
788 cfg, B_FALSE, fmt, ap);
789 va_end(ap);
790}
791
792void
793dr_create_vf(dr_t *dr, float *value, size_t n, bool_t writable,
794 const char *fmt, ...)
795{
796 ASSERT(dr != NULL);
797 ASSERT(fmt != NULL);
798 va_list ap;
799 va_start(ap, fmt);
800 dr_create_common(dr, xplmType_FloatArray, value,
801 (dr_cfg_t){ .count = n, .writable = writable }, B_FALSE, fmt, ap);
802 va_end(ap);
803}
804
805void
806dr_create_vf_cfg(dr_t *dr, float *value, dr_cfg_t cfg, const char *fmt, ...)
807{
808 ASSERT(dr != NULL);
809 ASSERT(fmt != NULL);
810 va_list ap;
811 va_start(ap, fmt);
812 dr_create_common(dr, xplmType_FloatArray, value, cfg, B_FALSE, fmt, ap);
813 va_end(ap);
814}
815
816void
817dr_create_vf64(dr_t *dr, double *value, size_t n, bool_t writable,
818 const char *fmt, ...)
819{
820 ASSERT(dr != NULL);
821 ASSERT(fmt != NULL);
822 va_list ap;
823 va_start(ap, fmt);
824 dr_create_common(dr, xplmType_FloatArray, value,
825 (dr_cfg_t){ .count = n, .writable = writable }, B_TRUE, fmt, ap);
826 va_end(ap);
827}
828
829void
830dr_create_vf64_cfg(dr_t *dr, double *value, dr_cfg_t cfg, const char *fmt, ...)
831{
832 ASSERT(dr != NULL);
833 ASSERT(fmt != NULL);
834 va_list ap;
835 va_start(ap, fmt);
836 dr_create_common(dr, xplmType_FloatArray, value, cfg, B_TRUE, fmt, ap);
837 va_end(ap);
838}
839
840void
841dr_create_vi_autoscalar(dr_t *dr, int *value, size_t n, bool_t writable,
842 const char *fmt, ...)
843{
844 ASSERT(dr != NULL);
845 ASSERT(fmt != NULL);
846 va_list ap;
847 va_start(ap, fmt);
848 dr_create_common(dr, xplmType_Int | xplmType_IntArray, value,
849 (dr_cfg_t){ .count = n, .writable = writable }, B_FALSE, fmt, ap);
850 va_end(ap);
851}
852
853void
854dr_create_vi_autoscalar_cfg(dr_t *dr, int *value, dr_cfg_t cfg,
855 const char *fmt, ...)
856{
857 ASSERT(dr != NULL);
858 ASSERT(fmt != NULL);
859 va_list ap;
860 va_start(ap, fmt);
861 dr_create_common(dr, xplmType_Int | xplmType_IntArray, value,
862 cfg, B_FALSE, fmt, ap);
863 va_end(ap);
864}
865
866void
867dr_create_vf_autoscalar(dr_t *dr, float *value, size_t n, bool_t writable,
868 const char *fmt, ...)
869{
870 ASSERT(dr != NULL);
871 ASSERT(fmt != NULL);
872 va_list ap;
873 va_start(ap, fmt);
874 dr_create_common(dr, xplmType_Float | xplmType_FloatArray, value,
875 (dr_cfg_t){ .count = n, .writable = writable }, B_FALSE, fmt, ap);
876 va_end(ap);
877}
878
879void
880dr_create_vf_autoscalar_cfg(dr_t *dr, float *value, dr_cfg_t cfg,
881 const char *fmt, ...)
882{
883 ASSERT(dr != NULL);
884 ASSERT(fmt != NULL);
885 va_list ap;
886 va_start(ap, fmt);
887 dr_create_common(dr, xplmType_Float | xplmType_FloatArray, value,
888 cfg, B_FALSE, fmt, ap);
889 va_end(ap);
890}
891
892void
893dr_create_vf64_autoscalar(dr_t *dr, double *value, size_t n, bool_t writable,
894 const char *fmt, ...)
895{
896 ASSERT(dr != NULL);
897 ASSERT(fmt != NULL);
898 va_list ap;
899 va_start(ap, fmt);
900 dr_create_common(dr, xplmType_Double | xplmType_FloatArray, value,
901 (dr_cfg_t){ .count = n, .writable = writable }, B_TRUE, fmt, ap);
902 va_end(ap);
903}
904
905void
906dr_create_vf64_autoscalar_cfg(dr_t *dr, double *value, dr_cfg_t cfg,
907 const char *fmt, ...)
908{
909 ASSERT(dr != NULL);
910 ASSERT(fmt != NULL);
911 va_list ap;
912 va_start(ap, fmt);
913 dr_create_common(dr, xplmType_Double | xplmType_FloatArray, value,
914 cfg, B_TRUE, fmt, ap);
915 va_end(ap);
916}
917
918void
919dr_create_b(dr_t *dr, void *value, size_t n, bool_t writable,
920 const char *fmt, ...)
921{
922 ASSERT(dr != NULL);
923 ASSERT(fmt != NULL);
924 va_list ap;
925 va_start(ap, fmt);
926 dr_create_common(dr, xplmType_Data, value,
927 (dr_cfg_t){ .count = n, .writable = writable }, B_FALSE, fmt, ap);
928 va_end(ap);
929}
930
931void
932dr_create_b_cfg(dr_t *dr, void *value, dr_cfg_t cfg, const char *fmt, ...)
933{
934 ASSERT(dr != NULL);
935 ASSERT(fmt != NULL);
936 va_list ap;
937 va_start(ap, fmt);
938 dr_create_common(dr, xplmType_Data, value, cfg, B_FALSE, fmt, ap);
939 va_end(ap);
940}
941
942/*
943 * Destroys a dataref previously set up using dr_intf_add_{i,f}.
944 */
945void
946dr_delete(dr_t *dr)
947{
948 if (dr->dr != NULL) {
949 XPLMUnregisterDataAccessor(dr->dr);
950 memset(dr, 0, sizeof (*dr));
951 }
952}
953
954void *
956{
957 return (dr->cb_userinfo);
958}
#define ASSERT_MSG(x, fmt,...)
Definition assert.h:214
#define VERIFY(x)
Definition assert.h:78
#define ASSERT(x)
Definition assert.h:208
#define VERIFY3S(x, op, y)
Definition assert.h:125
#define VERIFY_MSG(x, fmt,...)
Definition assert.h:91
#define VERIFY3U(x, op, y)
Definition assert.h:136
double dr_getf_impl(const dr_t *dr, const char *filename, int line, const char *varname)
Definition dr.c:113
void dr_setf_impl(const dr_t *dr, const char *filename, int line, const char *varname, double f)
Definition dr.c:133
void dr_array_set_stride(dr_t *dr, size_t stride)
Definition dr.c:626
void dr_create_vf_autoscalar_cfg(dr_t *dr, float *value, dr_cfg_t cfg, const char *fmt,...)
Definition dr.c:880
void dr_create_f_cfg(dr_t *dr, float *value, dr_cfg_t cfg, const char *fmt,...)
Definition dr.c:730
int dr_getvi_impl(const dr_t *dr, const char *filename, int line, const char *varname, int *i, unsigned off, unsigned num)
Definition dr.c:155
void dr_setvi_impl(const dr_t *dr, const char *filename, int line, const char *varname, int *i, unsigned off, unsigned num)
Definition dr.c:190
void dr_setvf_impl(const dr_t *dr, const char *filename, int line, const char *varname, double *df, unsigned off, unsigned num)
Definition dr.c:299
void dr_create_i_cfg(dr_t *dr, int *value, dr_cfg_t cfg, const char *fmt,...)
Definition dr.c:703
void dr_setvf32_impl(const dr_t *dr, const char *filename, int line, const char *varname, float *ff, unsigned off, unsigned num)
Definition dr.c:335
void dr_create_i(dr_t *dr, int *value, bool_t writable, const char *fmt,...)
Definition dr.c:691
void dr_seti_impl(const dr_t *dr, const char *filename, int line, const char *varname, int i)
Definition dr.c:94
void dr_create_vf(dr_t *dr, float *value, size_t n, bool_t writable, const char *fmt,...)
Definition dr.c:793
void dr_create_f64_cfg(dr_t *dr, double *value, dr_cfg_t cfg, const char *fmt,...)
Definition dr.c:757
void dr_create_f(dr_t *dr, float *value, bool_t writable, const char *fmt,...)
Definition dr.c:718
void dr_create_vf64_autoscalar(dr_t *dr, double *value, size_t n, bool_t writable, const char *fmt,...)
Definition dr.c:893
void dr_create_vf64_cfg(dr_t *dr, double *value, dr_cfg_t cfg, const char *fmt,...)
Definition dr.c:830
void dr_create_b_cfg(dr_t *dr, void *value, dr_cfg_t cfg, const char *fmt,...)
Definition dr.c:932
bool_t dr_find(dr_t *dr, const char *fmt,...)
Definition dr.c:44
void dr_create_vf_autoscalar(dr_t *dr, float *value, size_t n, bool_t writable, const char *fmt,...)
Definition dr.c:867
void dr_create_f64(dr_t *dr, double *value, bool_t writable, const char *fmt,...)
Definition dr.c:745
int dr_geti_impl(const dr_t *dr, const char *filename, int line, const char *varname)
Definition dr.c:74
void dr_create_b(dr_t *dr, void *value, size_t n, bool_t writable, const char *fmt,...)
Definition dr.c:919
void dr_create_vf64_autoscalar_cfg(dr_t *dr, double *value, dr_cfg_t cfg, const char *fmt,...)
Definition dr.c:906
void dr_create_vi_cfg(dr_t *dr, int *value, dr_cfg_t cfg, const char *fmt,...)
Definition dr.c:781
void dr_create_vi_autoscalar(dr_t *dr, int *value, size_t n, bool_t writable, const char *fmt,...)
Definition dr.c:841
void dr_delete(dr_t *dr)
Definition dr.c:946
void dr_create_vi(dr_t *dr, int *value, size_t n, bool_t writable, const char *fmt,...)
Definition dr.c:768
void dr_sets_impl(const dr_t *dr, const char *filename, int line, const char *varname, char *str)
Definition dr.c:380
void dr_setbytes_impl(const dr_t *dr, const char *filename, int line, const char *varname, void *data, unsigned off, unsigned num)
Definition dr.c:396
void dr_create_vi_autoscalar_cfg(dr_t *dr, int *value, dr_cfg_t cfg, const char *fmt,...)
Definition dr.c:854
int dr_getbytes_impl(const dr_t *dr, const char *filename, int line, const char *varname, void *data, unsigned off, unsigned num)
Definition dr.c:388
void dr_create_vf64(dr_t *dr, double *value, size_t n, bool_t writable, const char *fmt,...)
Definition dr.c:817
void dr_create_vf_cfg(dr_t *dr, float *value, dr_cfg_t cfg, const char *fmt,...)
Definition dr.c:806
int dr_getvf_impl(const dr_t *dr, const char *filename, int line, const char *varname, double *df, unsigned off, unsigned num)
Definition dr.c:217
void * dr_get_cb_userinfo(const dr_t *dr)
Definition dr.c:955
int dr_gets_impl(const dr_t *dr, const char *filename, int line, const char *varname, char *str, size_t cap)
Definition dr.c:367
int dr_getvf32_impl(const dr_t *dr, const char *filename, int line, const char *varname, float *ff, unsigned off, unsigned num)
Definition dr.c:261
bool_t dr_writable(dr_t *dr)
Definition dr.c:68
static void * safe_malloc(size_t size)
Definition safe_alloc.h:56
Definition dr.h:177
bool writable
Defines whether this dataref will be writable or read-only.
Definition dr.h:179
void * cb_userinfo
Definition dr.h:291
size_t stride
Definition dr.h:215
int(* read_array_cb)(dr_t *dr, void *values_out, int off, int cnt)
Definition dr.h:278
size_t count
Definition dr.h:182
void(* write_cb)(dr_t *dr, void *value_in)
Definition dr.h:244
bool_t(* write_scalar_cb)(dr_t *dr, void *value_in)
Definition dr.h:272
bool_t(* read_scalar_cb)(dr_t *dr, void *value_out)
Definition dr.h:261
void(* write_array_cb)(dr_t *dr, void *values_in, int off, int cnt)
Definition dr.h:285
void(* read_cb)(dr_t *dr, void *value_out)
Definition dr.h:238
#define REQ_PTR(x)
Definition sysmacros.h:334