aboutsummaryrefslogtreecommitdiff
path: root/api/api_atom.h
blob: 7b6790d381a6ebea49d25d7e9950da68f9124db4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*
 * Copyright (c) 2015 Hanspeter Portner (dev@open-music-kontrollers.ch)
 *
 * This is free software: you can redistribute it and/or modify
 * it under the terms of the Artistic License 2.0 as published by
 * The Perl Foundation.
 *
 * This source is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * Artistic License 2.0 for more details.
 *
 * You should have received a copy of the Artistic License 2.0
 * along the source as a COPYING file. If not, obtain it from
 * http://www.perlfoundation.org/artistic_license_2_0.
 */

#ifndef _MOONY_API_ATOM_H
#define _MOONY_API_ATOM_H

#include <moony.h>

typedef struct _lseq_t lseq_t;
typedef struct _latom_t latom_t;
typedef struct _lobj_t lobj_t;
typedef struct _ltuple_t ltuple_t;
typedef struct _lvec_t lvec_t;

typedef int (*latom_driver_function_t)(lua_State *L, latom_t *latom);
typedef int (*latom_driver_function_indexk_t)(lua_State *L, latom_t *latom, const char *key);

struct _latom_driver_t {
	latom_driver_function_t __indexi;
	latom_driver_function_indexk_t __indexk;
	latom_driver_function_t __len;
	latom_driver_function_t __tostring;
	latom_driver_function_t __call;

	latom_driver_function_t value;
	lua_CFunction unpack;
	lua_CFunction foreach;
};

struct _latom_t {
	lheader_t lheader;

	const LV2_Atom *atom;

	union {
		const void *raw;

		const int32_t *i32;
		const int64_t *i64;
		const float *f32;
		const double *f64;
		const uint32_t *u32;
		const char *str;
		const LV2_Atom_Literal_Body *lit;

		const LV2_Atom_Sequence_Body *seq;
		const LV2_Atom_Object_Body *obj;
		const LV2_Atom *tuple;
		const LV2_Atom_Vector_Body *vec;
	} body;

	union {
		struct _lseq_t {
			const LV2_Atom_Event *ev;
		} seq;

		struct _lobj_t {
			const LV2_Atom_Property_Body *prop;
		} obj;

		struct _ltuple_t {
			int pos;
			const LV2_Atom *item;
		} tuple;

		struct _lvec_t {
			int count;
			int pos;
		} vec;
	} iter;

	LV2_Atom payload [0];
};

// in api_atom.c
extern const latom_driver_t latom_nil_driver;
extern const latom_driver_t latom_bool_driver;
extern const latom_driver_t latom_int_driver;
extern const latom_driver_t latom_long_driver;
extern const latom_driver_t latom_float_driver;
extern const latom_driver_t latom_double_driver;
extern const latom_driver_t latom_urid_driver;
extern const latom_driver_t latom_string_driver;
extern const latom_driver_t latom_literal_driver;
extern const latom_driver_t latom_tuple_driver;
extern const latom_driver_t latom_object_driver;
extern const latom_driver_t latom_vector_driver;
extern const latom_driver_t latom_sequence_driver;
extern const latom_driver_t latom_chunk_driver;

extern const luaL_Reg latom_mt [];

extern const lua_CFunction upclosures [];

int
_latom_clone(lua_State *L);

int
_latom_literal_unpack(lua_State *L);
int
_latom_tuple_unpack(lua_State *L);
int
_latom_vec_unpack(lua_State *L);
int
_latom_chunk_unpack(lua_State *L);

int
_latom_tuple_foreach(lua_State *L);
int
_latom_obj_foreach(lua_State *L);
int
_latom_seq_foreach(lua_State *L);
int
_latom_vec_foreach(lua_State *L);

int
_latom_tuple_foreach_itr(lua_State *L);
int
_latom_obj_foreach_itr(lua_State *L);
int
_latom_seq_foreach_itr(lua_State *L);
int
_latom_vec_foreach_itr(lua_State *L);

int
_latom_seq_multiplex_itr(lua_State *L);

__realtime static inline latom_t *
_latom_body_new(lua_State *L, const LV2_Atom *atom, const void *body, bool cache)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));

	latom_t *latom = moony_newuserdata(L, moony, MOONY_UDATA_ATOM, cache);
	if(atom)
	{
		latom->atom = atom;
		latom->body.raw = body;
	}

	return latom;
}

__realtime static inline latom_t *
_latom_new(lua_State *L, const LV2_Atom *atom, bool cache)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));

	latom_t *latom = moony_newuserdata(L, moony, MOONY_UDATA_ATOM, cache);
	if(atom)
	{
		latom->atom = atom;
		latom->body.raw = LV2_ATOM_BODY_CONST(atom);
	}

	return latom;
}

__realtime static inline const latom_driver_t *
_latom_driver(moony_t *moony, LV2_URID type)
{
	const latom_driver_hash_t *base = moony->atom_driver_hash;

	for(unsigned N = DRIVER_HASH_MAX, half; N > 1; N -= half)
	{
		half = N/2;
		const latom_driver_hash_t *dst = &base[half];
		base = (dst->type > type) ? base : dst;
	}

	return (base->type == type) ? base->driver : &latom_chunk_driver;
}

__realtime static void
_latom_value(lua_State *L, const LV2_Atom *atom)
{
	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
	const latom_driver_t *driver = _latom_driver(moony, atom->type);

	// dummy wrapping
	latom_t latom = {
		.atom = atom,
		.body.raw = LV2_ATOM_BODY_CONST(atom),
	};

	if(driver && driver->value)
		driver->value(L, &latom);
	else
		lua_pushnil(L); // unknown type
}

#endif