1
2// TODO Experiment with versioning. This may be removed or changed dramatically.
3// Please ignore for now. Do not review.
4#define OBOE_VERSION_EXPERIMENT  0
5#if OBOE_VERSION_EXPERIMENT
6
7#define OBOE_EARLIEST_SUPPORTED_VERSION  1
8#define OBOE_CURRENT_VERSION  2
9
10typedef struct OboeInterface_s {
11    int32_t size; // do not use size_t because its size can vary
12    int32_t version;
13    int32_t reserved1;
14    void *  reserved2;
15    oboe_result_t (*createStreamBuilder)(OboeStreamBuilder *);
16} OboeInterface_t;
17
18OboeInterface_t s_oboe_template = {
19        .size = sizeof(OboeInterface_t),
20        .version = OBOE_CURRENT_VERSION,
21        .reserved1 = 0,
22        .reserved2 = NULL,
23        .createStreamBuilder = Oboe_createStreamBuilder
24};
25
26oboe_result_t Oboe_Unimplemented(OboeInterface_t *oboe) {
27    (void) oboe;
28    return OBOE_ERROR_UNIMPLEMENTED;
29}
30
31typedef oboe_result_t (*OboeFunction_t)(OboeInterface_t *oboe);
32
33int32_t Oboe_Initialize(OboeInterface_t *oboe, uint32_t flags) {
34    if (oboe->version < OBOE_EARLIEST_SUPPORTED_VERSION) {
35        return OBOE_ERROR_INCOMPATIBLE;
36    }
37    // Fill in callers vector table.
38    uint8_t *start = (uint8_t*)&oboe->reserved1;
39    uint8_t *end;
40    if (oboe->size <= s_oboe_template.size) {
41        end = ((uint8_t *)oboe) + oboe->size;
42    } else {
43        end = ((uint8_t *)oboe) + s_oboe_template.size;
44        // Assume the rest of the structure is vectors.
45        // Point them all to OboeInternal_Unimplemented()
46        // Point to first vector past end of the known structure.
47        OboeFunction_t *next = (OboeFunction_t*)end;
48        while ((((uint8_t *)next) - ((uint8_t *)oboe)) < oboe->size) {
49            *next++ = Oboe_Unimplemented;
50        }
51    }
52    memcpy(&oboe->reserved1, &s_oboe_template.reserved1, end - start);
53    return OBOE_OK;
54}
55#endif /* OBOE_VERSION_EXPERIMENT -------------------------- */
56