1 /*
2 * Copyright (c) 2017 Hanspeter Portner (dev@open-music-kontrollers.ch)
3 *
4 * This is free software: you can redistribute it and/or modify
5 * it under the terms of the Artistic License 2.0 as published by
6 * The Perl Foundation.
7 *
8 * This source is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * Artistic License 2.0 for more details.
12 *
13 * You should have received a copy of the Artistic License 2.0
14 * along the source as a COPYING file. If not, obtain it from
15 * http://www.perlfoundation.org/artistic_license_2_0.
16 */
17
18 #include <time.h>
19 #include <sratom/sratom.h>
20
21 #define NETATOM_IMPLEMENTATION
22 #include <netatom.lv2/netatom.h>
23
24 #define MAX_URIDS 2048
25 #define MAX_BUF 4092
26
27 typedef struct _urid_t urid_t;
28 typedef struct _store_t store_t;
29
30 struct _urid_t {
31 LV2_URID urid;
32 char *uri;
33 };
34
35 struct _store_t {
36 urid_t urids [MAX_URIDS];
37 LV2_URID urid;
38 };
39
40 static LV2_URID
_map(LV2_URID_Map_Handle instance,const char * uri)41 _map(LV2_URID_Map_Handle instance, const char *uri)
42 {
43 store_t *handle = instance;
44
45 urid_t *itm;
46 for(itm=handle->urids; itm->urid; itm++)
47 {
48 if(!strcmp(itm->uri, uri))
49 return itm->urid;
50 }
51
52 assert(handle->urid + 1 < MAX_URIDS);
53
54 // create new
55 itm->urid = ++handle->urid;
56 itm->uri = strdup(uri);
57
58 return itm->urid;
59 }
60
61 static const char *
_unmap(LV2_URID_Unmap_Handle instance,LV2_URID urid)62 _unmap(LV2_URID_Unmap_Handle instance, LV2_URID urid)
63 {
64 store_t *handle = instance;
65
66 for(urid_t *itm=handle->urids; itm->urid; itm++)
67 {
68 if(itm->urid == urid)
69 return itm->uri;
70 }
71
72 // not found
73 return NULL;
74 }
75
76 static void
_freemap(store_t * handle)77 _freemap(store_t *handle)
78 {
79 for(urid_t *itm = handle->urids; itm->urid; itm++)
80 free(itm->uri);
81 }
82
83 static void
_netatom_test(LV2_URID_Map * map,LV2_URID_Unmap * unmap,bool swap,const LV2_Atom * atom,unsigned iterations)84 _netatom_test(LV2_URID_Map *map, LV2_URID_Unmap *unmap, bool swap,
85 const LV2_Atom *atom, unsigned iterations)
86 {
87 static uint8_t buf [MAX_BUF];
88 netatom_t *netatom = netatom_new(map, unmap, swap);
89 assert(netatom);
90
91 for(unsigned i = 0; i < iterations; i++)
92 {
93 memcpy(buf, atom, lv2_atom_total_size(atom));
94
95 size_t size_tx = 0;
96 uint8_t *buf_tx = netatom_serialize(netatom, (LV2_Atom *)buf, MAX_BUF, &size_tx);
97 assert(buf_tx);
98
99 if(iterations == 1)
100 {
101 fwrite(buf_tx, size_tx, 1, stdout);
102
103 #if !defined(_WIN32)
104 const size_t tot_size = lv2_atom_total_size(atom);
105 fprintf(stderr, "%zu, %zu, %lf\n", tot_size, size_tx,
106 (double)size_tx / lv2_atom_total_size(atom));
107 #endif
108 }
109
110 const LV2_Atom *atom_rx = netatom_deserialize(netatom, buf_tx, size_tx);
111 assert(atom_rx);
112
113 const uint32_t size_rx = lv2_atom_total_size(atom_rx);
114
115 assert(size_rx == lv2_atom_total_size(atom));
116 assert(memcmp(atom, atom_rx, size_rx) == 0);
117 }
118
119 netatom_free(netatom);
120 }
121
122 static void
_sratom_test(LV2_URID_Map * map,LV2_URID_Unmap * unmap,bool pretty,const LV2_Atom * atom,unsigned iterations)123 _sratom_test(LV2_URID_Map *map, LV2_URID_Unmap *unmap, bool pretty,
124 const LV2_Atom *atom, unsigned iterations)
125 {
126 Sratom *sratom = sratom_new(map);
127 assert(sratom);
128 sratom_set_pretty_numbers(sratom, pretty);
129 const char *base_uri = "file:///tmp/base";
130 const SerdNode subject = serd_node_from_string(SERD_URI, (const uint8_t *)(""));
131 const SerdNode predicate = serd_node_from_string(SERD_URI, (const uint8_t *)(LV2_ATOM__atomTransfer));
132
133 for(unsigned i = 0; i < iterations; i++)
134 {
135 char *ttl = sratom_to_turtle(sratom, unmap, base_uri, &subject, &predicate,
136 atom->type, atom->size, LV2_ATOM_BODY_CONST(atom));
137 assert(ttl);
138
139 LV2_Atom *clone = sratom_from_turtle(sratom, base_uri, &subject, &predicate, ttl);
140 assert(clone);
141
142 assert(atom->size == clone->size);
143 assert(atom->type == clone->type);
144 //assert(memcmp(LV2_ATOM_BODY_CONST(atom), LV2_ATOM_BODY_CONST(clone), atom->size) == 0);
145
146 free(clone);
147 free(ttl);
148 }
149
150 sratom_free(sratom);
151 }
152
153 #define MAP(O) map.map(map.handle, "urn:netatom:test#"O)
154
155 int
main(int argc,char ** argv)156 main(int argc, char **argv)
157 {
158 static store_t handle;
159
160 if(argc < 2)
161 return -1;
162 const unsigned iterations = atoi(argv[1]);
163
164 LV2_URID_Map map = {
165 .handle = &handle,
166 .map = _map
167 };
168
169 LV2_URID_Unmap unmap = {
170 .handle = &handle,
171 .unmap = _unmap
172 };
173
174 LV2_Atom_Forge forge;
175 lv2_atom_forge_init(&forge, &map);
176
177 union {
178 LV2_Atom atom;
179 uint8_t buf [2048];
180 } un;
181
182 lv2_atom_forge_set_buffer(&forge, un.buf, 2048);
183
184 LV2_Atom_Forge_Frame obj_frame;
185 lv2_atom_forge_object(&forge, &obj_frame, 0, MAP("otype"));
186 {
187 lv2_atom_forge_key(&forge, forge.Int);
188 lv2_atom_forge_int(&forge, 12);
189
190 lv2_atom_forge_key(&forge, forge.Bool);
191 lv2_atom_forge_bool(&forge, 1);
192
193 lv2_atom_forge_key(&forge, forge.Long);
194 lv2_atom_forge_long(&forge, 14);
195
196 lv2_atom_forge_key(&forge, forge.Float);
197 lv2_atom_forge_float(&forge, 1.5);
198
199 lv2_atom_forge_key(&forge, forge.Double);
200 lv2_atom_forge_double(&forge, 4.5);
201
202 lv2_atom_forge_key(&forge, forge.String);
203 lv2_atom_forge_string(&forge, "hello", 5);
204
205 lv2_atom_forge_key(&forge, forge.Path);
206 lv2_atom_forge_path(&forge, "/tmp", 4);
207
208 lv2_atom_forge_key(&forge, forge.Literal);
209 lv2_atom_forge_literal(&forge, "hello", 5, MAP("dtype"), MAP("lang"));
210
211 /*
212 lv2_atom_forge_key(&forge, forge.URI);
213 lv2_atom_forge_uri(&forge, LV2_URID__map, strlen(LV2_URID__map));
214 */
215
216 lv2_atom_forge_key(&forge, forge.URID);
217 lv2_atom_forge_urid(&forge, MAP("key"));
218
219 const uint8_t m [3] = {0x90, 0x2f, 0x7f};
220 lv2_atom_forge_key(&forge, map.map(map.handle, LV2_MIDI__MidiEvent));
221 lv2_atom_forge_atom(&forge, 3, map.map(map.handle, LV2_MIDI__MidiEvent));
222 lv2_atom_forge_write(&forge, m, 3);
223
224 const uint8_t b [8] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
225 lv2_atom_forge_key(&forge, forge.Chunk);
226 lv2_atom_forge_atom(&forge, 8, forge.Chunk);
227 lv2_atom_forge_write(&forge, b, 8);
228
229 LV2_Atom_Forge_Frame tup_frame;
230 lv2_atom_forge_key(&forge, forge.Tuple);
231 lv2_atom_forge_tuple(&forge, &tup_frame);
232 {
233 for(unsigned i = 0; i < 16; i++)
234 lv2_atom_forge_int(&forge, i);
235 }
236 lv2_atom_forge_pop(&forge, &tup_frame);
237
238 LV2_Atom_Forge_Frame vec_frame;
239 lv2_atom_forge_key(&forge, forge.Vector);
240 lv2_atom_forge_vector_head(&forge, &vec_frame, sizeof(int32_t), forge.Int);
241 {
242 for(unsigned i = 0; i < 16; i++)
243 lv2_atom_forge_int(&forge, i);
244 }
245 lv2_atom_forge_pop(&forge, &vec_frame);
246
247 LV2_Atom_Forge_Frame seq_frame;
248 lv2_atom_forge_key(&forge, forge.Sequence);
249 lv2_atom_forge_sequence_head(&forge, &seq_frame, MAP(LV2_ATOM__frameTime));
250 {
251 for(unsigned i = 0; i < 16; i++)
252 {
253 lv2_atom_forge_frame_time(&forge, i);
254 lv2_atom_forge_int(&forge, i);
255 }
256 }
257 lv2_atom_forge_pop(&forge, &seq_frame);
258 }
259 lv2_atom_forge_pop(&forge, &obj_frame);
260
261 // add some dummy URI to hash map
262 char tmp [32];
263 for(int i=0; i<1024; i++)
264 {
265 snprintf(tmp, 32, "urn:dummy:%i", i);
266 map.map(map.handle, tmp);
267 }
268
269 #if !defined(__APPLE__) && !defined(_WIN32)
270 struct timespec t0, t1, t2;
271 clock_gettime(CLOCK_MONOTONIC, &t0);
272 #endif
273 _netatom_test(&map, &unmap, true, &un.atom, iterations);
274 #if !defined(__APPLE__) && !defined(_WIN32)
275 clock_gettime(CLOCK_MONOTONIC, &t1);
276 #endif
277 _sratom_test(&map, &unmap, false, &un.atom, iterations);
278 #if !defined(__APPLE__) && !defined(_WIN32)
279 clock_gettime(CLOCK_MONOTONIC, &t2);
280
281 const double d1 = (t1.tv_sec - t0.tv_sec) + (t1.tv_nsec - t0.tv_nsec) * 1e-9;
282 const double d2 = (t2.tv_sec - t1.tv_sec) + (t2.tv_nsec - t1.tv_nsec) * 1e-9;
283 fprintf(stderr, "%lf s, %lf s, x %lf\n", d1, d2, d2/d1);
284 #endif
285
286 _freemap(&handle);
287
288 return 0;
289 }
290